diff options
author | Karl Berry <karl@freefriends.org> | 2012-11-23 22:46:32 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2012-11-23 22:46:32 +0000 |
commit | 4472c1a09891d886ecdc6dd3fbfa39e66ef55ff7 (patch) | |
tree | 0235845fbcfde75dc2d3b817a8cf2a7a047e201c | |
parent | e59dc86d50620df70414da4bd434219b46137fc9 (diff) |
xecjk (23nov12)
git-svn-id: svn://tug.org/texlive/trunk@28348 c570f23f-e606-0410-a88d-b1316a301751
14 files changed, 4685 insertions, 3493 deletions
diff --git a/Master/texmf-dist/doc/xelatex/xecjk/README b/Master/texmf-dist/doc/xelatex/xecjk/README index 126933d2dfe..94a9f709aab 100644 --- a/Master/texmf-dist/doc/xelatex/xecjk/README +++ b/Master/texmf-dist/doc/xelatex/xecjk/README @@ -12,13 +12,17 @@ This package is licensed in LPPL. This package consists of the file xeCJK.dtx and the derived files xeCJK.pdf, xeCJK.sty, + xeCJK.cfg, xeCJK.ins, xeCJK-example-autofake.tex, xeCJK-example-fallback.tex, xeCJK-example-subCJKblock.tex, xeCJK-example-CJKecglue.tex, - xeCJK-example-checksingle.tex and - README.txt (this file). + xeCJK-example-checksingle.tex, + xeCJK-example-CJKfntef.tex, + xeCJK-example-punctstyle.tex, + xeCJK-example-verbatim.tex, and + README.txt. (this file). If you are interested in the process of development you may observe @@ -43,7 +47,8 @@ The package requires LaTeX3 support as provided in the l3kernel and l3packages bundles and the fontspec package. All of these are available on CTAN as ready-to-install zip files. Suitable versions are available in the latest version of MiKTeX and TeX Live (updating the relevant -packages online may be necessary). +packages online may be necessary). Both of xpatch and etoolbox packages +are required. They are also available on CTAN. To compile the documentation without error, you will need some specific CJK scripts fonts (TrueType or OpenType). diff --git a/Master/texmf-dist/doc/xelatex/xecjk/example/xeCJK-example-CJKecglue.tex b/Master/texmf-dist/doc/xelatex/xecjk/example/xeCJK-example-CJKecglue.tex index f9159b4976a..41c3a087fbd 100644 --- a/Master/texmf-dist/doc/xelatex/xecjk/example/xeCJK-example-CJKecglue.tex +++ b/Master/texmf-dist/doc/xelatex/xecjk/example/xeCJK-example-CJKecglue.tex @@ -6,29 +6,6 @@ %% %% xeCJK.dtx (with options: `ex-ecglue') %% -%% $Id: xeCJK.dtx 358 2012-10-27 11:52:01Z sobenlee $ -%% $URL: https://ctex-kit.googlecode.com/svn/trunk/xeCJK/xeCJK.dtx $ -%% ----------------------------------------------------------------- -%% Author: -%% Wenchang Sun <sunwch@nankai.edu.cn> -%% Current Maintainers: -%% Leo Liu <leoliu.pku@gmail.com> -%% Qing Lee <sobenlee@gmail.com> -%% -%% Copyright (C) 2007--2012 Wenchang Sun -%% -%% This file may be distributed and/or modified under the -%% conditions of the LaTeX Project Public License, either version 1.3 -%% of this license or (at your option) any later version. -%% The latest version of this license is in -%% http://www.latex-project.org/lppl.txt -%% and version 1.3 or later is part of all distributions of LaTeX -%% version 2005/12/01 or later. -%% -%% This work has the LPPL maintenance status "maintained". -%% The Current Maintainer of this work are Leo Liu and Qing Lee. -%% ----------------------------------------------------------------- -%% \documentclass{minimal} \usepackage{xeCJK} \setCJKmainfont[BoldFont=SimHei]{SimSun} @@ -47,15 +24,5 @@ This is an example. 这是一个例子} \showtext \end{document} %% -%% This package consists of the file xeCJK.dtx -%% and the derived files xeCJK.pdf, -%% xeCJK.sty, -%% xeCJK.ins, -%% xeCJK-example-autofake.tex, -%% xeCJK-example-fallback.tex, -%% xeCJK-example-subCJKblock.tex, -%% xeCJK-example-CJKecglue.tex, -%% xeCJK-example-checksingle.tex and -%% README.txt. %% %% End of file `xeCJK-example-CJKecglue.tex'. diff --git a/Master/texmf-dist/doc/xelatex/xecjk/example/xeCJK-example-CJKfntef.tex b/Master/texmf-dist/doc/xelatex/xecjk/example/xeCJK-example-CJKfntef.tex new file mode 100644 index 00000000000..700f3d0d3a6 --- /dev/null +++ b/Master/texmf-dist/doc/xelatex/xecjk/example/xeCJK-example-CJKfntef.tex @@ -0,0 +1,32 @@ +%% +%% This is file `xeCJK-example-CJKfntef.tex', +%% generated with the docstrip utility. +%% +%% The original source files were: +%% +%% xeCJK.dtx (with options: `ex-fntef') +%% +\documentclass{article} +\usepackage{xeCJK} +\usepackage{xcolor} +\usepackage{CJKfntef} +\setCJKmainfont{SimSun} + +\begin{document} + +\CJKunderline{汉字}\CJKunderline{加下划线加下划线加下划线加下划线 +加下划线加下划线加下划线加下划线加下划线加下划线加下划线} + +\CJKunderwave{波浪线} + +\CJKunderanyline{0.5em}{\sixly \kern-.021em\char58 \kern-.021em}{自定义下划线} + +\CJKunderanyline{0.2em}{\kern-.03em\vtop{\kern.2ex\hrule width.2em\kern 0.11em + \hrule height 0.1em}\kern-.03em}{自定义下划线} + +\CJKunderanysymbol{0.5em}{$\cdot$}{汉字加点} + +\end{document} +%% +%% +%% End of file `xeCJK-example-CJKfntef.tex'. diff --git a/Master/texmf-dist/doc/xelatex/xecjk/example/xeCJK-example-autofake.tex b/Master/texmf-dist/doc/xelatex/xecjk/example/xeCJK-example-autofake.tex index 190dfb2883d..5e7126280c7 100644 --- a/Master/texmf-dist/doc/xelatex/xecjk/example/xeCJK-example-autofake.tex +++ b/Master/texmf-dist/doc/xelatex/xecjk/example/xeCJK-example-autofake.tex @@ -6,29 +6,6 @@ %% %% xeCJK.dtx (with options: `ex-autofake') %% -%% $Id: xeCJK.dtx 358 2012-10-27 11:52:01Z sobenlee $ -%% $URL: https://ctex-kit.googlecode.com/svn/trunk/xeCJK/xeCJK.dtx $ -%% ----------------------------------------------------------------- -%% Author: -%% Wenchang Sun <sunwch@nankai.edu.cn> -%% Current Maintainers: -%% Leo Liu <leoliu.pku@gmail.com> -%% Qing Lee <sobenlee@gmail.com> -%% -%% Copyright (C) 2007--2012 Wenchang Sun -%% -%% This file may be distributed and/or modified under the -%% conditions of the LaTeX Project Public License, either version 1.3 -%% of this license or (at your option) any later version. -%% The latest version of this license is in -%% http://www.latex-project.org/lppl.txt -%% and version 1.3 or later is part of all distributions of LaTeX -%% version 2005/12/01 or later. -%% -%% This work has the LPPL maintenance status "maintained". -%% The Current Maintainer of this work are Leo Liu and Qing Lee. -%% ----------------------------------------------------------------- -%% \documentclass{article} \usepackage[AutoFakeBold,AutoFakeSlant]{xeCJK} \setCJKmainfont[BoldFont=simhei.ttf, ItalicFont=simkai.ttf]{simsun.ttc} @@ -78,15 +55,5 @@ \end{tabular} \end{document} %% -%% This package consists of the file xeCJK.dtx -%% and the derived files xeCJK.pdf, -%% xeCJK.sty, -%% xeCJK.ins, -%% xeCJK-example-autofake.tex, -%% xeCJK-example-fallback.tex, -%% xeCJK-example-subCJKblock.tex, -%% xeCJK-example-CJKecglue.tex, -%% xeCJK-example-checksingle.tex and -%% README.txt. %% %% End of file `xeCJK-example-autofake.tex'. diff --git a/Master/texmf-dist/doc/xelatex/xecjk/example/xeCJK-example-checksingle.tex b/Master/texmf-dist/doc/xelatex/xecjk/example/xeCJK-example-checksingle.tex index 07b0e4822d6..16f4a034420 100644 --- a/Master/texmf-dist/doc/xelatex/xecjk/example/xeCJK-example-checksingle.tex +++ b/Master/texmf-dist/doc/xelatex/xecjk/example/xeCJK-example-checksingle.tex @@ -6,29 +6,6 @@ %% %% xeCJK.dtx (with options: `ex-single') %% -%% $Id: xeCJK.dtx 358 2012-10-27 11:52:01Z sobenlee $ -%% $URL: https://ctex-kit.googlecode.com/svn/trunk/xeCJK/xeCJK.dtx $ -%% ----------------------------------------------------------------- -%% Author: -%% Wenchang Sun <sunwch@nankai.edu.cn> -%% Current Maintainers: -%% Leo Liu <leoliu.pku@gmail.com> -%% Qing Lee <sobenlee@gmail.com> -%% -%% Copyright (C) 2007--2012 Wenchang Sun -%% -%% This file may be distributed and/or modified under the -%% conditions of the LaTeX Project Public License, either version 1.3 -%% of this license or (at your option) any later version. -%% The latest version of this license is in -%% http://www.latex-project.org/lppl.txt -%% and version 1.3 or later is part of all distributions of LaTeX -%% version 2005/12/01 or later. -%% -%% This work has the LPPL maintenance status "maintained". -%% The Current Maintainer of this work are Leo Liu and Qing Lee. -%% ----------------------------------------------------------------- -%% \documentclass{minimal} \usepackage{xeCJK} \setCJKmainfont{SimSun} @@ -53,15 +30,5 @@ x^2+y^2 \showtext \end{document} %% -%% This package consists of the file xeCJK.dtx -%% and the derived files xeCJK.pdf, -%% xeCJK.sty, -%% xeCJK.ins, -%% xeCJK-example-autofake.tex, -%% xeCJK-example-fallback.tex, -%% xeCJK-example-subCJKblock.tex, -%% xeCJK-example-CJKecglue.tex, -%% xeCJK-example-checksingle.tex and -%% README.txt. %% %% End of file `xeCJK-example-checksingle.tex'. diff --git a/Master/texmf-dist/doc/xelatex/xecjk/example/xeCJK-example-fallback.tex b/Master/texmf-dist/doc/xelatex/xecjk/example/xeCJK-example-fallback.tex index e6d2f36fde5..53e64190a31 100644 --- a/Master/texmf-dist/doc/xelatex/xecjk/example/xeCJK-example-fallback.tex +++ b/Master/texmf-dist/doc/xelatex/xecjk/example/xeCJK-example-fallback.tex @@ -6,29 +6,6 @@ %% %% xeCJK.dtx (with options: `ex-fallback') %% -%% $Id: xeCJK.dtx 358 2012-10-27 11:52:01Z sobenlee $ -%% $URL: https://ctex-kit.googlecode.com/svn/trunk/xeCJK/xeCJK.dtx $ -%% ----------------------------------------------------------------- -%% Author: -%% Wenchang Sun <sunwch@nankai.edu.cn> -%% Current Maintainers: -%% Leo Liu <leoliu.pku@gmail.com> -%% Qing Lee <sobenlee@gmail.com> -%% -%% Copyright (C) 2007--2012 Wenchang Sun -%% -%% This file may be distributed and/or modified under the -%% conditions of the LaTeX Project Public License, either version 1.3 -%% of this license or (at your option) any later version. -%% The latest version of this license is in -%% http://www.latex-project.org/lppl.txt -%% and version 1.3 or later is part of all distributions of LaTeX -%% version 2005/12/01 or later. -%% -%% This work has the LPPL maintenance status "maintained". -%% The Current Maintainer of this work are Leo Liu and Qing Lee. -%% ----------------------------------------------------------------- -%% \documentclass{article} \usepackage[AutoFallBack]{xeCJK} \usepackage{CJKfntef} @@ -69,15 +46,5 @@ \end{table} \end{document} %% -%% This package consists of the file xeCJK.dtx -%% and the derived files xeCJK.pdf, -%% xeCJK.sty, -%% xeCJK.ins, -%% xeCJK-example-autofake.tex, -%% xeCJK-example-fallback.tex, -%% xeCJK-example-subCJKblock.tex, -%% xeCJK-example-CJKecglue.tex, -%% xeCJK-example-checksingle.tex and -%% README.txt. %% %% End of file `xeCJK-example-fallback.tex'. diff --git a/Master/texmf-dist/doc/xelatex/xecjk/example/xeCJK-example-punctstyle.tex b/Master/texmf-dist/doc/xelatex/xecjk/example/xeCJK-example-punctstyle.tex new file mode 100644 index 00000000000..be735b5d5c7 --- /dev/null +++ b/Master/texmf-dist/doc/xelatex/xecjk/example/xeCJK-example-punctstyle.tex @@ -0,0 +1,51 @@ +%% +%% This is file `xeCJK-example-punctstyle.tex', +%% generated with the docstrip utility. +%% +%% The original source files were: +%% +%% xeCJK.dtx (with options: `ex-punctstyle') +%% +\documentclass{article} +\usepackage{xeCJK} +\setCJKmainfont{SimSun} +\xeCJKDeclarePunctStyle { mine } + { + fixed-punct-ratio = 0 , + fixed-margin-width = 0 pt , + mixed-margin-width = \maxdimen , + mixed-margin-ratio = 0.5 , + middle-margin-width = \maxdimen , + middle-margin-ratio = 0.5 , + add-min-bound-to-margin = true , + min-bound-to-kerning = true , + kerning-margin-minimum = 0.1 em + } + +\begin{document} +\setlength\parindent{2em} +\newcommand\showexample[1]{% + \texttt{------ #1 ------}\par\xeCJKsetup{PunctStyle=#1}\showtexts\par} + +\newcommand\showtexts{% +列位看官:你道此书从何而来?说起根由,虽近荒唐,细按则深有趣味。待在下将此来历注明,方使阅者了然不惑。 + +原来女娲氏炼石补天之时,于大荒山无稽崖炼成高经十二丈、方经二十四丈顽石三万六千五百零一块。娲皇氏只用了三万六千五百块,只单单剩了一块未用,便弃在此山青埂峰下。谁知此石自经煆炼之后,灵性已通,因见众石俱得补天,独自己无材不堪入选,遂自怨自叹,日夜悲号惭愧。 + +一日,正当嗟悼之际,俄见一僧一道远远而来,生得骨格不凡,丰神迥别,说说笑笑,来至峰下,坐于石边,高谈快论:先是说些云山雾海、神仙玄幻之事,后便说到红尘中荣华富贵。此石听了,不觉打动凡心,也想要到人间去享一享这荣华富贵,但自恨粗蠢,不得已,便口吐人言,向那僧道说道:“大师,弟子蠢物,不能见礼了!适闻二位谈那人世间荣耀繁华,心切慕之。弟子质虽粗蠢,性却稍通,况见二师仙形道体,定非凡品,必有补天济世之材,利物济人之德。如蒙发一点慈心,携带弟子得入红尘,在那富贵场中,温柔乡里受享几年,自当永佩洪恩,万劫不忘也!”二仙师听毕,齐憨笑道:“善哉,善哉!那红尘中有却有些乐事,但不能永远依恃;况又有‘美中不足,好事多磨’八个字紧相连属,瞬息间则又乐极悲生,人非物换,究竟是到头一梦,万境归空,倒不如不去的好。”这石凡心已炽,那里听得进这话去,乃复苦求再四。二仙知不可强制,乃叹道:“此亦静极思动,无中生有之数也!既如此,我们便携你去受享受享,只是到不得意时,切莫后悔!”石道:“自然,自然。”那僧又道:“若说你性灵,却又如此质蠢,并更无奇贵之处。如此也只好踮脚而已。也罢!我如今大施佛法,助你助,待劫终之日,复还本质,以了此案。你道好否?”石头听了,感谢不尽。那僧便念咒书符,大展幻术,将一块大石登时变成一块鲜明莹洁的美玉,且又缩成扇坠大小的可佩可拿。那僧托于掌上,笑道:“形体倒也是个宝物了!还只没有实在的好处,须得再镌上数字,使人一见便知是奇物方妙。然后好携你到那昌明隆盛之邦、诗礼簪缨之族、花柳繁华地、温柔富贵乡去安身乐业。”石头听了,喜不能禁,乃问:“不知赐了弟子那哪几件奇处?又不知携了弟子到何地方?望乞明示,使弟子不惑。”那僧笑道:“你且莫问,日后自然明白的。”说着,便袖了这石,同那道人飘然而去,竟不知投奔何方何舍。 + +\hfill +——曹雪芹《红楼梦》} + +\showexample{mine} +\showexample{quanjiao} +\showexample{banjiao} +\showexample{CCT} +\showexample{kaiming} +\showexample{hangmobanjiao} +\showexample{plain} + +\end{document} +%% +%% +%% End of file `xeCJK-example-punctstyle.tex'. diff --git a/Master/texmf-dist/doc/xelatex/xecjk/example/xeCJK-example-subCJKblock.tex b/Master/texmf-dist/doc/xelatex/xecjk/example/xeCJK-example-subCJKblock.tex index 00042b473bf..fa6cac040ef 100644 --- a/Master/texmf-dist/doc/xelatex/xecjk/example/xeCJK-example-subCJKblock.tex +++ b/Master/texmf-dist/doc/xelatex/xecjk/example/xeCJK-example-subCJKblock.tex @@ -6,29 +6,6 @@ %% %% xeCJK.dtx (with options: `ex-block') %% -%% $Id: xeCJK.dtx 358 2012-10-27 11:52:01Z sobenlee $ -%% $URL: https://ctex-kit.googlecode.com/svn/trunk/xeCJK/xeCJK.dtx $ -%% ----------------------------------------------------------------- -%% Author: -%% Wenchang Sun <sunwch@nankai.edu.cn> -%% Current Maintainers: -%% Leo Liu <leoliu.pku@gmail.com> -%% Qing Lee <sobenlee@gmail.com> -%% -%% Copyright (C) 2007--2012 Wenchang Sun -%% -%% This file may be distributed and/or modified under the -%% conditions of the LaTeX Project Public License, either version 1.3 -%% of this license or (at your option) any later version. -%% The latest version of this license is in -%% http://www.latex-project.org/lppl.txt -%% and version 1.3 or later is part of all distributions of LaTeX -%% version 2005/12/01 or later. -%% -%% This work has the LPPL maintenance status "maintained". -%% The Current Maintainer of this work are Leo Liu and Qing Lee. -%% ----------------------------------------------------------------- -%% \documentclass{article} \usepackage{xeCJK} \usepackage{array} @@ -85,15 +62,5 @@ CJK統合漢字(シージェーケーとうごうかんじ、CJK Unified Ideog \end{table} \end{document} %% -%% This package consists of the file xeCJK.dtx -%% and the derived files xeCJK.pdf, -%% xeCJK.sty, -%% xeCJK.ins, -%% xeCJK-example-autofake.tex, -%% xeCJK-example-fallback.tex, -%% xeCJK-example-subCJKblock.tex, -%% xeCJK-example-CJKecglue.tex, -%% xeCJK-example-checksingle.tex and -%% README.txt. %% %% End of file `xeCJK-example-subCJKblock.tex'. diff --git a/Master/texmf-dist/doc/xelatex/xecjk/example/xeCJK-example-verbatim.tex b/Master/texmf-dist/doc/xelatex/xecjk/example/xeCJK-example-verbatim.tex new file mode 100644 index 00000000000..f37cb46eff1 --- /dev/null +++ b/Master/texmf-dist/doc/xelatex/xecjk/example/xeCJK-example-verbatim.tex @@ -0,0 +1,62 @@ +%% +%% This is file `xeCJK-example-verbatim.tex', +%% generated with the docstrip utility. +%% +%% The original source files were: +%% +%% xeCJK.dtx (with options: `ex-verb') +%% +\documentclass[a4paper]{article} +\usepackage{xeCJK} +\usepackage{fullpage} +\xeCJKDeclareSubCJKBlock{Hangul} + { "1100 -> "11FF, "3130 -> "318F, "A960 -> "A97F, "AC00 -> "D7AF } +\setCJKmainfont{Adobe Song Std} +\setCJKmainfont[Hangul]{Adobe Myungjo Std} +%%\setmonofont{Inconsolata} +%%\setmonofont{Source Code Pro} +%%\setCJKmonofont{Adobe Kaiti Std} +\setmonofont{TeX Gyre Cursor} +\setCJKmonofont{Adobe Fangsong Std} +\begin{document} + +\begin{verbatim} +************************************************************* +* * +* 精致甲版红楼梦 - 精致工作室特别奉献(2010年9月) * +* * +* GBK简体、GBK繁体、Big5繁体、PDF简体、PDF繁体 * +* * +* 为 GBK、Big5 特别度身订制,并经反复修订,方便纯文本阅读 * +* * +* 精致甲、乙版红楼梦下载专页 * +* http://www.speedy7.com/cn/stguru/gb2312/redmansions.htm * +* http://www.speedy7.com/cn/stguru/big5/redmansions.htm * +* * +* 此电子文件可随意传播、发布、下载。 * +* 传播时建议保留此版本说明供查阅与识别。 * +* 未经修订者同意,不得将此版本用于商业用途。 * +* 如您对红楼梦不具深入了解,请勿随便修改其中的内容。 * +* * +************************************************************* +\end{verbatim} + +\verb|a 汉 字 b| + +\verb*|a 汉 字 b| + +\begin{verbatim} +lang_set = { + ["English"] = lang.en, + ["Français"] = lang.fr, + ["Español"] = lang.es, + ["中文"] = lang.zh, + ["日本語"] = lang.ja, + ["한국어"] = lang.ko, +} +\end{verbatim} + +\end{document} +%% +%% +%% End of file `xeCJK-example-verbatim.tex'. diff --git a/Master/texmf-dist/doc/xelatex/xecjk/xeCJK.pdf b/Master/texmf-dist/doc/xelatex/xecjk/xeCJK.pdf Binary files differindex 4f418136d5a..39ed5e3552e 100644 --- a/Master/texmf-dist/doc/xelatex/xecjk/xeCJK.pdf +++ b/Master/texmf-dist/doc/xelatex/xecjk/xeCJK.pdf diff --git a/Master/texmf-dist/source/xelatex/xecjk/xeCJK.dtx b/Master/texmf-dist/source/xelatex/xecjk/xeCJK.dtx index 7db4de8d136..4bdcdb2f7bc 100644 --- a/Master/texmf-dist/source/xelatex/xecjk/xeCJK.dtx +++ b/Master/texmf-dist/source/xelatex/xecjk/xeCJK.dtx @@ -20,13 +20,17 @@ This package is licensed in LPPL. This package consists of the file xeCJK.dtx and the derived files xeCJK.pdf, xeCJK.sty, + xeCJK.cfg, xeCJK.ins, xeCJK-example-autofake.tex, xeCJK-example-fallback.tex, xeCJK-example-subCJKblock.tex, xeCJK-example-CJKecglue.tex, - xeCJK-example-checksingle.tex and - README.txt (this file). + xeCJK-example-checksingle.tex, + xeCJK-example-CJKfntef.tex, + xeCJK-example-punctstyle.tex, + xeCJK-example-verbatim.tex, and + README.txt. (this file). If you are interested in the process of development you may observe @@ -52,7 +56,8 @@ The package requires LaTeX3 support as provided in the l3kernel and l3packages bundles and the fontspec package. All of these are available on CTAN as ready-to-install zip files. Suitable versions are available in the latest version of MiKTeX and TeX Live (updating the relevant -packages online may be necessary). +packages online may be necessary). Both of xpatch and etoolbox packages +are required. They are also available on CTAN. To compile the documentation without error, you will need some specific CJK scripts fonts (TrueType or OpenType). @@ -64,13 +69,9 @@ CJK scripts fonts (TrueType or OpenType). \edef\tempb{plain} \ifx\tempa\tempb \endgroup - \expandafter\let\csname ifxeCJKplainTeX\expandafter\endcsname\csname iftrue\endcsname + \def\xeCJKMaybeStopHere{\endbatchfile} \else - \endgroup - \expandafter\let\csname ifxeCJKplainTeX\expandafter\endcsname\csname iffalse\endcsname -\fi -\ifxeCJKplainTeX \else - \expandafter\begingroup + \let\xeCJKMaybeStopHere\endgroup \fi %</internal> %<*batchfile> @@ -80,7 +81,7 @@ CJK scripts fonts (TrueType or OpenType). \askforoverwritefalse \preamble -$Id: xeCJK.dtx 358 2012-10-27 11:52:01Z sobenlee $ +$Id: xeCJK.dtx 368 2012-11-23 04:55:23Z sobenlee $ $URL: https://ctex-kit.googlecode.com/svn/trunk/xeCJK/xeCJK.dtx $ ----------------------------------------------------------------- Author: @@ -109,23 +110,41 @@ $URL: https://ctex-kit.googlecode.com/svn/trunk/xeCJK/xeCJK.dtx $ This package consists of the file xeCJK.dtx and the derived files xeCJK.pdf, xeCJK.sty, + xeCJK.cfg, xeCJK.ins, xeCJK-example-autofake.tex, xeCJK-example-fallback.tex, xeCJK-example-subCJKblock.tex, xeCJK-example-CJKecglue.tex, - xeCJK-example-checksingle.tex and + xeCJK-example-checksingle.tex, + xeCJK-example-CJKfntef.tex, + xeCJK-example-punctstyle.tex, + xeCJK-example-verbatim.tex, and README.txt. \endpostamble +\declarepreamble\emptypreamble +\endpreamble +\declarepostamble\emptypostamble +\endpostamble \usedir{tex/xelatex/xecjk} \generate{\file{\jobname.sty}{\from{\jobname.dtx}{package}}} +\usedir{tex/xelatex/xecjk/config} +\generate{ + \usepreamble\emptypreamble + \usepostamble\emptypostamble + \file{\jobname.cfg}{\from{\jobname.dtx}{config}}} \usedir{doc/xelatex/xecjk/example} \generate{ + \usepreamble\emptypreamble + \usepostamble\emptypostamble \file{\jobname-example-autofake.tex}{\from{\jobname.dtx}{ex-autofake}} \file{\jobname-example-fallback.tex}{\from{\jobname.dtx}{ex-fallback}} \file{\jobname-example-subCJKblock.tex}{\from{\jobname.dtx}{ex-block}} \file{\jobname-example-CJKecglue.tex}{\from{\jobname.dtx}{ex-ecglue}} - \file{\jobname-example-checksingle.tex}{\from{\jobname.dtx}{ex-single}}} + \file{\jobname-example-checksingle.tex}{\from{\jobname.dtx}{ex-single}} + \file{\jobname-example-CJKfntef.tex}{\from{\jobname.dtx}{ex-fntef}} + \file{\jobname-example-punctstyle.tex}{\from{\jobname.dtx}{ex-punctstyle}} + \file{\jobname-example-verbatim.tex}{\from{\jobname.dtx}{ex-verb}}} %</batchfile> %<batchfile>\endbatchfile %<*internal> @@ -134,37 +153,50 @@ $URL: https://ctex-kit.googlecode.com/svn/trunk/xeCJK/xeCJK.dtx $ \nopreamble\nopostamble \usedir{doc/xelatex/xecjk} \generate{\file{README.txt}{\from{\jobname.dtx}{readme}}} -\ifxeCJKplainTeX - \expandafter\endbatchfile -\else - \expandafter\endgroup -\fi +\xeCJKMaybeStopHere %</internal> % -%<*driver|package> +%<*driver|package|config> \NeedsTeXFormat{LaTeX2e} +%<*!config> \RequirePackage{expl3} -\GetIdInfo$Id: xeCJK.dtx 358 2012-10-27 11:52:01Z sobenlee $ - {package for typesetting CJK scripts with XeLaTeX} -%<*driver> +%</!config> +\GetIdInfo$Id: xeCJK.dtx 368 2012-11-23 04:55:23Z sobenlee $ +%<*!config> + {Typesetting CJK scripts with XeLaTeX} +%</!config> +%<config> {Configuration file for xeCJK package} +%<*!package> \ProvidesExplFile +%</!package> +%<*driver> {\ExplFileName.\ExplFileExtension} %</driver> +%<config> {\ExplFileName.cfg} %<package>\ProvidesExplPackage %<package> {\ExplFileName} - {\ExplFileDate}{3.0.10}{\ExplFileDescription} + {\ExplFileDate}{3.1.0}{\ExplFileDescription} %<*driver> +\let\xeCJKrevnum\ExplFileVersion \ExplSyntaxOff %</driver> -%</driver|package> +%</driver|package|config> % %<*driver> -\documentclass[full]{l3doc} +\expandafter\let\csname ver@thumbpdf.sty\endcsname\empty +\documentclass[numbered,a4paper,full]{l3doc} \hypersetup{pdfstartview=FitH} \usepackage{xeCJK} -\fvset{formatcom=\CJKfixedspacing} +\usepackage{CJKfntef} +\usepackage{geometry} +\usepackage[toc]{multitoc} +\normalem +\fvset{formatcom=\xeCJKVerbAddon} \linespread{1.1} -\setlist{nosep} +\setlist{noitemsep,topsep=1ex} +\newlist{optiondesc}{description}{3} +\setlist[optiondesc]{font=\mdseries\ttfamily,align=right,labelsep=.5em,leftmargin=4.5em} +\def\PSKeyVal#1#2{\item[#1]\makebox[4em][l]{\meta{#2}}\ignorespaces} \setmainfont[Ligatures=TeX]{TeX Gyre Pagella} \setmonofont{Inconsolata} \setCJKmainfont[BoldFont=Adobe Heiti Std,ItalicFont=Adobe Kaiti Std]{Adobe Song Std} @@ -176,19 +208,41 @@ $URL: https://ctex-kit.googlecode.com/svn/trunk/xeCJK/xeCJK.dtx $ \setCJKmainfont[Ext-B]{SimSun-ExtB} \setCJKmainfont[Hangul]{Adobe Myungjo Std} \xeCJKsetup{PunctStyle=kaiming,KaiMingPunct+={:;}} -\def\MacroFont{\small\normalfont\ttfamily\punctstyle{plain}} +\def\MacroFont{\small\normalfont\ttfamily\xeCJKVerbAddon} \def\XeTeX{\hologo{XeTeX}} \def\XeLaTeX{\hologo{XeLaTeX}} \def\LaTeX{\hologo{LaTeX}} +\def\LaTeXe{\hologo{LaTeX2e}} \parindent=2em \AtBeginDocument{\DeleteShortVerb{\"}\MakeShortVerb{\|}} \def\contentsname{目录} \DeclareUrlCommand\email{\def\UrlLeft##1\UrlRight{\href{mailto:##1}{##1}}} -\addtolength{\voffset}{-5\baselineskip} -\addtolength\textheight{8\baselineskip} +\def\ctexkit{\href{http://code.google.com/p/ctex-kit/}{\texttt{ctex-kit}}} +\def\ctexkitrev#1{% + \href{http://code.google.com/p/ctex-kit/source/detail?r=#1} + {\texttt{ctex-kit} rev#1}} +\ExplSyntaxOn +\cs_new_nopar:Npn \package #1 + { + \href + { + http://mirrors.ctan.org/help/Catalogue/entries/ + \tl_expandable_lowercase:n {#1} .html + } + { \pkg {#1} } + } +\ExplSyntaxOff +\geometry{includemp,hmargin={0mm,15mm},vmargin=15mm,footskip=7mm} \makeatletter +\appto\GlossaryParms{% + \def\@idxitem{\par\hangindent 2em}% + \def\subitem{\@idxitem\hspace*{1em}}% + \def\subsubitem{\@idxitem\hspace*{2em}}} +\patchcmd\changes@{\space}{\lbrack}{}{} +\patchcmd\@wrglossary{hdpindex}{hdclindex{\the\c@HD@hypercount}}{}{} \let\orig@meta\meta -\def\meta#1{\orig@meta{\mbox{\normalfont\itshape\CJKfixedspacing#1}}} +\def\meta#1{% + \orig@meta{\mbox{\normalfont\itshape\xeCJKsetup{PunctStyle=plain,CJKecglue}#1}}} \def\TF{true\orvar{}false} \def\TTF{\defaultvar{true}\orvar{}false} \def\TFF{true\orvar\defaultvar{false}} @@ -199,49 +253,58 @@ $URL: https://ctex-kit.googlecode.com/svn/trunk/xeCJK/xeCJK.dtx $ \def\tokslink#1{\hyperlink{#1}{\ding{51}}} \makeatother \def\indexname{代码索引} +\def\glossaryname{版本历史} +\GlossaryPrologue{% + \addtocounter{secnumdepth}{-10}% + \section{\glossaryname}} \IndexPrologue{% - \section*{\indexname} - \markboth{\indexname}{\indexname} + \section{\indexname}% 斜体的数字表示对应项说明所在的页码,下划线的数字表示定义所在的代码行号,而直立体的 数字表示对应项使用时所在的行号。} \begin{document} \DocInput{\jobname.dtx} + \newgeometry{margin=15mm,footskip=7mm} + \PrintChanges + \PrintIndex \end{document} %</driver> % \fi % -% \CheckSum{3129} -% \DoNotIndex{\T,\F,\C,\J,\K,\O,\U,\Z,\E,\R,\M,\A,\Y,\R,\;,\t,\c,\:,\\,\@} +% \CheckSum{3035} +% \changes{v3.1.0}{2012/11/13}{放弃对 \cs{outer} 宏的特殊处理。} +% % \GetFileInfo{\jobname.dtx} % % \title{\bfseries\pkg{xeCJK} 宏包} % \author{\href{http://www.ctex.org}{ctex.org}} -% \date{\filedate\qquad\fileversion} +% \date{\filedate\qquad\fileversion\thanks{\ctexkitrev{\xeCJKrevnum}.}} % \maketitle % % \tableofcontents +% \vspace{\baselineskip} % % \begin{documentation} % % \section{简介} % % \pkg{xeCJK} 是一个 \XeLaTeX 宏包,用于排版中日韩(CJK)文字。主要功能: -% \begin{enumerate} +% \begin{enumerate}[labelindent=\parindent,leftmargin=*] % \item 分别设置 CJK 和英文字体; % \item 自动忽略 CJK 文字间的空格而保留其它空格,允许在非标点汉字和英文 -% 字母 (a--z, A--Z) 间断行; +% 字母 (a -- z, A -- Z) 间断行; % \item 提供多种标点处理方式: 全角式、半角式、开明式、行末半角式和 CCT 式; % \item 自动调整中英文间空白。 % \end{enumerate} % % \pkg{xeCJK} 使用了 \XeTeX 的一些最新特性,需要 \XeTeX{} |0.9995.0 [2009/06/29]| 以 -% 后的版本。\pkg{xeCJK} 依赖 \LaTeX~3 项目的 \pkg{expl3},\pkg{xparse} 和 -% \pkg{l3keys2e} 宏包。\pkg{xeCJK} 还通过 \pkg{fontspec}^^A -% \footnote{\url{http://mirrors.ctan.org/macros/latex/contrib/fontspec/}} -% 宏包来调用系统字体。个别兼容性功能需要 \pkg{CJK} 宏包的支持。 -% -% \pkg{xeCJK} 的原始作者是孙文昌,2009 年 5 月起宏包被收入 -% \texttt{ctex-kit}\footnote{\url{http://code.google.com/p/ctex-kit/}} 项目进行 +% 后的版本。\pkg{xeCJK} 依赖 \hologo{LaTeX3} 项目的宏包套件 \package{l3kernel} 和 +% \package{l3packages}。\pkg{xeCJK} 还需要通过 \package{fontspec} 宏包来调用系统字 +% 体。将在 \ref{subsec:opts}~节介绍的功能选项 |CJKnumber| 需要 \package{CJK} 宏包套 +% 件中的 \pkg{CJKnumb} 的支持;|indentfirst| 选项需要 \package{indentfirst} 宏包。 +% 此外还需要 \package{xpatch} 和 \package{etoolbox} 宏包。 +% \pkg{xeCJK} 会自动根据需要载入这些宏包。 +% +% \pkg{xeCJK} 的原始作者是孙文昌,2009 年 5 月起宏包被收入 \ctexkit\ 项目进行 % 维护,目前主要维护者是刘海洋\footnote{\email{leoliu.pku@gmail.com}} 和 % 李清\footnote{\email{sobenlee@gmail.com}}。 % @@ -268,14 +331,14 @@ $URL: https://ctex-kit.googlecode.com/svn/trunk/xeCJK/xeCJK.dtx $ % 源文件用 UTF-8 编码保存,使用 \XeLaTeX{} 编译。 % % \pkg{xeCJK} 只提供了字体和标点控制等基本 CJK 语言支持。对于中文文档,可以使 -% 用更为高层的 \pkg{ctex} 宏包或文档类,它将自动调用 \pkg{xeCJK} 并设置好中文 -% 字体,同时提供了进一步的本地化支持。详细内容参看 \pkg{ctex} 宏包^^A -% \footnote{\url{http://mirrors.ctan.org/language/chinese/ctex/}}的说明。 +% 用更为高层的 \package{ctex} 宏包或文档类,它将自动调用 \pkg{xeCJK} 并设置好中文 +% 字体,同时提供了进一步的本地化支持。详细内容参看 \package{ctex} 宏包套件的说明。 % % \pkg{xeCJK} 提供了大量选项,可以在宏包调用时作为宏包选项或用 \cs{xeCJKsetup} % 命令进行设置,详见 \ref{subsec:opts}~节。除了 \cs{setCJKmainfont} 命令, % \pkg{xeCJK} 还提供了许多其他命令设置和选择中文字体,详见 -% \ref{subsec:fontset}~节。其他更详细的功能也都将在下面详细说明。 +% \ref{subsec:fontset}~节。其他更详细的功能也都将在下面详细说明。在本文档所在的 +% 文件夹的 |example| 目录下面也有一些例子可以参考。 % % \section{用户手册} % @@ -284,13 +347,14 @@ $URL: https://ctex-kit.googlecode.com/svn/trunk/xeCJK/xeCJK.dtx $ % % \pkg{xeCJK} 以 \meta{key}|=|\meta{var} 的形式提供宏包选项,你可以在调用宏包 % 的时候直接设置这些选项,也可以在调用宏包之后使用 \cs{xeCJKsetup} 来设置这些选 -% 项。 +% 项。\pkg{xeCJK} 内部调用 \pkg{fontspec} 宏包,可以在调用 \pkg{xeCJK} 的时候, +% 使用它的宏包选项。\pkg{xeCJK} 会将 \pkg{fontspec} 的选项传递给它。 % % \begin{function}{\xeCJKsetup} % \begin{syntax} -% \cs{xeCJKsetup} \argbrace{\meta{key1}=\meta{var1}, \meta{key2}=\meta{var2}, ...} +% \cs{xeCJKsetup} \argbrace{\meta{key_1}=\meta{var_1}, \meta{key_2}=\meta{var_2}, ...} % \end{syntax} -% 其中 \meta{key1}, \meta{key2} 是设置选项,而 \meta{val1}, \meta{val2} 则是对应选项的 +% 其中 \meta{key_1}, \meta{key_2} 是设置选项,而 \meta{val_1}, \meta{val_2} 则是对应选项的 % 设置内容。多个选项可以在一个语句中完成设置。例如 % \begin{verbatim} % \usepackage[PunctStyle=kaiming]{xeCJK} @@ -310,29 +374,47 @@ $URL: https://ctex-kit.googlecode.com/svn/trunk/xeCJK/xeCJK.dtx $ % % 下列选项使用加粗的形式来表示 \pkg{xeCJK} 的默认设置。 % -% \begin{function}{xeCJKactive} +% \begin{function}[EXP]{LocalConfig} % \begin{syntax} -% xeCJKactive = \meta{\TTF} +% LocalConfig = \marg{\TTF\orvar{}name} % \end{syntax} -% 打开/关闭对中文的特殊处理。 +% 是否使用本地配置文件 \texttt{xeCJK-\meta{name}.cfg}。\meta{name} 可以是不包含 +% 空格的任意使文件名合法的字符串。如果设置为 |true|,则使用的是 \texttt{xeCJK.cfg}; +% 设置为 |false| 则不载入配置文件。可以把将要在下文介绍到的对 \pkg{xeCJK} 的一些 +% 设置(例如设置常用 CJK 字体、修改字符范围和定义新的标点输出格式等)保存到文件 +% \texttt{xeCJK-\meta{name}.cfg}。然后把这个文件放在本地的 |TDS| 目录下的适当 +% 位置。使用 \TeX Live 的用户,可以新建下列目录,然后再把 +% \texttt{xeCJK-\meta{name}.cfg} 放在里面: +% \begin{verbatim} +% texlive/texmf-local/tex/xelatex/xecjk +% \end{verbatim} +% 最后还需要在命令行下执行 |mktexlsr|,刷新文件名数据库以便 \TeX 系统能够找到它。 % \end{function} % % \begin{function}[EXP]{CJKnumber} % \begin{syntax} % CJKnumber = \meta{\TFF} % \end{syntax} -% 是否使用 \pkg{CJKnumb} 宏包。请注意,为了与 \pkg{CJKnumb} 兼容,\pkg{xeCJK} 修改了 -% 它的一些内部命令,所以这个选项需要在调用 \pkg{xeCJK} 时设置,而不能通过 \cs{xeCJKsetup} -% 来设置它。 +% 为了与 \pkg{CJKnumb} 宏包兼容,\pkg{xeCJK} 作了一些特别处理。因此,如果需要使用 +% 到 \pkg{CJKnumb},请通过这个选项调用它。 % \end{function} % % \begin{function}[EXP]{indentfirst} % \begin{syntax} % indentfirst = \meta{\TTF} % \end{syntax} -% 跟在章节标题后面的第一段首行是否缩进。这个选项需要在调用 \pkg{xeCJK} 时设置,不能 -% 通过 \cs{xeCJKsetup} 来设置它。\pkg{xeCJK} 宏包中只有 |indentfirst| 和 |CJKnumber| -% 这两个选项,不能通过 \cs{xeCJKsetup} 来设置。 +% 是否使用 \pkg{indentfirst} 宏包,使得跟在章节标题后面的第一段首行也缩进。\bigskip +% \end{function} +% +% 请注意,\pkg{xeCJK} 宏包中只有上述 |LocalConfig|、|CJKnumber| 和 |indentfirst| +% 这三个选项需要在调用 \pkg{xeCJK} 时设置,而不能通过 \cs{xeCJKsetup} 来设置。 +% +% \begin{function}{xeCJKactive} +% \begin{syntax} +% xeCJKactive = \meta{\TTF} +% \end{syntax} +% 打开/关闭对中文的特殊处理。事实上,这个选项会打开/关闭 \XeTeX 的整个字符类机制,依赖 +% 这个机制的宏包都会受到影响。 % \end{function} % % \begin{function}{CJKspace} @@ -390,7 +472,7 @@ $URL: https://ctex-kit.googlecode.com/svn/trunk/xeCJK/xeCJK.dtx $ % InlineEnv = \argbrace{env1, env2, env3, ...} % \end{syntax} % 在使用 |CheckSingle| 选项的时候,\pkg{xeCJK} 会将 CJK 文字后接着的 \LaTeX 环境的 -% 开始 \cs{begin{...}} 和结束 \cs{end{...}} 视为断行的地方,如果有某些特殊 +% 开始 |\begin{...}| 和结束 |\end{...}| 视为断行的地方,如果有某些特殊 % 的 \LaTeX 环境没有造成断行,可以使用这个选项来声明它,以便 |CheckSingle| 能正确识别。 % \end{function} % @@ -434,17 +516,19 @@ $URL: https://ctex-kit.googlecode.com/svn/trunk/xeCJK/xeCJK.dtx $ % % \begin{function}{PunctStyle} % \begin{syntax} -% PunctStyle = \marg{\defaultvar{quanjiao}\orvar{}banjiao\orvar{}kaiming\orvar{}hangmobanjiao\orvar{}CCT\orvar{}plain} +% PunctStyle = \marg{\defaultvar{quanjiao}\orvar{}banjiao\orvar{}kaiming\orvar{}hangmobanjiao\orvar{}CCT\orvar{}plain\orvar{}...} % \end{syntax} -% 设置标点处理格式,有效值分别为 -% \begin{itemize}[font=\ttfamily,labelsep=1em] +% 设置标点处理格式。\pkg{xeCJK} 中预先定义好的格式为 +% \begin{description}[font=\mdseries\ttfamily,align=right,labelsep=1em,labelindent=2em,leftmargin=*] % \item[quanjiao] 全角式:所有标点占一个汉字宽度,相邻两个标点占 1.5 汉字宽度; % \item[banjiao] 半角式:所有标点占半个汉字宽度; % \item[kaiming] 开明式:句末点号用全角,其他半角; % \item[hangmobanjiao] 行末半角式:所有标点占一个汉字宽度,行首行末对齐; % \item[CCT] CCT 格式; % \item[plain] 原样(不调整标点间距)。 -% \end{itemize} +% \end{description} +% 可以使用 \ref{subsec:punctstyle} 中介绍的 \cs{xeCJKDeclarePunctStyle} 定义新的标点 +% 格式。 % \end{function} % % \begin{function}[EXP]{KaiMingPunct,KaiMingPunct+,KaiMingPunct-} @@ -474,13 +558,13 @@ $URL: https://ctex-kit.googlecode.com/svn/trunk/xeCJK/xeCJK.dtx $ % % \begin{function}[EXP]{PunctWidth} % \begin{syntax} -% PunctWidth = \Arg{dimen} +% PunctWidth = \Arg{length} % \end{syntax} % 缺省状态下,\pkg{xeCJK} 会根据所选择的标点处理格式自动计算标点所占的宽度,如果对缺 % 省设置不满意,可以通过这一选项来改变它。为了使得标点所占的宽度能够适应字体大小的变化, -% 这里设置的 |dimen| 的单位最好用 |em| 等相对距离单位,而不建议使用诸如 |pt| 之类的 -% 绝对距离单位。这里的设置对除了 |plain| 以外的所有标点处理格式都有效。同时,这里的 -% 设置对所有的 CJK 标点都生效,如果只要设置部分标点,请使用 \ref{subsec:punct} 节的 +% 这里设置的 |length| 的单位最好用 |em| 等相对距离单位,而不建议使用诸如 |pt| 之类的 +% 绝对距离单位。这里的设置可用于除了 |plain| 以外的所有标点处理格式。同时,这里的 +% 设置对所有的 CJK 标点都生效,如果只要设置部分标点,请使用 \ref{subsec:punct}~节的 % \cs{xeCJKsetwidth}。 % \end{function} % @@ -526,37 +610,21 @@ $URL: https://ctex-kit.googlecode.com/svn/trunk/xeCJK/xeCJK.dtx $ % \begin{syntax} % \cs{setCJKmonofont} \oarg{font features} \Arg{font name} % \end{syntax} -% 设置正文等宽族的 CJK 字体,影响 \cs{ttfamily} 和 \cs{texttt} 的字体。为了有利于等宽 -% 字体的代码对齐等情形,\pkg{xeCJK} 在 \meta{font features} 里增加了 |Mono| 这个选项。 +% 设置正文等宽族的 CJK 字体,影响 \cs{ttfamily} 和 \cs{texttt} 的字体。 % \end{function} % -% \begin{function}{Mono} +% \begin{function}{\xeCJKVerbAddon} % \begin{syntax} -% Mono = \meta{Scale\orvar{}Exspace} +% \cs{xeCJKVerbAddon} % \end{syntax} -% 有效值仅为 |Scale| 或 |Exspace|。分别表示使用放缩的方式或改变间距的方式,让 CJK -% 字符的宽度等于西文字体中两个空格的宽度。 -% \end{function} -% -% \begin{function}{\CJKfixedspacing,\CJKflexiblespacing} -% \begin{syntax} -% \cs{CJKfixedspacing} -% \cs{CJKflexiblespacing} -% \end{syntax} -% \cs{CJKfixedspacing} 命令设置固定字距和不压缩标点格式,符合上面 |Mono=Exspace| 选 -% 项的意义。\cs{CJKflexiblespacing} 命令恢复可伸缩的字距和标点压缩。抄录 |(verbatim)| -% 环境将自动使用 \cs{CJKfixedspacing} 的效果。 -% \end{function} -% -% \begin{function}{\setCJKmonoscale,\setCJKmonoexspace} -% \begin{syntax} -% \cs{setCJKmonoscale} -% \cs{setCJKmonoexspace} -% \end{syntax} -% \cs{setCJKmonoscale} 和 \cs{setCJKmonoexspace} 命令分别计算并设置当前字号下西文等宽 -% 字体与 CJK 字体的放缩比例和字距,以符合上面所说的 |Mono=Scale| 与 |Mono=Exspace| -% 选项的意义。在字号改变时,应该使用两个命令之一,重新计算相关参数;但注意两个命令不 -% 能同时使用。 +% 调整文字间距以便于让 CJK 字符占的宽度等于西文等宽字体中两个空格的宽度。这有利于 +% 等宽字体的代码对齐等情形。抄录 |(verbatim)| 环境将自动使用 \cs{xeCJKVerbAddon} +% 的效果。需要注意的是,\cs{xeCJKVerbAddon} 对 \pkg{xeCJK} 的内部进行了比较大的 +% 修改,使用它之后,关于标点符号的禁则将会丢失。所以不能单独使用,应该放在分组里 +% 限制其作用域,否则是无效的。当然它可以和其它关于代码抄录的宏包配合使用。例如, +% 可以使用于 \package{fancyvrb} 宏包的 |formatcom| 选项。此时设置的西文字体应该 +% 确实是等宽的以保证对齐。若西文等宽字体发生变动(包括字体大小),则需要在其后面 +% 使用 \cs{xeCJKVerbAddon},重新计算间距的宽度。 % \end{function} % % \begin{function}[EXP]{\setCJKfamilyfont} @@ -692,11 +760,11 @@ $URL: https://ctex-kit.googlecode.com/svn/trunk/xeCJK/xeCJK.dtx $ % \begin{function}[EXP]{\setCJKfallbackfamilyfont} % \begin{syntax} % \cs{setCJKfallbackfamilyfont} \Arg{family} \oarg{common font features} -% \ \char`\{ +% \ \{ % \ \argbrace{\oarg{font features 1} \Arg{font name 1}} , % \ \argbrace{\oarg{font features 2} \Arg{font name 2}} , % \ ...... -% \ \char`\} +% \ \} % \end{syntax} % \cs{setCJKfallbackfamilyfont} 还可以用于设置多层的备用字体。例如,使用 % \begin{verbatim} @@ -725,7 +793,7 @@ $URL: https://ctex-kit.googlecode.com/svn/trunk/xeCJK/xeCJK.dtx $ % % |fc-list| 命令列出的信息很多,而且在安装字体较多的 Windows 系统上的输出将非 % 常庞大,如其中可能包含: -% \begin{verbatim}[formatcom=\fontspec{CMU Typewriter Text}\CJKfixedspacing] +% \begin{verbatim}[formatcom=\fontspec{CMU Typewriter Text}\xeCJKVerbAddon] % Times New Roman:style=cursiva,kurzíva,kursiv,Πλάγια,Italic, % Kursivoitu,Italique,Dőlt,Corsivo,Cursief,kursywa,Itálico,Курсив, % İtalik,Poševno,nghiêng,Etzana @@ -855,6 +923,13 @@ $URL: https://ctex-kit.googlecode.com/svn/trunk/xeCJK/xeCJK.dtx $ % 命令除了设置字符类别以外,为了确保标点处理的正确性,还重置标点符号所属的字符类。 % \end{function} % +% \begin{function}[EXP]{\xeCJKResetCharClass} +% \begin{syntax} +% \cs{xeCJKResetCharClass} +% \end{syntax} +% 用于重置 \pkg{xeCJK} 对各个字符类别的设置。 +% \end{function} +% % \begin{function}[EXP]{\xeCJKResetPunctClass} % \begin{syntax} % \cs{xeCJKResetPunctClass} @@ -869,45 +944,231 @@ $URL: https://ctex-kit.googlecode.com/svn/trunk/xeCJK/xeCJK.dtx $ % 在 \meta{char list} 中出现的字符两端不自动添加空格,默认设置是 |/|。 % \end{function} % -% \subsection{设置标点宽度和间距} +% \subsection{标点符号的处理} +% +% \pkg{xeCJK} 对标点符号的输出宽度的调整是通过调整其左边或右边的空白宽度来实现的。 +% 按照目前的处理方式,对于位于左边的标点符号(如左引号),\pkg{xeCJK} 只能调整它 +% 左边的空白;对于位于右边的标点符号(如右引号),\pkg{xeCJK} 只能调整它右边的空 +% 白;对于居中的标点符号,则调整其左右空白,以保证其居中。 +% +% \subsubsection{设置特定标点符号的宽度和间距} % \label{subsec:punct} % -% 这里的设置对除了 |plain| 以外的所有标点处理格式都有效。 +% 这里的设置可用于除 |plain| 以外的所有标点处理格式。 % % \begin{function}[EXP]{\xeCJKsetwidth} % \begin{syntax} -% \cs{xeCJKsetwidth} \Arg{标点列表} \Arg{dimen} +% \cs{xeCJKsetwidth} \Arg{标点列表} \Arg{length} % \end{syntax} % \meta{标点列表}可以是单个标点,也可以是多个标点。例如, % \begin{verbatim} % \xeCJKsetwidth{。?}{0.7em} % \end{verbatim} -% 将设置句号和问号所占的宽度为 |0.7em|。 +% 将设置句号和问号所占的宽度为 |0.7 em|。 % \end{function} % % \begin{function}[EXP]{\xeCJKsetkern} % \begin{syntax} -% \cs{xeCJKsetkern} \Arg{标点1} \Arg{标点2} \Arg{dimen} +% \cs{xeCJKsetkern} \Arg{前标点} \Arg{后标点} \Arg{length} % \end{syntax} -% \pkg{xeCJK} 会根据选定的标点处理格式自动调整相邻两个 |CJK| 标点的距离。如果对缺省 -% 配置不满意,可以使用此命令设置两个标点之间的距离。例如, +% \pkg{xeCJK} 会根据选定的标点处理格式自动调整相邻的前后两个 |CJK| 标点符号的 +% 空白宽度。如果需要对个别情况进行特殊调整,可以使用这个命令。例如, % \begin{verbatim} % \xeCJKsetkern{:}{“}{0.3em} % \end{verbatim} +% 将设置冒号与左双引号之间的空白宽度为 |0.3 em|。 +% \end{function} +% +% \subsubsection{定义标点符号处理格式} +% \label{subsec:punctstyle} +% +% \begin{function}[EXP]{\xeCJKDeclarePunctStyle} +% \begin{syntax} +% \cs{xeCJKDeclarePunctStyle} \Arg{style} \Arg{options} +% \end{syntax} +% 定义新的标点符号处理格式,已经存在的同名格式将被覆盖。可以设置的选项将在下面介绍。 % \end{function} % +% \begin{function}[EXP]{\xeCJKEditPunctStyle} +% \begin{syntax} +% \cs{xeCJKEditPunctStyle} \Arg{style} \Arg{options} +% \end{syntax} +% 修改已有的标点符号处理格式。\strut +% \end{function} +% +% 下面是可以设置的标点符号格式选项。其中左边一栏是选项名称,中间是选项的输入值类 +% 型,右边则是相关说明。某些选项之间是互斥的,具有优先级关系。要使下一级的选项有 +% 效,则需要先禁用上一级的设置:对于 \meta{boolean} 类型的选项,将其设置为 |false|, +% 对于 \meta{length} 类型的选项,将其设置为 \cs{maxdimen},而对于 \meta{real} 类型 +% 的选项,将其设置为 |0|。 +% +% \begin{optiondesc} +% \PSKeyVal{enabled-global-setting}{boolean} +% 是否使用 \cs{xeCJKsetup} 的 |PunctWidth| 选项和 \cs{xeCJKsetwidth}、 +% \cs{xeCJKsetkern} 的设置。默认值是 |true|。 +% \end{optiondesc} +% +% \begin{optiondesc} +% \PSKeyVal{fixed-punct-width}{length} +% 设置单个标点符号的宽度。默认值是 \cs{maxdimen}。 +% \PSKeyVal{fixed-punct-ratio}{real} +% 设置单个标点符号的输出宽度与实际宽度的比例。默认值是 |1.0|。 +% \PSKeyVal{mixed-punct-width}{length} +% 设置句末标点符号的宽度。其中句末标点符号通过 \cs{xeCJKsetup} 的 |KaiMingPunct| +% 来设置。默认值是与 |fixed-punct-width| 选项的值相同。 +% \PSKeyVal{mixed-punct-width}{real} +% 设置句末标点符号的宽度比例。默认值是与 |fixed-punct-ratio| 选项的值相同。 +% \PSKeyVal{middle-punct-width}{length} +% 设置居中标点符号的宽度。其中居中标点符号通过 \cs{xeCJKsetup} 的 |MiddlePunct| +% 来设置。默认值是与 |fixed-punct-width| 选项的值相同。 +% \PSKeyVal{middle-punct-width}{real} +% 设置居中标点符号的宽度比例。默认值是与 |fixed-punct-ratio| 选项的值相同。 +% \end{optiondesc} +% +% 以上三个选项设置的是标点的固定宽度或比例,\pkg{xeCJK} 会根据设定的选项计算标点符号 +% 左/右的空白宽度。下面的选项设置的是标点符号左/右的空白宽度或比例,因此不同标点符号 +% 的宽度可能会不同。为了使下面的选项生效,需要先禁用上面的相应选项。优先级自上而下。 +% +% \begin{optiondesc} +% \PSKeyVal{fixed-margin-width}{length} +% 设置标点的左/右空白宽度。默认值是 \cs{maxdimen}。 +% \PSKeyVal{fixed-margin-ratio}{real} +% 设置标点的左/右空白宽度与字体中该标点的相应实际边界宽度的比例。默认值是 |1.0|。 +% \PSKeyVal{mixed-margin-width}{length} +% 设置句末标点的左/右空白宽度。默认值是与 |fixed-margin-width| 的值相同。 +% \PSKeyVal{mixed-margin-ratio}{real} +% 设置句末标点的左/右空白宽度的比例。默认值是与 |fixed-margin-ratio| 的值相同。 +% \PSKeyVal{middle-margin-width}{length} +% 设置居中标点的两边空白宽度。默认值是与 |fixed-margin-width| 的值相同。 +% \PSKeyVal{middle-margin-ratio}{real} +% 设置居中标点的两边空白宽度之和与两边实际两边边界宽度之和的比例。 +% 默认值是与 |fixed-margin-ratio| 的值相同。 +% \end{optiondesc} +% +% \begin{optiondesc} +% \PSKeyVal{add-min-bound-to-margin}{boolean} +% 是否在以上计算结果的基础上再加上标点的左右实际边界宽度中的最小值。这个选项 +% 对居中的标点无效。默认值是 |false|。 +% \end{optiondesc} +% +% \begin{optiondesc} +% \PSKeyVal{optimize-margin}{boolean} +% 使用以上设置空白宽度或比例的选项时,最终输出的标点符号左/右的空白宽度可能大 +% 于原来的实际边界宽度。若此时本选项被设置为 |true|,则使用原来的实际边界宽度。 +% 而使用 |fixed-punct-width| 选项计算得出的左/右宽度可能小于该标点的另一侧宽 +% 度,若此时本选项被启用,则使用该标点的另一侧宽度。默认值为 |false|。 +% \end{optiondesc} +% +% \begin{optiondesc} +% \PSKeyVal{margin-minimum}{length} +% 指定标点符号左/右的最小空白宽度。当经过以上选项设置的空白宽度小于这个选项的值 +% 时,则使用这个选项的值。默认值是 |0 pt|。 +% \end{optiondesc} +% +% 下面的选项处理的是前后相邻的两个标点符号之间的空白宽度。这些选项是互斥的,优先级 +% 自上而下。 +% +% \begin{optiondesc} +% \PSKeyVal{enabled-kerning}{boolean} +% 是否调整前后相邻的两个标点之间的空白宽度。如果设置为 |false|,则每个标点都按 +% 原来的输出宽度输出。默认值是 |true|。 +% \PSKeyVal{min-bound-to-kerning}{boolean} +% 是否使用当前字体中前面标点实际左右边界的最小值与后面标点实际左右边界的最小值 +% 中的最大值作为两个标点之间的空白宽度。默认值是 |false|。 +% \PSKeyVal{kerning-total-width}{length} +% 设置两个标点的总共宽度。此时 \pkg{xeCJK} 会自动计算两个标点之间的空白宽度。 +% 默认值是 \cs{maxdimen}。 +% \PSKeyVal{kerning-total-ratio}{real} +% 设置两个标点的总共输出宽度与实际宽度的比例。默认值是 |0.75|。 +% \PSKeyVal{same-align-margin}{length} +% 当前后两个标点位于同侧时,它们之间的空白宽度。默认值是 \cs{maxdimen}。 +% \PSKeyVal{same-align-ratio}{real} +% 当前后两个标点位于同侧时,它们之间的空白宽度与实际输出宽度的比例。默认值是 |0|。 +% \PSKeyVal{different-align-margin}{length} +% 当前后两个标点位于异侧时,它们之间的空白宽度。默认值是 \cs{maxdimen}。 +% \PSKeyVal{different-align-ratio}{real} +% 当前后两个标点位于异侧时,它们之间的空白宽度与实际输出宽度的比例。默认值是 |0|。 +% \PSKeyVal{kerning-margin-width}{length} +% 设置前后两个标点之间的空白宽度。默认值是 \cs{maxdimen}。 +% \PSKeyVal{kerning-margin-ratio}{real} +% 设置前后两个标点之间的空白宽度与实际输出空白的比例。默认值是 |1.0|。 +% \end{optiondesc} +% +% \begin{optiondesc} +% \PSKeyVal{optimize-kerning}{boolean} +% 使用以上选项计算出两个标点之间的空白宽度可能小于通过 |min-bound-to-kerning| +% 选项得出的结果。当出现这一情况时,若此选项被设置为 |true|,则使用该选项的空 +% 白宽度。默认值为 |false|。 +% \end{optiondesc} +% +% \begin{optiondesc} +% \PSKeyVal{kerning-margin-minimum}{length} +% 指定两个标点之间的最小空白宽度。当经过以上选项设置的空白宽度小于这个选项的值 +% 时,则使用这个选项的值。默认值是 |0 pt|。 +% \end{optiondesc} +% +% 事实上,\pkg{xeCJK} 的默认设置就相当于中文全角(|quanjiao|)格式。可以使用上面 +% 说明的选项定义新的标点处理格式。例如,使用 +% \begin{verbatim} +% \xeCJKDeclarePunctStyle { mine } +% { +% fixed-punct-ratio = 0 , +% fixed-margin-width = 0 pt , +% mixed-margin-width = \maxdimen , +% mixed-margin-ratio = 0.5 , +% middle-margin-width = \maxdimen , +% middle-margin-ratio = 0.5 , +% add-min-bound-to-margin = true , +% min-bound-to-kerning = true , +% kerning-margin-minimum = 0.1 em +% } +% \end{verbatim} +% 就定义了一个名为 |mine| 的标点处理格式。可以在通过 +% \begin{verbatim} +% \xeCJKsetup{PunctStyle=mine} +% \end{verbatim} +% 在文档中使用这个格式。它的意义是:使用标点符号的实际左右边界中的最小值作为其左/右 +% 空白的宽度,对于句末标点和居中标点,再加上实际边界空白的一半;使用相邻两个标点的 +% 实际边界中的较小值作为它们之间的空白宽度,并且最小的空白宽度是 |0.1 em|。 +% 再例如,使用 +% \begin{verbatim} +% \xeCJKEditPunctStyle { hangmobanjiao } { enabled-global-setting = false } +% \end{verbatim} +% 将使得 \cs{xeCJKsetkern} 等的设置对 |hangmobanjiao| 这一格式无效。 +% % \section{已知问题和兼容性} % -% 为了与 \pkg{CJKnumb} 和 \pkg{CJKulem} 宏包兼容,\pkg{xeCJK} 使用并重新定义了 +% 为了与 \pkg{CJKnumb} 和 \pkg{CJKfntef} 宏包兼容,\pkg{xeCJK} 使用并重新定义了 % \pkg{CJK} 宏包的部分宏命令,如 \cs{CJKfamily}、\cs{CJKsymbol} 和 \cs{CJKpunctsymbol} 等。 % 需要指出,\pkg{xeCJK} 不需要 \pkg{CJK} 的支持,并且 \pkg{xeCJK} 自动禁止在它之后载入 % \pkg{CJK} 宏包。 % -% 可以在 \pkg{xeCJK} 之后载入 \pkg{CJKfntef} 宏包,以实现汉字加点等。 +% 可以在 \pkg{xeCJK} 之后载入 \pkg{CJKfntef} 宏包,以实现\CJKunderdot{汉字加点} +% 和\CJKunderwave{可断行的下划线}等。 +% +% 新版本(\texttt{3.x})的 \pkg{xeCJK} 完全使用 \hologo{LaTeX3} 的语法来编写。 +% \hologo{LaTeX3} 放弃了 \cs{outer} 宏的概念,因此相关工具(例如 |peek| 类函数)在 +% 遇到 \cs{outer} 宏时可能会存在问题。按照目前 \pkg{xeCJK} 的实现方式,在 CJK 文字 +% 后面遇到 \cs{outer} 宏时会出现类似 +% \begin{verbatim} +% ! Forbidden control sequence found while scanning use of \token_if_eq_meaning:NNTF +% \end{verbatim} +% 的错误。目前已知的有 \pkg{cprotect} 宏包提供的 \cs{cprotect}。它的定义是 +% \begin{verbatim} +% \outer\long\def\cprotect{\icprotect} +% \end{verbatim} +% 因此,这时可以暂时用 \cs{icprotect} 代替 \cs{cprotect}。事实上,当 \pkg{cprotect} +% 被引入时,\pkg{xeCJK} 将使用 +% \begin{verbatim} +% \let\cprotect\icprotect +% \end{verbatim} +% 来取消 \cs{cprotect} 的外部宏限制。但由于 \cs{cprotect} 的特殊性,应该只在外部 +% 使用它,即不要让它出现在任何宏的参数中。其它 \cs{outer} 宏的情况,可以在它前面 +% 加上 \cs{relax} 来回避上面的错误。 % % \pkg{xeCJK} 依赖 \XeTeX 的 \cs{XeTeXinterchartoks} 机制,与使用相同机制的宏包(例如 -% \pkg{polyglossia})会存在大小不一的冲突。\pkg{xeCJK} 虽然为此作了一些处理,但与它们 -% 共同使用时应该小心。 +% \pkg{polyglossia})可能会存在大小不一的冲突。\pkg{xeCJK} 虽然为此作了一些处理,但与 +% 它们共同使用时应该小心。 % %\end{documentation} % @@ -945,160 +1206,210 @@ $URL: https://ctex-kit.googlecode.com/svn/trunk/xeCJK/xeCJK.dtx $ % \begin{macrocode} \msg_new:nnn { xeCJK } { l3-too-old } { - Support~package~'expl3'~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.\\ - Loading~xeCJK~will~abort! + \str_if_eq:nnT {#1} { expl3 } { Loading~xeCJK~will~abort! } } -\@ifpackagelater { expl3 } { 2012/09/10 } { } - { \msg_critical:nn { xeCJK } { l3-too-old } } +\@ifpackagelater { expl3 } { 2012/11/10 } { } + { \msg_critical:nnn { xeCJK } { l3-too-old } { expl3 } } % \end{macrocode} % +% 以下日期以前的 \pkg{xtemplate} 宏包关于 \cs{KeyValue} 的 Bug 会影响到后面 +% 标点符号的处理。 % \begin{macrocode} -\RequirePackage{xparse} -\RequirePackage{l3keys2e} +\RequirePackage { xtemplate } +\@ifpackagelater { xtemplate } { 2012/11/10 } { } + { \msg_error:nnn { xeCJK } { l3-too-old } { xtemplate } } % \end{macrocode} % -% \cs{XeTeXglyphbouds} 可以得到一个字符的左右边距,用于标点压缩。 % \begin{macrocode} -\msg_new:nnn { xeCJK } { XeTeX-too-old } - { - \token_to_str:N \XeTeXglyphbounds \ is~not~defined.\\\\ - You~have~to~update~XeTeX~to~the~version~0.9995.0~or~later. - } -\cs_if_free:NT \XeTeXglyphbounds - { - \msg_error:nn { xeCJK } { XeTeX-too-old } - \AtEndOfPackage { \@@_AfterPreamble:n { \punctstyle { plain } } } - } +\RequirePackage { xparse , l3keys2e } +\RequirePackage { xpatch } % \end{macrocode} % % \subsection{内部工具} % % 分配临时变量。 -% \begin{macro}[internal,var]{\l_@@_tmpa_int,\l_@@_tmpb_int,\l_@@_tmpc_int} % \begin{macrocode} +\tl_new:N \l_@@_tmpa_tl +\tl_new:N \l_@@_tmpb_tl \int_new:N \l_@@_tmpa_int \int_new:N \l_@@_tmpb_int \int_new:N \l_@@_tmpc_int +\box_new:N \l_@@_tmp_box +\dim_new:N \l_@@_tmp_dim +\skip_new:N \g_@@_tmp_skip +\prop_new:N \l_@@_tmp_prop +\clist_new:N \l_@@_tmpa_clist +\clist_new:N \l_@@_tmpb_clist % \end{macrocode} -% \end{macro} -% -% \begin{macro}[internal,var]{\l_@@_tmpa_dim,\l_@@_tmpb_dim,\l_@@_tmpc_dim} -% \begin{macrocode} -\dim_new:N \l_@@_tmpa_dim -\dim_new:N \l_@@_tmpb_dim -\dim_new:N \l_@@_tmpc_dim -% \end{macrocode} -% \end{macro} % -% \begin{macro}[internal,var]{\l_@@_tmpa_tl,\l_@@_tmpb_tl} -% \begin{macrocode} -\tl_new:N \l_@@_tmpa_tl -\tl_new:N \l_@@_tmpb_tl -% \end{macrocode} -% \end{macro} -% -% \begin{macro}[internal,var]{\l_@@_tmpa_clist,\l_@@_tmpb_clist,\l_@@_tmpc_clist} +% \begin{macro}[internal] +% {\@@_msg_new:nn ,\@@_error:n,\@@_error:nx,\@@_warning:nx,\@@_info:nx,\@@_info:nxx} +% 各种信息函数的缩略形式。 % \begin{macrocode} -\clist_new:N \l_@@_tmpa_clist -\clist_new:N \l_@@_tmpb_clist -\clist_new:N \l_@@_tmpc_clist +\cs_new_protected_nopar:Npn \@@_msg_new:nn { \msg_new:nnn { xeCJK } } +\cs_new_protected_nopar:Npn \@@_error:n { \msg_error:nn { xeCJK } } +\cs_new_protected_nopar:Npn \@@_error:nx { \msg_error:nnx { xeCJK } } +\cs_new_protected_nopar:Npn \@@_warning:n { \msg_warning:nn { xeCJK } } +\cs_new_protected_nopar:Npn \@@_warning:nx { \msg_warning:nnx { xeCJK } } +\cs_new_protected_nopar:Npn \@@_warning:nxx { \msg_warning:nnxx { xeCJK } } +\cs_new_protected_nopar:Npn \@@_info:nx { \msg_info:nnx { xeCJK } } +\cs_new_protected_nopar:Npn \@@_info:nxx { \msg_info:nnxx { xeCJK } } % \end{macrocode} % \end{macro} % -% \begin{macro}[internal]{\xeCJK_no_break:} +% \begin{macro}[internal]{\xeCJK_allow_break:,\xeCJK_no_break:} % \begin{macrocode} +\cs_new_protected_nopar:Npn \xeCJK_allow_break: { \tex_penalty:D \c_zero } \cs_new_protected_nopar:Npn \xeCJK_no_break: { \tex_penalty:D \c_ten_thousand } % \end{macrocode} % \end{macro} % % \begin{macro}[internal] -% {\@@_AtEndPreamble:n,\@@_AfterPreamble:n,\@@_AfterEndPreamble:n} +% {\@@_at_end_preamble:n,\@@_after_preamble:n,\@@_after_end_preamble:n} % 在 \cs{document} 前后加上各种钩子。 % \begin{macrocode} \tl_new:N \g_@@_at_end_preamble_hook_tl \tl_new:N \g_@@_after_preamble_hook_tl \tl_new:N \g_@@_after_end_preamble_hook_tl -\cs_new_protected:Npn \@@_AtEndPreamble:n #1 +\cs_new_protected:Npn \@@_at_end_preamble:n #1 { \tl_gput_right:Nn \g_@@_at_end_preamble_hook_tl {#1} } -\cs_new_protected:Npn \@@_AfterPreamble:n #1 +\cs_new_protected:Npn \@@_after_preamble:n #1 { \tl_gput_right:Nn \g_@@_after_preamble_hook_tl {#1} } -\cs_new_protected:Npn \@@_AfterEndPreamble:n #1 +\cs_new_protected:Npn \@@_after_end_preamble:n #1 { \tl_gput_right:Nn \g_@@_after_end_preamble_hook_tl {#1} } -\AtBeginDocument { \g_@@_after_preamble_hook_tl } -\tl_put_left:Nn \document { \group_end: \g_@@_at_end_preamble_hook_tl \group_begin: } -\tl_put_right:Nn \document { \g_@@_after_end_preamble_hook_tl \tex_ignorespaces:D } +\AtEndPreamble { \g_@@_at_end_preamble_hook_tl } +\AfterPreamble { \g_@@_after_preamble_hook_tl } +\AfterEndPreamble { \g_@@_after_end_preamble_hook_tl } % \end{macrocode} % \end{macro} % -% \begin{macro}[pTF,internal]{\xeCJK_if_outer_macro:c} -% 判断是否是 \cs{outer} 宏,输入的是控制序列的名字。 +% \begin{macro}[internal]{\xeCJK_reverse:nnn} +% |#1| 为 |#2| 或 |#3|,若 |#1| 和 |#2| 相等,则返回 |#3|,否则返回 |#2|。 +% \begin{macrocode} +\cs_new_nopar:Npn \xeCJK_reverse:nnn #1#2#3 + { \str_if_eq_x:nnTF {#1} {#2} {#3} {#2} } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal] +% {\xeCJK_tl_remove_outer_braces:N,\xeCJK_tl_remove_outer_braces:n} +% 去掉 |#1| 外层的分组括号。 % \begin{macrocode} -\group_begin: -\char_set_lccode:nn { `\Z } { `\t } -\char_set_lccode:nn { `\Y } { `\c } -\char_set_lccode:nn { `\; } { `\: } -\char_set_lccode:nn { `\/ } { `\\ } -\tl_map_inline:nn { \T \F \C \J \K } { \char_set_lccode:nn { `#1 } { `#1 } } -\tl_map_function:nN { \O \U \Z \E \R \M \A \Y \R \; \/ } \char_set_catcode_other:N -\tl_to_lowercase:n +\cs_new_protected_nopar:Npn \xeCJK_tl_remove_outer_braces:N #1 + { \tl_set:Nx #1 { \exp_args:NV \xeCJK_tl_remove_outer_braces:n #1 } } +\cs_new:Npn \xeCJK_tl_remove_outer_braces:n #1 + { \@@_tl_remove_outer_braces:w #1 \q_stop } +\cs_new:Npn \@@_tl_remove_outer_braces:w #1 \q_stop { - \group_end: - \prg_new_conditional:Npnn \xeCJK_if_outer_macro:c #1 { p , T , F , TF } - { - \exp_last_unbraced:Nf \@@_if_outer_macro_aux:w - { \cs_meaning:c {#1} } OUZER ~ MAYRO ; \q_stop - } - \cs_new_nopar:Npn \@@_if_outer_macro_aux:w #1 OUZER ~ MAYRO ; #2 \q_stop + \bool_if:nTF { \tl_if_single_p:n {#1} && \tl_if_head_is_group_p:n {#1} } + { \@@_tl_remove_outer_braces:w #1 \q_stop } + { \tl_trim_spaces:n {#1} } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\xeCJK_cs_add:Nnn,\xeCJK_cs_patch:Nnn} +% 在已有宏内容打补丁:在其前后附加内容或者替换掉它的某些内容,只替换掉第一次匹配 +% 的内容。 +% \begin{macrocode} +\cs_new_protected:Npn \xeCJK_cs_add:Nnn #1#2#3 + { + \tl_if_empty:nTF {#3} + { \tl_if_empty:nTF {#2} { \use_ii:nn } { \xpretocmd {#1} {#2} } } { - \if_cs_exist:w c_@@_prefix_#1_aux_tl \cs_end: - \prg_return_true: \else: \prg_return_false: \fi: + \tl_if_empty:nTF {#2} { \xapptocmd {#1} {#3} } + { \xpretocmd {#1} {#2} { \xapptocmd {#1} {#3} } { \use_ii:nn } } } - \tl_new:c { c_@@_prefix_/_aux_tl } - \tl_new:c { c_@@_prefix_/long/_aux_tl } - \tl_new:c { c_@@_prefix_/protected/_aux_tl } - \tl_new:c { c_@@_prefix_/protected/long/_aux_tl } + { \@@_info:nxx { patch-cmd } { \token_to_str:N #1 } { succeeded } } + { \@@_warning:nxx { patch-cmd } { \token_to_str:N #1 } { failed } } } +\cs_new_protected:Npn \xeCJK_cs_patch:Nnn #1#2#3 + { + \xpatchcmd {#1} {#2} {#3} + { \@@_info:nxx { patch-cmd } { \token_to_str:N #1 } { succeeded } } + { \@@_warning:nxx { patch-cmd } { \token_to_str:N #1 } { failed } } + } +\@@_msg_new:nn { patch-cmd } { Patching~'#1'~#2! } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\xeCJK_cs_clear:N,\xeCJK_cs_gclear:N} +% 让控制序列的意义为空。 +% \begin{macrocode} +\cs_new_eq:NN \xeCJK_cs_clear:N \tl_clear:N +\cs_new_eq:NN \xeCJK_cs_gclear:N \tl_gclear:N % \end{macrocode} % \end{macro} % -% \begin{macro}[TF,internal]{\xeCJK_peek_catcode_ignore_spaces:N} -% 对 \pkg{l3token} 打的补丁,使 \cs{xeCJK_peek_catcode_ignore_spaces:NTF} 等可 -% 用于 \cs{outer} 宏。 +% \begin{macro}[internal]{\xeCJK_swap_cs:NN} +% 交换 |#1| 和 |#2| 的意义。 % \begin{macrocode} -\token_new:Nn \l_@@_peek_search_token { ? } -\cs_new_protected:Npn \xeCJK_peek_catcode_ignore_spaces:NTF #1#2#3 +\cs_new_protected:Npn \xeCJK_swap_cs:NN #1#2 { - \cs_set_eq:NN \l_@@_peek_search_token #1 \prg_do_nothing: - \tl_set:Nn \@@_peek_true:w { \group_align_safe_end: #2 } - \tl_set:Nn \@@_peek_false:w { \group_align_safe_end: #3 } - \group_align_safe_begin: - \peek_after:Nw \@@_peek_ignore_spaces_execute_branches: + \cs_set_eq:NN \@@_swap_cs_aux:w #1 + \cs_set_eq:NN #1 #2 + \cs_set_eq:NN #2 \@@_swap_cs_aux:w + \cs_undefine:N \@@_swap_cs_aux:w } -\cs_new_protected:Npn \xeCJK_peek_catcode_ignore_spaces:NT #1#2 - { \xeCJK_peek_catcode_ignore_spaces:NTF #1 {#2} { } } -\cs_new_protected:Npn \xeCJK_peek_catcode_ignore_spaces:NF #1#2 - { \xeCJK_peek_catcode_ignore_spaces:NTF #1 { } {#2} } -\cs_new_nopar:Npn \@@_peek_ignore_spaces_execute_branches: +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\xeCJK_font_gset_to_current:c} +% |#1| 是控制序列的名字,令它等于当前字体命令。 +% \begin{macrocode} +\cs_new_protected_nopar:Npn \xeCJK_font_gset_to_current:c #1 { - \if_meaning:w \l_peek_token \c_space_token - \tex_afterassignment:D \@@_peek_ignore_spaces_execute_branches_aux: - \exp_after:wN \cs_set_eq:NN \exp_after:wN \@@_peek_tmp:w - \else: - \exp_after:wN \@@_peek_execute_branches_catcode: - \fi: + \exp_after:wN \cs_gset_eq:NN + \cs:w #1 \exp_after:wN \cs_end: \tex_the:D \tex_font:D } -\cs_new_protected_nopar:Npn \@@_peek_ignore_spaces_execute_branches_aux: - { \peek_after:Nw \@@_peek_ignore_spaces_execute_branches: } -\cs_new_nopar:Npn \@@_peek_execute_branches_catcode: +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal,pTF]{\xeCJK_glyph_if_exist:N} +% \changes{v3.1.0}{2012/11/19}{改进 \pkg{fontspec} 宏包中定义的 +% \cs{font_glyph_if_exist:NnTF}。} +% 判断当前字体中是否含有字符 |#1|。\pkg{fontspec} 中的类似函数在判断为真的时候, +% 会留有一个 \cs{scan_stop:},造成不必要的边界,同时也不完全可展。因此,我们重新 +% 定义它。 +% \begin{macrocode} +\prg_new_conditional:Npnn \xeCJK_glyph_if_exist:N #1 { p , T , F , TF } { - \if_catcode:w \exp_not:N \l_peek_token \exp_not:N \l_@@_peek_search_token - \exp_after:wN \@@_peek_true:w - \else: - \exp_after:wN \@@_peek_false:w - \fi: + \etex_iffontchar:D \tex_font:D `#1 \exp_stop_f: + \prg_return_true: \else: \prg_return_false: \fi: + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal,var]{\c_xeCJK_space_skip_tl} +% \changes{v3.1.0}{2012/11/18}{字间空格考虑 \cs{spaceskip} 不为零的情况。} +% 当前字体状态下,一个字间空格产生的 |glue| 的长度,包括伸展和收缩部分。 +% 没有考虑到 \cs{xspaceskip} 和 \cs{spacefactor} 的情况。 +% \begin{macrocode} +\tl_const:Nn \c_xeCJK_space_skip_tl + { + \skip_if_eq:nnTF \tex_spaceskip:D \c_zero_skip + { + \tex_fontdimen:D \c_two \tex_font:D + plus \tex_fontdimen:D \c_three \tex_font:D + minus \tex_fontdimen:D \c_four \tex_font:D + } + { \tex_spaceskip:D } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\xeCJK_glue_to_skip:nN} +% 取得一个 |glue| 的长度,包括伸展和收缩部分。 +% \begin{macrocode} +\cs_new_protected_nopar:Npn \xeCJK_glue_to_skip:nN #1#2 + { + \hbox_set:Nn \l_@@_tmp_box + { #1 \skip_gset_eq:NN \g_@@_tmp_skip \tex_lastskip:D } + \skip_set_eq:NN #2 \g_@@_tmp_skip } % \end{macrocode} % \end{macro} @@ -1119,42 +1430,39 @@ $URL: https://ctex-kit.googlecode.com/svn/trunk/xeCJK/xeCJK.dtx $ % \end{macro} % % \begin{macro}[pTF,internal]{\xeCJK_if_package_loaded:n} -% 判断宏包是否载入,可用于文档中。 +% 判断宏包是否被引入,可用于文档正文中。 % \begin{macrocode} \prg_new_conditional:Npnn \xeCJK_if_package_loaded:n #1 { p , T , F , TF } { - \tl_if_exist:cTF { ver@ #1 . \c_@@_pkg_extension_tl } - { \prg_return_true: } { \prg_return_false: } + \tl_if_exist:cTF { ver@ #1 . \c_@@_package_ext_tl } + { \prg_return_true: } + { \prg_return_false: } } -\tl_const:Nx \c_@@_pkg_extension_tl { \@pkgextension } +\tl_const:Nx \c_@@_package_ext_tl { \@pkgextension } % \end{macrocode} % \end{macro} % -% \begin{macro}[internal] -% {\@@_msg_new:nn ,\@@_error:n,\@@_error:nx,\@@_warning:nx,\@@_info:nx,\@@_info:nxx} -% 各种信息函数的缩略形式。 +% \begin{macro}[internal]{\xeCJK_int_until_do:nn,\@@_int_until_do:wn} +% 由于定义较为简单,可以比 \cs{int_until_do:nNnn} 稍微快一点点。 % \begin{macrocode} -\cs_new_nopar:Npn \@@_msg_new:nn { \msg_new:nnn { xeCJK } } -\cs_new_nopar:Npn \@@_error:n { \msg_error:nn { xeCJK } } -\cs_new_nopar:Npn \@@_error:nx { \msg_error:nnx { xeCJK } } -\cs_new_nopar:Npn \@@_warning:n { \msg_warning:nn { xeCJK } } -\cs_new_nopar:Npn \@@_warning:nx { \msg_warning:nnx { xeCJK } } -\cs_new_nopar:Npn \@@_warning:nxx { \msg_warning:nnxx { xeCJK } } -\cs_new_nopar:Npn \@@_info:nx { \msg_info:nnx { xeCJK } } -\cs_new_nopar:Npn \@@_info:nxx { \msg_info:nnxx { xeCJK } } +\cs_new_protected:Npn \xeCJK_int_until_do:nn #1#2 + { \@@_int_until_do:wn \use_none:n { \reverse_if:N \if_int_compare:w #1#2 } } +\cs_new_protected:Npn \@@_int_until_do:wn \use_none:n #1 + { #1 \exp_after:wN \@@_int_until_do:wn \fi: \use_none:n {#1} } % \end{macrocode} % \end{macro} % % \subsection{功能开关} % % \begin{macro}{xeCJKactive} +% 事实上,将开启或关闭 \XeTeX 的整个字符类机制。 % \begin{macrocode} \keys_define:nn { xeCJK / options } { - xeCJKactive .choice:, + xeCJKactive .choice: , xeCJKactive / true .code:n = { \makexeCJKactive } , xeCJKactive / false .code:n = { \makexeCJKinactive } , - xeCJKactive .default:n = { true }, + xeCJKactive .default:n = { true } } % \end{macrocode} % \end{macro} @@ -1179,7 +1487,7 @@ $URL: https://ctex-kit.googlecode.com/svn/trunk/xeCJK/xeCJK.dtx $ % \begin{center}\punctstyle{plain} % \begin{tabular}{cll} % \toprule -% 类别 & 说明 & 例子 \\ \midrule +% 类别 & 说明 & 例子 \\ \midrule % |Default| & 西文一般符号 & abc123 \\ % |CJK| & CJK 表意符号 & 汉字ぁぃぅ \\ % |FullLeft| & 全角左标点 & (《:“ \\ @@ -1187,28 +1495,26 @@ $URL: https://ctex-kit.googlecode.com/svn/trunk/xeCJK/xeCJK.dtx $ % |HalfLeft| & 半角左标点 & ( [ \{ \\ % |HalfRight| & 半角右标点 & , . ? ) ] \} \\ % |NormalSpace| & 前后原始间距的符号 & / \\ -% |Boundary| & 边界 & 空格 \\ +% |Boundary| & 边界 & 空格 \\ % \bottomrule % \end{tabular} % \end{center} % -% \begin{macro}[internal,var] -% { \c_@@_Default_class_int, \c_@@_CJK_class_int, \c_@@_FullLeft_class_int, -% \c_@@_FullRight_class_int, \c_@@_Boundary_class_int } +% \begin{macro}[internal,var]{Default,CJK,FullLeft,FullRight,Boundary} % 这五类是 \XeTeX\ 预定义的类别。 % \begin{macrocode} -\int_const:Nn \c_@@_Default_class_int { 0 } -\int_const:Nn \c_@@_CJK_class_int { 1 } -\int_const:Nn \c_@@_FullLeft_class_int { 2 } -\int_const:Nn \c_@@_FullRight_class_int { 3 } -\int_const:Nn \c_@@_Boundary_class_int { 255 } +\int_const:Nn \c_@@_Default_class_int { \c_zero } +\int_const:Nn \c_@@_CJK_class_int { \c_one } +\int_const:Nn \c_@@_FullLeft_class_int { \c_two } +\int_const:Nn \c_@@_FullRight_class_int { \c_three } +\int_const:Nn \c_@@_Boundary_class_int { \c_two_hundred_fifty_five } % \end{macrocode} % \end{macro} % -% \begin{macro}[internal]{\@@_new_class:n,\g_@@_class_seq} +% \begin{macro}[internal]{\xeCJK_new_class:n,\g_@@_class_seq} % 新建一个字符类别。 % \begin{macrocode} -\cs_new_protected_nopar:Npn \@@_new_class:n #1 +\cs_new_protected_nopar:Npn \xeCJK_new_class:n #1 { \exp_args:Nc \newXeTeXintercharclass { c_@@_#1_class_int } \clist_gclear_new:c { g_@@_#1_range_clist } @@ -1218,397 +1524,453 @@ $URL: https://ctex-kit.googlecode.com/svn/trunk/xeCJK/xeCJK.dtx $ % \end{macrocode} % \end{macro} % -% \begin{macro}[internal,var] -% { \c_@@_HalfLeft_class_int, \c_@@_HalfRight_class_int, \c_@@_NormalSpace_class_int } +% \begin{macro}[internal,var]{HalfLeft,HalfRight,NormalSpace} % 新增西文半角左/右标点和前后原始间距的符号类。 % \begin{macrocode} -\@@_new_class:n { HalfLeft } -\@@_new_class:n { HalfRight } -\@@_new_class:n { NormalSpace } +\xeCJK_new_class:n { HalfLeft } +\xeCJK_new_class:n { HalfRight } +\xeCJK_new_class:n { NormalSpace } % \end{macrocode} % \end{macro} % -% \begin{macro}[internal,var] -% {\g_@@_base_class_clist,\g_@@_CJK_class_clist,\g_@@_CJK_class_prop} +% \begin{macro}[var,internal] +% {\c_@@_HalfLeft_chars_clist,\c_@@_HalfRight_chars_clist,\c_@@_NormalSpace_chars_clist, +% \c_@@_FullLeft_chars_clist,\c_@@_FullRight_chars_clist,\c_@@_CJK_chars_clist} +% \hypertarget{CJKcharclass}{\pkg{xeCJK} 设置的各个字符类的默认范围。} % \begin{macrocode} -\clist_set:Nn \g_@@_base_class_clist +\clist_const:Nn \c_@@_HalfLeft_chars_clist + { "28 , "2D , "5B , "60 , "7B } +\clist_const:Nn \c_@@_HalfRight_chars_clist + { "21 , "22 , "25 , "27 , "29 , "2C , "2E , "3A , "3B , "3F , "5D , "7D } +\clist_const:Nn \c_@@_NormalSpace_chars_clist { "2F } +\clist_const:Nn \c_@@_FullLeft_chars_clist { - Default, CJK, FullLeft, FullRight, Boundary, - HalfLeft, HalfRight, NormalSpace + "2018 , "201C , "2116 , "3008 , "300A , "300C , "300E , "3010 , "3012 , + "3014 , "3016 , "3018 , "301A , "301D , "3036 , "E76C , "FE59 , "FE5B , + "FE5D , "FE5F , "FE60 , "FE69 , "FE6B , "FF03 , "FF04 , "FF08 , "FF20 , + "FF3B , "FF5B , "FFE0 , "FFE1 , "FFE5 , "FFE6 } -\clist_map_inline:Nn \g_@@_base_class_clist - { \clist_gclear_new:c { g_@@_#1_range_clist } } -\clist_new:N \g_@@_CJK_class_clist -\prop_new:N \g_@@_CJK_class_prop -\cs_new_protected_nopar:Npn \@@_save_CJK_class:n #1 - { - \clist_gput_right:Nx \g_@@_CJK_class_clist {#1} - \prop_gput:Nvx \g_@@_CJK_class_prop { c_@@_#1_class_int } {#1} - } -\cs_generate_variant:Nn \prop_gput:Nnn { Nvx } -\clist_map_function:nN { CJK, FullLeft, FullRight } \@@_save_CJK_class:n -% \end{macrocode} -% \end{macro} -% -% \begin{macro}[internal]{\@@_class_num:n} -% |#1| 为字符类别名称,用于取得字符类别对应的编号。 -% \begin{macrocode} -\cs_new_nopar:Npn \@@_class_num:n #1 { \tl_use:c { c_@@_#1_class_int } } -% \end{macrocode} -% \end{macro} -% -% \begin{macro}{\xeCJKDeclareCharClass} -% \begin{macro}[aux]{\@@_set_char_class_aux:Nn} -% 用于设置字符所属的类别,|#1| 为类别名称,|#2| 为字符的 |Unicode|,相邻字符用 -% 半角逗号隔开,支持类似 |"1100 -> "11FF| 起止范围的使用方式。 -% \begin{macrocode} -\NewDocumentCommand \xeCJKDeclareCharClass { s > { \TrimSpaces } m m } +\clist_const:Nn \c_@@_FullRight_chars_clist { - \@@_declare_char_class:nn {#2} {#3} - \IfBooleanT {#1} { \xeCJKResetPunctClass } + "00B7 , "2019 , "201D , "2014 , "2015 , "2025 , "2026 , "2030 , "2500 , + "3001 , "3002 , "3005 , "3006 , "3009 , "300B , "300D , "300F , "3011 , + "3015 , "3017 , "3019 , "301B , "301E , "301F , "3041 , "3043 , "3045 , + "3047 , "3049 , "3063 , "3083 , "3085 , "3087 , "308E , "309B , "309C , + "309D , "309E , "30A1 , "30A3 , "30A5 , "30A7 , "30A9 , "30C3 , "30E3 , + "30E5 , "30E7 , "30EE , "30F5 , "30F6 , "30FB , "30FC , "30FD , "30FE , + "FE50 , "FE51 , "FE52 , "FE54 , "FE55 , "FE56 , "FE57 , "FE5A , "FE5C , + "FE5E , "FE6A , "FF01 , "FF05 , "FF09 , "FF0C , "FF0E , "FF1A , "FF1B , + "FF1F , "FF3D , "FF5D , "FF61 , "FF63 , "FF64 , "FF65 , "FF67 , "FF68 , + "FF69 , "FF6A , "FF6B , "FF6C , "FF6D , "FF6E , "FF6F , "FF70 , "FF9E , + "FF9F } -\cs_new_protected_nopar:Npn \@@_declare_char_class:nn #1#2 +\clist_const:Nn \c_@@_CJK_chars_clist { - \clist_gput_right:cx { g_@@_#1_range_clist } {#2} - \clist_map_inline:xn {#2} - { - \str_if_eq_x:nnF {##1} { -> } - { - \@@_set_char_class_aux:Nn \@@_set_char_class:nnn {##1} - { \@@_class_num:n {#1} } - } - } - } -\NewDocumentCommand \@@_set_char_class_aux:Nn - { m > { \SplitArgument { 1 } { -> } } m } { #1 #2 } -\cs_generate_variant:Nn \clist_map_inline:nn { x } -% \end{macrocode} -% \end{macro} -% \end{macro} -% -% \begin{macro}[internal]{\xeCJKsetcharclass} -% |#1| 和 |#2| 为字符类别起止的 |Unicode|,|#3| 为类别名称对应编号。 -% \begin{macrocode} -\NewDocumentCommand \xeCJKsetcharclass { s m m m } - { - \@@_set_char_class:nnn {#2} {#3} {#4} - \IfBooleanF {#1} { \xeCJKResetPunctClass } - } -\cs_new_protected_nopar:Npn \@@_set_char_class:nnn #1#2#3 - { - \@@_check_num_range:nnNN {#1} {#2} \l_@@_tmpa_int \l_@@_tmpb_int - \int_set:Nn \l_@@_tmpc_int {#3} - \prop_if_in:NVTF \g_@@_CJK_class_prop \l_@@_tmpc_int - { \cs_set_eq:NN \@@_set_char_catcode:n \char_set_catcode_other:n } - { \cs_set_eq:NN \@@_set_char_catcode:n \use_none:n } - \xeCJK_int_until_do:nn { \l_@@_tmpa_int > \l_@@_tmpb_int } - { - \@@_set_char_catcode:n { \l_@@_tmpa_int } - \XeTeXcharclass \l_@@_tmpa_int = \l_@@_tmpc_int - \int_incr:N \l_@@_tmpa_int - } - } % \end{macrocode} -% \end{macro} -% -% \begin{macro}[internal]{\xeCJK_int_until_do:nn} -% \begin{macro}[aux]{\@@_int_until_do_aux:wn} -% \begin{macrocode} -\cs_new_protected:Npn \xeCJK_int_until_do:nn #1#2 - { - \@@_int_until_do_aux:wn \use_none:n - { \reverse_if:N \if_int_compare:w #1#2 } - } -\cs_new_protected:Npn \@@_int_until_do_aux:wn \use_none:n #1 - { - #1 \exp_after:wN \@@_int_until_do_aux:wn \fi: - \use_none:n {#1} - } -% \end{macrocode} -% \end{macro} -% \end{macro} -% -% \begin{macro}[internal]{\@@_check_num_range:nnNN} -% \begin{macrocode} -\cs_new_protected_nopar:Npn \@@_check_num_range:nnNN #1#2#3#4 - { - \bool_if:nTF { \xeCJK_if_blank_x_p:n {#1} || \xeCJK_if_blank_x_p:n {#2} } - { - \int_set:Nn #3 { \xeCJK_if_blank_x:nTF {#1} {#2} {#1} } - \int_set_eq:NN #3 #4 - } - { - \int_set:Nn #3 { \int_min:nn {#1} { \IfNoValueTF {#2} {#1} {#2} } } - \int_set:Nn #4 { \int_max:nn {#1} { \IfNoValueTF {#2} {#1} {#2} } } - } - } -% \end{macrocode} -% \end{macro} -% -% \begin{macro}{\xeCJKResetPunctClass} -% 用于重置标点符号所属的字符类。 -% \begin{macrocode} -\NewDocumentCommand \xeCJKResetPunctClass { } - { - \@@_declare_char_class:nn { HalfLeft } - { "28 , "2D , "5B , "60 , "7B } - \@@_declare_char_class:nn { HalfRight } - { "21 , "22 , "25 , "27 , "29 , "2C , "2E , "3A , "3B , "3F , "5D , "7D , } - \@@_declare_char_class:nn { FullLeft } - { - "2018 , "201C , "2116 , "3008 , "300A , "300C , "300E , "3010 , "3012 , - "3014 , "3016 , "3018 , "301A , "301D , "3036 , "E76C , "FE59 , "FE5B , - "FE5D , "FE5F , "FE60 , "FE69 , "FE6B , "FF03 , "FF04 , "FF08 , "FF20 , - "FF3B , "FF5B , "FFE0 , "FFE1 , "FFE5 , "FFE6 , - } - \@@_declare_char_class:nn { FullRight } - { - "00B7 , "2019 , "201D , "2014 , "2015 , "2025 , "2026 , "2030 , "2500 , - "3001 , "3002 , "3005 , "3006 , "3009 , "300B , "300D , "300F , "3011 , - "3015 , "3017 , "3019 , "301B , "301E , "301F , "3041 , "3043 , "3045 , - "3047 , "3049 , "3063 , "3083 , "3085 , "3087 , "308E , "309B , "309C , - "309D , "309E , "30A1 , "30A3 , "30A5 , "30A7 , "30A9 , "30C3 , "30E3 , - "30E5 , "30E7 , "30EE , "30F5 , "30F6 , "30FB , "30FC , "30FD , "30FE , - "FE50 , "FE51 , "FE52 , "FE54 , "FE55 , "FE56 , "FE57 , "FE5A , "FE5C , - "FE5E , "FE6A , "FF01 , "FF05 , "FF09 , "FF0C , "FF0E , "FF1A , "FF1B , - "FF1F , "FF3D , "FF5D , "FF61 , "FF63 , "FF64 , "FF65 , "FF67 , "FF68 , - "FF69 , "FF6A , "FF6B , "FF6C , "FF6D , "FF6E , "FF6F , "FF70 , "FF9E , - "FF9F , - } - } -% \end{macrocode} -% \end{macro} -% -% \hypertarget{CJKcharclass}{设置 CJK 文字的范围}。 -% \begin{macrocode} -\@@_declare_char_class:nn { CJK } - { -% \end{macrocode} -% \begin{itemize} +% \begin{itemize}[nosep,leftmargin=0pt] % \item Hangul Jamo (谚文字母) % \begin{macrocode} - "1100 -> "11FF , + "1100 -> "11FF , % \end{macrocode} % \item CJK Radicals Supplement (中日韩部首补充) % \begin{macrocode} - "2E80 -> "2EFF , + "2E80 -> "2EFF , % \end{macrocode} % \item Kangxi Radicals (康熙部首) % \begin{macrocode} - "2F00 -> "2FDF , + "2F00 -> "2FDF , % \end{macrocode} % \item Ideographic Description Characters (表意文字描述符) % \begin{macrocode} - "2FF0 -> "2FFF , + "2FF0 -> "2FFF , % \end{macrocode} % \item CJK Symbols and Punctuation (中日韩符号和标点) % \begin{macrocode} - "3000 -> "303F , + "3000 -> "303F , % \end{macrocode} % \item Hiragana (日文平假名) % \begin{macrocode} - "3040 -> "309F , + "3040 -> "309F , % \end{macrocode} % \item Katakana (日文片假名) % \begin{macrocode} - "30A0 -> "30FF , + "30A0 -> "30FF , % \end{macrocode} % \item Bopomofo (注音字母) % \begin{macrocode} - "3100 -> "312F , + "3100 -> "312F , % \end{macrocode} % \item Hangul Compatibility Jamo (谚文兼容字母) % \begin{macrocode} - "3130 -> "318F , + "3130 -> "318F , % \end{macrocode} % \item Kanbun (象形字注释标志) % \begin{macrocode} - "3190 -> "319F , + "3190 -> "319F , % \end{macrocode} % \item Bopomofo Extended (注音字母扩展) % \begin{macrocode} - "31A0 -> "31BF , + "31A0 -> "31BF , % \end{macrocode} % \item CJK Strokes (中日韩笔画) % \begin{macrocode} - "31C0 -> "31EF , + "31C0 -> "31EF , % \end{macrocode} % \item Katakana Phonetic Extensions (日文片假名语音扩展) % \begin{macrocode} - "31F0 -> "31FF , + "31F0 -> "31FF , % \end{macrocode} % \item Enclosed CJK Letters and Months (带圈中日韩字母和月份) % \begin{macrocode} - "3200 -> "32FF , + "3200 -> "32FF , % \end{macrocode} % \item CJK Compatibility (中日韩兼容) % \begin{macrocode} - "3300 -> "33FF , + "3300 -> "33FF , % \end{macrocode} % \item CJK Unified Ideographs Extension-A (中日韩统一表意文字扩展 A) % \begin{macrocode} - "3400 -> "4DBF , + "3400 -> "4DBF , % \end{macrocode} % \item Yijing Hexagrams Symbols (易经六十四卦符号) % \begin{macrocode} - "4DC0 -> "4DFF , + "4DC0 -> "4DFF , % \end{macrocode} % \item CJK Unified Ideographs (中日韩统一表意文字) % \begin{macrocode} - "4E00 -> "9FFF , + "4E00 -> "9FFF , % \end{macrocode} % \item Yi Syllables (彝文音节) % \begin{macrocode} - "A000 -> "A48F , + "A000 -> "A48F , % \end{macrocode} % \item Yi Radicals (彝文字根) % \begin{macrocode} - "A490 -> "A4CF , + "A490 -> "A4CF , % \end{macrocode} % \item Hangul Jamo Extended-A (谚文扩展 A) % \begin{macrocode} - "A960 -> "A97F , + "A960 -> "A97F , % \end{macrocode} % \item Hangul Syllables (谚文音节) % \begin{macrocode} - "AC00 -> "D7AF , + "AC00 -> "D7AF , % \end{macrocode} % \item Kana Supplement (日文假名增补) % \begin{macrocode} - "B000 -> "B0FF , + "B000 -> "B0FF , % \end{macrocode} % \item Hangul Jamo Extended-B (谚文扩展 B) % \begin{macrocode} - "D7B0 -> "D7FF , + "D7B0 -> "D7FF , % \end{macrocode} % \item CJK Compatibility Ideographs (中日韩兼容表意文字) % \begin{macrocode} - "F900 -> "FAFF , + "F900 -> "FAFF , % \end{macrocode} % \item CJK Compatibility Forms (中日韩兼容形式) % \begin{macrocode} - "FE30 -> "FE4F , + "FE30 -> "FE4F , % \end{macrocode} % \item Halfwidth and Fullwidth Forms (半角及全角形式) % \begin{macrocode} - "FF00 -> "FFEF , + "FF00 -> "FFEF , % \end{macrocode} % \item CJK Unified Ideographs Extension-B (中日韩统一表意文字扩展 B) % \begin{macrocode} - "20000 -> "2A6DF , + "20000 -> "2A6DF , % \end{macrocode} % \item CJK Unified Ideographs Extension-C (中日韩统一表意文字扩展 C) % \begin{macrocode} - "2A700 -> "2B73F , + "2A700 -> "2B73F , % \end{macrocode} % \item CJK Unified Ideographs Extension-D (中日韩统一表意文字扩展 D) % \begin{macrocode} - "2B740 -> "2B81F , + "2B740 -> "2B81F , % \end{macrocode} % \item CJK Compatibility Ideographs Supplement (中日韩兼容表意文字增补) % \begin{macrocode} - "2F800 -> "2FA1F , + "2F800 -> "2FA1F % \end{macrocode} % \end{itemize} % \begin{macrocode} } % \end{macrocode} +% \end{macro} +% +% \subsection{字符类别处理} +% +% \begin{macro}[internal,var] +% {\g_@@_base_class_seq,\g_@@_CJK_class_seq,\g_@@_CJK_class_prop} +% \begin{macrocode} +\seq_new:N \g_@@_base_class_seq +\seq_gset_split:Nnn \g_@@_base_class_seq { , } + { + Default , CJK , FullLeft , FullRight , Boundary , + HalfLeft , HalfRight , NormalSpace + } +\seq_map_inline:Nn \g_@@_base_class_seq + { \clist_gclear_new:c { g_@@_#1_range_clist } } +\seq_new:N \g_@@_CJK_class_seq +\prop_new:N \g_@@_CJK_class_prop +\cs_new_protected_nopar:Npn \@@_save_CJK_class:n #1 + { + \seq_gput_right:Nn \g_@@_CJK_class_seq {#1} + \prop_gput:Nvn \g_@@_CJK_class_prop { c_@@_#1_class_int } {#1} + } +\cs_generate_variant:Nn \prop_gput:Nnn { Nvn } +\clist_map_function:nN { CJK , FullLeft , FullRight } \@@_save_CJK_class:n +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\xeCJK_class_num:n} +% |#1| 为字符类别名称,用于取得字符类别对应的编号。 +% \begin{macrocode} +\cs_new_nopar:Npn \xeCJK_class_num:n #1 { \use:c { c_@@_#1_class_int } } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\xeCJK_value_class:n} +% |#1| 为字符的 |Unicode|,用于取得该字符所在的字符类。 +% \begin{macrocode} +\cs_new_nopar:Npn \xeCJK_value_class:n #1 + { \XeTeXcharclass \etex_numexpr:D #1 \scan_stop: } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[pTF,internal]{\xeCJK_if_same_class:NN} +% 判断两个字符是否同属于一个字符类。 +% \begin{macrocode} +\prg_new_conditional:Npnn \xeCJK_if_same_class:NN #1#2 { p , T , F , TF } + { + \if_int_compare:w \xeCJK_value_class:n {`#1} = \xeCJK_value_class:n {`#2} + \prg_return_true: \else: \prg_return_false: \fi: + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\xeCJKDeclareCharClass} +% \begin{macrocode} +\NewDocumentCommand \xeCJKDeclareCharClass { s > { \TrimSpaces } m m } + { + \xeCJK_declare_char_class:nx {#2} {#3} + \IfBooleanT {#1} { \xeCJKResetPunctClass } + } +% \end{macrocode} +% \end{macro} % -% 重置标点符号的字符类。 +% \begin{macro}[internal]{\xeCJK_declare_char_class:nn,\@@_set_char_class_aux:Nnw} +% 用于设置字符所属的类别,|#1| 为类别名称,|#2| 为字符的 |Unicode|,相邻字符用 +% 半角逗号隔开,支持类似 |"1100 -> "11FF| 起止范围的使用方式。 % \begin{macrocode} -\xeCJKResetPunctClass +\cs_new_protected_nopar:Npn \xeCJK_declare_char_class:nn #1#2 + { + \clist_set:Nn \l_@@_tmpa_clist {#2} + \clist_gconcat:ccN + { g_@@_#1_range_clist } { g_@@_#1_range_clist } \l_@@_tmpa_clist + \clist_map_inline:Nn \l_@@_tmpa_clist + { + \str_if_eq:nnF {##1} { -> } + { + \@@_set_char_class_aux:Nnw \xeCJK_set_char_class:nnn {##1} + { \xeCJK_class_num:n {#1} } + } + } + } +\NewDocumentCommand \@@_set_char_class_aux:Nnw + { m > { \SplitArgument { 1 } { -> } } m } { #1 #2 } +\cs_generate_variant:Nn \clist_gconcat:NNN { cc } +\cs_generate_variant:Nn \xeCJK_declare_char_class:nn { nx , nV } % \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\xeCJK_set_char_class:nnn} +% |#1| 和 |#2| 为字符类别起止的 |Unicode|,|#3| 为类别名称对应编号。 +% \begin{macrocode} +\NewDocumentCommand \xeCJKsetcharclass { s m m m } + { + \xeCJK_set_char_class:nnn {#2} {#3} {#4} + \IfBooleanF {#1} { \xeCJKResetPunctClass } + } +\cs_new_protected_nopar:Npn \xeCJK_set_char_class:nnn #1#2#3 + { + \@@_check_num_range:nnNN {#1} {#2} \l_@@_tmpa_int \l_@@_tmpb_int + \int_set:Nn \l_@@_tmpc_int {#3} + \prop_get:NVNTF \g_@@_CJK_class_prop \l_@@_tmpc_int \l_@@_tmpa_tl + { \cs_set_eq:NN \@@_set_char_catcode:n \char_set_catcode_other:n } + { \cs_set_eq:NN \@@_set_char_catcode:n \use_none:n } + \xeCJK_int_until_do:nn { \l_@@_tmpa_int > \l_@@_tmpb_int } + { + \@@_set_char_catcode:n { \l_@@_tmpa_int } + \XeTeXcharclass \l_@@_tmpa_int = \l_@@_tmpc_int + \int_incr:N \l_@@_tmpa_int + } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\@@_check_num_range:nnNN} +% \begin{macrocode} +\cs_new_protected_nopar:Npn \@@_check_num_range:nnNN #1#2#3#4 + { + \bool_if:nTF { \xeCJK_if_blank_x_p:n {#1} || \xeCJK_if_blank_x_p:n {#2} } + { + \int_set:Nn #3 { \xeCJK_if_blank_x:nTF {#1} {#2} {#1} } + \int_set_eq:NN #3 #4 + } + { + \int_set:Nn #3 { \int_min:nn {#1} { \IfNoValueTF {#2} {#1} {#2} } } + \int_set:Nn #4 { \int_max:nn {#1} { \IfNoValueTF {#2} {#1} {#2} } } + } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\@@_set_char_class_eq:nn} +% 将字符类 |#2| 中的字符全部设置成字符类 |#1|。只使用于 |#2| 的字符类范围为离散的 +% 逗号列表的情况。 +% \begin{macrocode} +\cs_new_protected_nopar:Npn \@@_set_char_class_eq:nn #1#2 + { + \int_set:Nn \l_@@_tmpa_int { \xeCJK_class_num:n {#1} } + \clist_map_inline:cn { c_@@_#2_chars_clist } + { \XeTeXcharclass ##1 = \l_@@_tmpa_int } + } +% \end{macrocode} +% \end{macro} % % \begin{macro}{\normalspacedchars} % 声明前后不加间距的字符。 % \begin{macrocode} \NewDocumentCommand \normalspacedchars { m } { - \tl_map_inline:nn {#1} - { \XeTeXcharclass `##1 = \@@_class_num:n { NormalSpace } } + \tl_map_inline:xn {#1} + { \XeTeXcharclass `##1 = \xeCJK_class_num:n { NormalSpace } } } -\normalspacedchars{/} +\cs_generate_variant:Nn \tl_map_inline:nn { x } % \end{macrocode} % \end{macro} % -% \begin{macro}[internal] -% {\@@_inter_class_toks:nnn,\@@_inter_class_toks:nnc,\@@_inter_class_toks:nnx} +% \begin{macro}{\xeCJKResetPunctClass} +% 用于重置标点符号所属的字符类。 +% \begin{macrocode} +\NewDocumentCommand \xeCJKResetPunctClass { } + { + \xeCJK_declare_char_class:nV { HalfLeft } \c_@@_HalfLeft_chars_clist + \xeCJK_declare_char_class:nV { HalfRight } \c_@@_HalfRight_chars_clist + \xeCJK_declare_char_class:nV { FullLeft } \c_@@_FullLeft_chars_clist + \xeCJK_declare_char_class:nV { FullRight } \c_@@_FullRight_chars_clist + } +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\xeCJKResetCharClass} +% 用于恢复 \pkg{xeCJK} 对字符类别的设置。 +% \begin{macrocode} +\NewDocumentCommand \xeCJKResetCharClass { } + { + \xeCJK_declare_char_class:nV { CJK } \c_@@_CJK_chars_clist + \xeCJK_declare_char_class:nV { NormalSpace } \c_@@_NormalSpace_chars_clist + \xeCJKResetPunctClass + } +% \end{macrocode} +% \end{macro} +% +% 设置字符类别。 +% \begin{macrocode} +\xeCJKResetCharClass +% \end{macrocode} +% +% \begin{macro}[internal]{\xeCJK_inter_class_toks:nnn} % 在相邻类别之间插入内容。 % \begin{macrocode} -\cs_new_protected_nopar:Npn \@@_inter_class_toks:nnn #1#2#3 - { \XeTeXinterchartoks \@@_class_num:n {#1} \@@_class_num:n {#2} = {#3} } -\cs_generate_variant:Nn \@@_inter_class_toks:nnn { nnc , nnx } +\cs_new_protected_nopar:Npn \xeCJK_inter_class_toks:nnn #1#2#3 + { \XeTeXinterchartoks \xeCJK_class_num:n {#1} ~ \xeCJK_class_num:n {#2} = {#3} } +\cs_generate_variant:Nn \xeCJK_inter_class_toks:nnn { nnc , nnx } % \end{macrocode} % \end{macro} % -% \begin{macro}[internal]{\@@_get_inter_class_toks:nn} +% \begin{macro}[internal]{\xeCJK_get_inter_class_toks:nn} % 取出相邻类别之间的内容。 % \begin{macrocode} -\cs_new_nopar:Npn \@@_get_inter_class_toks:nn #1#2 - { \tex_the:D \XeTeXinterchartoks \@@_class_num:n {#1} \@@_class_num:n {#2} } +\cs_new_nopar:Npn \xeCJK_get_inter_class_toks:nn #1#2 + { \tex_the:D \XeTeXinterchartoks \xeCJK_class_num:n {#1} ~ \xeCJK_class_num:n {#2} } % \end{macrocode} % \end{macro} % -% \begin{macro}[internal]{\@@_clear_inter_class_toks:nn} +% \begin{macro}[internal]{\xeCJK_clear_inter_class_toks:nn} % 清除相邻类别之间的内容。 % \begin{macrocode} -\cs_new_protected_nopar:Npn \@@_clear_inter_class_toks:nn #1#2 - { \@@_inter_class_toks:nnn {#1} {#2} { \c_empty_tl } } +\cs_new_protected_nopar:Npn \xeCJK_clear_inter_class_toks:nn #1#2 + { \xeCJK_inter_class_toks:nnn {#1} {#2} { \prg_do_nothing: } } % \end{macrocode} % \end{macro} % -% \begin{macro}[internal]{\@@_pre_inter_class_toks:nnn} +% \begin{macro}[internal]{\xeCJK_pre_inter_class_toks:nnn} % 在相邻类别之间已有的内容前增加内容。 % \begin{macrocode} -\cs_new_protected_nopar:Npn \@@_pre_inter_class_toks:nnn #1#2#3 +\cs_new_protected_nopar:Npn \xeCJK_pre_inter_class_toks:nnn #1#2#3 { - \@@_inter_class_toks:nnx {#1} {#2} - { \exp_not:n {#3} \@@_get_inter_class_toks:nn {#1} {#2} } + \xeCJK_inter_class_toks:nnx {#1} {#2} + { \exp_not:n {#3} \xeCJK_get_inter_class_toks:nn {#1} {#2} } } +\cs_generate_variant:Nn \xeCJK_pre_inter_class_toks:nnn { nnx } % \end{macrocode} % \end{macro} % -% \begin{macro}[internal]{\@@_app_inter_class_toks:nnn,\@@_app_inter_class_toks:nnc} +% \begin{macro}[internal]{\xeCJK_app_inter_class_toks:nnn} % 在相邻类别之间已有的内容后追加内容。 % \begin{macrocode} -\cs_new_protected_nopar:Npn \@@_app_inter_class_toks:nnn #1#2#3 +\cs_new_protected_nopar:Npn \xeCJK_app_inter_class_toks:nnn #1#2#3 { - \@@_inter_class_toks:nnx {#1} {#2} - { \@@_get_inter_class_toks:nn {#1} {#2} \exp_not:n {#3} } + \xeCJK_inter_class_toks:nnx {#1} {#2} + { \xeCJK_get_inter_class_toks:nn {#1} {#2} \exp_not:n {#3} } } -\cs_generate_variant:Nn \@@_app_inter_class_toks:nnn { nnc } +\cs_generate_variant:Nn \xeCJK_app_inter_class_toks:nnn { nnc , nnx } % \end{macrocode} % \end{macro} % -% \begin{macro}[internal]{\@@_copy_inter_class_toks:nnnn} +% \begin{macro}[internal]{\xeCJK_copy_inter_class_toks:nnnn} % 将 |#3| 和 |#4| 之间的内容复制到 |#1| 和 |#2| 之间。 % \begin{macrocode} -\cs_new_protected_nopar:Npn \@@_copy_inter_class_toks:nnnn #1#2#3#4 +\cs_new_protected_nopar:Npn \xeCJK_copy_inter_class_toks:nnnn #1#2#3#4 { - \@@_inter_class_toks:nnx {#1} {#2} - { \@@_get_inter_class_toks:nn {#3} {#4} } + \xeCJK_inter_class_toks:nnx {#1} {#2} + { \xeCJK_get_inter_class_toks:nn {#3} {#4} } } % \end{macrocode} % \end{macro} % -% \begin{macro}[internal]{\@@_clear_CJK_toks:} -% 清除边界与 CJK 文字、全角左右标点之间的内容。 +% \begin{macro}[internal]{\xeCJK_replace_inter_class_toks:nnnn} +% 将 |#1| 和 |#2| 之间出现的 |#3| 用 |#4| 替换。 % \begin{macrocode} -\cs_new_protected_nopar:Npn \@@_clear_CJK_toks: +\cs_new_protected_nopar:Npn \xeCJK_replace_inter_class_toks:nnnn #1#2#3#4 { - \clist_map_inline:Nn \g_@@_CJK_class_clist - { \@@_clear_inter_class_toks:nn { Boundary } {##1} } + \tl_set:Nx \l_@@_tmpa_tl { \xeCJK_get_inter_class_toks:nn {#1} {#2} } + \tl_replace_all:Nnn \l_@@_tmpa_tl {#3} {#4} + \xeCJK_inter_class_toks:nnx {#1} {#2} { \exp_not:V \l_@@_tmpa_tl } } % \end{macrocode} % \end{macro} % +% \begin{macro}[internal]{\xeCJK_clear_Boundary_and_CJK_toks:} +% 清除边界与 CJK 文字、全角左右标点之间的内容。 +% \begin{macrocode} +\cs_new_protected_nopar:Npn \xeCJK_clear_Boundary_and_CJK_toks: + { \seq_map_function:NN \g_@@_CJK_class_seq \@@_clear_Boundary_and_CJK_toks:n } +\cs_new_protected_nopar:Npn \@@_clear_Boundary_and_CJK_toks:n #1 + { \xeCJK_clear_inter_class_toks:nn { Boundary } {#1} } +% \end{macrocode} +% \end{macro} +% % \subsection{字符输出规则} % -% \hspace*{-.8\marginparwidth} +% \begin{center} % \begin{tabular}{l*8c} % \toprule -% & |Default| & |CJK| & |FullLeft| & |FullRight| & |HalfLeft| -% & |HalfRight| & |NormalSpace| & |Boundary| \\ \midrule +% & |Default| & |CJK| & |FullL| & |FullR| & |HalfL| +% & |HalfR| & |Normal| & |Bound| \\ \midrule % |Default| % & % & \tokslink{def-cjk} @@ -1629,22 +1991,22 @@ $URL: https://ctex-kit.googlecode.com/svn/trunk/xeCJK/xeCJK.dtx $ % & \tokslink{cjk-bound}\\ % |FullLeft| % & \tokslink{def-cjk} -% & \tokslink{fl-fr-bound-cjk} +% & \tokslink{fl-fr-others} % & \tokslink{cjk-fl-fr} % & \tokslink{cjk-fl-fr} % & \tokslink{def-cjk} % & \tokslink{def-cjk} % & \tokslink{def-cjk} -% & \tokslink{fl-fr-bound-cjk}\\ +% & \tokslink{fl-fr-others}\\ % |FullRight| % & \tokslink{def-cjk} -% & \tokslink{fl-fr-bound-cjk} +% & \tokslink{fl-fr-others} % & \tokslink{cjk-fl-fr} % & \tokslink{cjk-fl-fr} % & \tokslink{def-cjk} % & \tokslink{def-cjk} % & \tokslink{def-cjk} -% & \tokslink{fl-fr-bound-cjk}\\ +% & \tokslink{fl-fr-others}\\ % |HalfLeft| % & % & \tokslink{def-cjk} @@ -1671,159 +2033,281 @@ $URL: https://ctex-kit.googlecode.com/svn/trunk/xeCJK/xeCJK.dtx $ % |Boundary| % & \tokslink{bound-def} % & \tokslink{bound-cjk} -% & \tokslink{fl-fr-bound-cjk} -% & \tokslink{fl-fr-bound-cjk} +% & \tokslink{bound-fl-fr} +% & \tokslink{bound-fl-fr} % & \tokslink{bound-def} % & % & \tokslink{bound-def}\\ % \bottomrule % \end{tabular} +% \end{center} +% +% \begin{macro}[internal]{\xeCJK_class_group_begin:,\xeCJK_class_group_end:} +% \begin{macrocode} +\cs_new_eq:NN \xeCJK_class_group_begin: \c_group_begin_token +\cs_new_eq:NN \xeCJK_class_group_end: \c_group_end_token +% \end{macrocode} +% \end{macro} % % \hypertarget{def-cjk}{} % \begin{macrocode} -\clist_map_inline:nn { Default, HalfLeft, HalfRight, NormalSpace } +\clist_map_inline:nn { Default , HalfLeft , HalfRight , NormalSpace } { - \clist_map_inline:nn { CJK, FullLeft, FullRight } + \clist_map_inline:nn { CJK , FullLeft , FullRight } { - \@@_inter_class_toks:nnn {#1} {##1} + \xeCJK_inter_class_toks:nnn {#1} {##1} { - \c_group_begin_token + \xeCJK_class_group_begin: \xeCJK_select_font: - \@@_clear_inter_class_toks:nn {#1} {##1} - \@@_clear_CJK_toks: + \xeCJK_clear_inter_class_toks:nn {#1} {##1} + \xeCJK_clear_Boundary_and_CJK_toks: } - \@@_inter_class_toks:nnn {##1} {#1} { \c_group_end_token } + \xeCJK_inter_class_toks:nnn {##1} {#1} { \xeCJK_class_group_end: } } - \@@_app_inter_class_toks:nnn {#1} { CJK } { \CJKsymbol } - \clist_map_inline:nn { FullLeft, FullRight } - { \@@_app_inter_class_toks:nnc {#1} {##1} { xeCJK_CJK_and_##1:N } } + \xeCJK_app_inter_class_toks:nnn {#1} { CJK } { \CJKsymbol } + \clist_map_inline:nn { FullLeft , FullRight } + { \xeCJK_app_inter_class_toks:nnc {#1} {##1} { xeCJK_CJK_and_##1:N } } } % \end{macrocode} % % \hypertarget{bound-def}{} % \begin{macrocode} -\clist_map_inline:nn { Default, HalfLeft, NormalSpace } +\clist_map_inline:nn { Default , HalfLeft , NormalSpace } { - \@@_inter_class_toks:nnn { Boundary } {#1} + \xeCJK_inter_class_toks:nnn { Boundary } {#1} { \bool_if:nTF { \l_@@_xecglue_bool && - \int_compare_p:nNn \etex_lastnodetype:D = \c_eleven && - \skip_if_eq_p:nn \tex_lastskip:D \l_@@_space_glue_tl + \skip_if_eq_p:nn \tex_lastskip:D \c_xeCJK_space_skip_tl } { \tex_unskip:D \bool_if:nTF - { \xeCJK_if_last_node_p:n { CJK } || \xeCJK_if_last_node_p:n { CJK_space } } + { + \xeCJK_if_last_node_p:n { CJK } || + \xeCJK_if_last_node_p:n { CJK-space } + } { \CJKecglue } { \c_space_token } } { \xeCJK_if_last_node:nTF { CJK } { \CJKecglue } - { \xeCJK_if_last_node:nT { CJK_space } { \@@_space_or_xecglue: } } + { \xeCJK_if_last_node:nT { CJK-space } { \@@_space_or_xecglue: } } } } - \str_if_eq_x:nnF {#1} { NormalSpace } - { \@@_app_inter_class_toks:nnn { CJK } {#1} { \CJKecglue } } + \str_if_eq:nnF {#1} { NormalSpace } + { \xeCJK_app_inter_class_toks:nnn { CJK } {#1} { \CJKecglue } } } % \end{macrocode} % % \hypertarget{def-bound}{} % \begin{macrocode} -\clist_map_inline:nn { Default, HalfRight, NormalSpace } +\clist_map_inline:nn { Default , HalfRight , NormalSpace } { - \@@_inter_class_toks:nnn {#1} { Boundary } + \xeCJK_inter_class_toks:nnn {#1} { Boundary } { - \peek_catcode:NTF \c_space_token - { { \xeCJK_make_node:n { default_space } } } - { { \xeCJK_make_node:n { default } } } + \peek_meaning_remove:NTF \/ + { \/ { \xeCJK_make_node:n { default } } } + { + \token_if_space:NTF \l_peek_token + { { \xeCJK_make_node:n { default-space } } } + { { \xeCJK_make_node:n { default } } } + } } - \str_if_eq_x:nnF {#1} { NormalSpace } - { \@@_pre_inter_class_toks:nnn {#1} { CJK } { \CJKecglue } } + \str_if_eq:nnF {#1} { NormalSpace } + { \xeCJK_pre_inter_class_toks:nnn {#1} { CJK } { \CJKecglue } } } % \end{macrocode} % % \hypertarget{bound-cjk}{} % \begin{macrocode} -\@@_inter_class_toks:nnn { Boundary } { CJK } { \xeCJK_Boundary_and_CJK: } -% \end{macrocode} -% -% \begin{macro}[internal]{\xeCJK_Boundary_and_CJK:,\@@_check_for_glue:} -% \begin{macrocode} -\cs_new_protected_nopar:Npn \xeCJK_Boundary_and_CJK: +\xeCJK_inter_class_toks:nnn { Boundary } { CJK } { - { \@@_check_for_glue: } - \c_group_begin_token - \@@_clear_CJK_toks: + { \xeCJK_check_for_glue: } + \xeCJK_class_group_begin: + \xeCJK_clear_Boundary_and_CJK_toks: \xeCJK_select_font: \CJKsymbol } -\cs_new_protected_nopar:Npn \@@_check_for_glue: +% \end{macrocode} +% +% \begin{macro}[internal]{\xeCJK_check_for_glue:} +% \begin{macrocode} +\cs_new_protected_nopar:Npn \xeCJK_check_for_glue: { \bool_if:nTF - { \xeCJK_if_last_node_p:n { CJK } || \xeCJK_if_last_node_p:n { CJK_space } } + { \xeCJK_if_last_node_p:n { CJK } || \xeCJK_if_last_node_p:n { CJK-space } } { \CJKglue } { \bool_if:nTF { \xeCJK_if_last_node_p:n { default } || - \int_compare_p:nNn \etex_lastnodetype:D = \c_ten || - \xeCJK_if_last_node_p:n { default_itcorr } + \int_compare_p:nNn \etex_lastnodetype:D = \c_ten } { \CJKecglue } { \bool_if:nT { \l_@@_xecglue_bool && - \int_compare_p:nNn \etex_lastnodetype:D = \c_eleven && - ( \skip_if_eq_p:nn \tex_lastskip:D \l_@@_space_glue_tl || - \dim_compare_p:nNn \tex_lastskip:D = \l_@@_ecglue_dim ) + ( \skip_if_eq_p:nn \tex_lastskip:D \c_xeCJK_space_skip_tl || + \skip_if_eq_p:nn \tex_lastskip:D \l_@@_ecglue_skip ) } { \tex_unskip:D \bool_if:nTF { - \xeCJK_if_last_node_p:n { default_space } || + \xeCJK_if_last_node_p:n { default-space } || \int_compare_p:nNn \etex_lastnodetype:D = \c_ten || - \xeCJK_if_last_node_p:n { default } || - \xeCJK_if_last_node_p:n { default_itcorr } + \xeCJK_if_last_node_p:n { default } } { \CJKecglue } { \bool_if:nTF { \xeCJK_if_last_node_p:n { CJK } || - \xeCJK_if_last_node_p:n { CJK_space } + \xeCJK_if_last_node_p:n { CJK-space } } - { \bool_if:NTF \l_@@_space_bool \c_space_token \CJKglue } + { \bool_if:NTF \l_@@_reserve_space_bool \c_space_token \CJKglue } { \c_space_token } } } } } } -\tl_set:Nn \l_@@_space_glue_tl +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[pTF,internal]{\xeCJK_if_last_node:n} +% \begin{macrocode} + \prg_new_conditional:Npnn \xeCJK_if_last_node:n #1 { p , T , F , TF } + { + \if_dim:w \use:c { c_@@_#1_node_dim } = \tex_lastkern:D + \prg_return_true: \else: \prg_return_false: \fi: + } +% \end{macrocode} +% \end{macro} +% +% \changes{v3.1.0}{2012/11/14}{删除多余的 \texttt{default-itcorr} 结点。} +% +% \begin{macro}[internal]{\xeCJK_def_node:nn,\xeCJK_make_node:n} +% 用于判断插入的各种 |kern|。 +% \begin{macrocode} +\cs_new_protected_nopar:Npn \xeCJK_def_node:nn #1#2 + { + \dim_if_exist:cTF { c_@@_#1_node_dim } + { \dim_gset:cn } { \dim_const:cn } + { c_@@_#1_node_dim } {#2} + } +\cs_new_protected_nopar:Npn \xeCJK_make_node:n #1 { - \tex_fontdimen:D \c_two \tex_font:D - \@plus \tex_fontdimen:D \c_three \tex_font:D - \@minus \tex_fontdimen:D \c_four \tex_font:D + \tex_kern:D - \use:c { c_@@_#1_node_dim } + \tex_kern:D \use:c { c_@@_#1_node_dim } + } +\xeCJK_def_node:nn { CJK } { 11 sp } +\xeCJK_def_node:nn { CJK-space } { 12 sp } +\xeCJK_def_node:nn { default } { 13 sp } +\xeCJK_def_node:nn { default-space } { 14 sp } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{CJKglue} +% CJK 文字之间插入的 |glue|。 +% \begin{macrocode} +\keys_define:nn { xeCJK / options } + { CJKglue .code:n = { \cs_set_protected:Npn \CJKglue {#1} } } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{CJKecglue,xCJKecglue} +% CJK 与西文和数学行内数学公式之间自动添加的空白。 +% \begin{macrocode} +\keys_define:nn { xeCJK / options } + { + CJKecglue .code:n = + { + \cs_set_protected:Npn \CJKecglue {#1} + \xeCJK_glue_to_skip:nN \CJKecglue \l_@@_ecglue_skip + } , + xCJKecglue .choice: , + xCJKecglue / true .code:n = + { + \bool_set_true:N \l_@@_xecglue_bool + \cs_set_eq:NN \@@_space_or_xecglue: \CJKecglue + } , + xCJKecglue / false .code:n = + { + \bool_set_false:N \l_@@_xecglue_bool + \cs_set_eq:NN \@@_space_or_xecglue: \c_space_token + } , + xCJKecglue / unknown .code:n = + { + \bool_set_true:N \l_@@_xecglue_bool + \cs_set_protected:Npn \CJKecglue {#1} + \xeCJK_glue_to_skip:nN \CJKecglue \l_@@_ecglue_skip + \cs_set_eq:NN \@@_space_or_xecglue: \CJKecglue + } , + xCJKecglue .default:n = { true } + } +\skip_new:N \l_@@_ecglue_skip +\bool_new:N \l_@@_xecglue_bool +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{CJKspace} +% 是否保留 CJK 文字间的空白,默认不保留。 +% \begin{macrocode} +\keys_define:nn { xeCJK / options } + { + CJKspace .bool_set:N = \l_@@_reserve_space_bool , + space .meta:n = { CJKspace = true } , + nospace .meta:n = { CJKspace = false } } % \end{macrocode} % \end{macro} % % \hypertarget{cjk-bound}{} % \begin{macrocode} -\@@_inter_class_toks:nnn { CJK } { Boundary } +\xeCJK_inter_class_toks:nnn { CJK } { Boundary } { - \c_group_end_token + \xeCJK_class_group_end: { \xeCJK_make_node:n { CJK } } - \xeCJK_ignorespaces: + \xeCJK_ignore_spaces:w } % \end{macrocode} % +% \begin{macro}[internal]{\xeCJK_ignore_spaces:w} +% \begin{macrocode} +\cs_new_protected_nopar:Npn \xeCJK_ignore_spaces:w + { + \peek_catcode:NTF \c_space_token + { + \xeCJK_if_last_node:nT { CJK } + { \tex_unkern:D \tex_unkern:D { \xeCJK_make_node:n { CJK-space } } } + \peek_catcode_ignore_spaces:NTF \c_math_toggle_token + { \@@_space_or_xecglue: } + { + \bool_if:nT + { + \token_if_macro_p:N \l_peek_token || + ( \l_@@_reserve_space_bool && + \token_if_other_p:N \l_peek_token ) + } + { \@@_space_or_xecglue: } + } + } + { + \token_if_math_toggle:NTF \l_peek_token + { \CJKecglue } + { \cs_if_exist:NF \l_peek_token \exp_not:N } + } + } +\cs_new_eq:NN \xeCJK_ignorespaces: \xeCJK_ignore_spaces:w +% \end{macrocode} +% \end{macro} +% % \hypertarget{cjk-cjk}{} % \begin{macrocode} -\@@_inter_class_toks:nnn { CJK } { CJK } { \xeCJK_CJK_and_CJK:N } +\xeCJK_inter_class_toks:nnn { CJK } { CJK } { \xeCJK_CJK_and_CJK:N } % \end{macrocode} % % \begin{macro}[internal]{\xeCJK_CJK_and_CJK:N} @@ -1832,92 +2316,102 @@ $URL: https://ctex-kit.googlecode.com/svn/trunk/xeCJK/xeCJK.dtx $ % \end{macrocode} % \end{macro} % -% \hypertarget{fl-fr-bound-cjk}{} +% \hypertarget{bound-fl-fr}{} % \begin{macrocode} -\clist_map_inline:nn { FullLeft, FullRight } +\clist_map_inline:nn { FullLeft , FullRight } { - \@@_inter_class_toks:nnn { Boundary } {#1} + \xeCJK_inter_class_toks:nnn { Boundary } {#1} { - \c_group_begin_token - \@@_clear_CJK_toks: + \xeCJK_class_group_begin: + \xeCJK_clear_Boundary_and_CJK_toks: \xeCJK_select_font: \use:c { xeCJK_CJK_and_#1:N } } - \@@_inter_class_toks:nnn {#1} { CJK } { \CJKsymbol } - \@@_inter_class_toks:nnn {#1} { Boundary } { \c_group_end_token \tex_ignorespaces:D } } +\xeCJK_inter_class_toks:nnn { FullLeft } { Boundary } + { \xeCJK_class_group_end: \tex_ignorespaces:D } +\xeCJK_inter_class_toks:nnn { FullRight } { Boundary } + { \xeCJK_class_group_end: \CJKglue \tex_ignorespaces:D } % \end{macrocode} % +% \hypertarget{fl-fr-others}{} % \begin{macrocode} -\clist_map_inline:Nn \g_@@_base_class_clist +\xeCJK_inter_class_toks:nnn { FullLeft } { CJK } { \CJKsymbol } +\xeCJK_inter_class_toks:nnn { FullRight } { CJK } { \CJKglue \CJKsymbol } +\seq_map_inline:Nn \g_@@_base_class_seq { \bool_if:nF - { \str_if_eq_x_p:nn {#1} { FullLeft } || \str_if_eq_x_p:nn {#1} { FullRight } } + { \str_if_eq_p:nn {#1} { FullLeft } || \str_if_eq_p:nn {#1} { FullRight } } { - \@@_pre_inter_class_toks:nnn { FullLeft } {#1} { \xeCJK_no_break: } - \@@_pre_inter_class_toks:nnn { FullRight } {#1} { \xeCJK_after_FullRight: } + \xeCJK_pre_inter_class_toks:nnn { FullLeft } {#1} { \xeCJK_after_FullLeft: } + \xeCJK_pre_inter_class_toks:nnn { FullRight } {#1} { \xeCJK_after_FullRight: } } } % \end{macrocode} % % \hypertarget{cjk-fl-fr}{} % \begin{macrocode} -\clist_map_inline:nn { CJK, FullLeft, FullRight } +\clist_map_inline:nn { CJK , FullLeft , FullRight } { - \clist_map_inline:nn { FullLeft, FullRight } - { \@@_inter_class_toks:nnc {#1} {##1} { xeCJK_#1_and_##1:N } } + \clist_map_inline:nn { FullLeft , FullRight } + { \xeCJK_inter_class_toks:nnc {#1} {##1} { xeCJK_#1_and_##1:N } } } % \end{macrocode} % -% \begin{macro}[internal]{\@@_punct_rule:n} +% \begin{macro}[internal]{\@@_punct_rule:NN} % 用于抹去标点符号的左/右空白。 % \begin{macrocode} -\cs_new_protected_nopar:Npn \@@_punct_rule:n #1 +\cs_new_protected_nopar:Npn \@@_punct_rule:NN #1#2 { \tex_vrule:D - \@width \dim_eval:c { \l_@@_punct_coor_tl/rule/#1 } - \@depth \c_zero_dim - \@height \c_zero_dim \scan_stop: + width - \@@_use_punct_dim:nnn { bound } {#1} {#2} + depth \c_zero_dim + height \c_zero_dim \scan_stop: } % \end{macrocode} % \end{macro} % -% \begin{macro}[internal]{\@@_punct_glue:n} +% \begin{macro}[internal]{\@@_punct_glue:NN} % 根据所选的标点处理方式在标点符号左/右增加的空白。 % \begin{macrocode} -\cs_new_protected_nopar:Npn \@@_punct_glue:n #1 +\cs_new_protected_nopar:Npn \@@_punct_glue:NN #1#2 { \skip_horizontal:n { - \dim_eval:c { \l_@@_punct_coor_tl/glue/#1 } - \@plus \dim_eval:n { ( \tl_use:c { \l_@@_punct_coor_tl/glue/#1 } ) /4 } - \@minus \dim_eval:n { ( \tl_use:c { \l_@@_punct_coor_tl/glue/#1 } ) /2 } + \@@_use_punct_dim:nnn { glue } {#1} {#2} + minus \dim_eval:n { ( \@@_use_punct_dim:nnn { glue } {#1} {#2} ) / \c_two } } } % \end{macrocode} % \end{macro} % -% \begin{macro}[internal]{\@@_punct_kern:n} +% \begin{macro}[internal]{\@@_punct_kern:NN} % 相邻两个标点之间的间距。 % \begin{macrocode} -\cs_new_protected_nopar:Npn \@@_punct_kern:n #1 - { \tex_kern:D \dim_eval:c { \l_@@_punct_coor_tl/kern/#1 } } +\cs_new_protected_nopar:Npn \@@_punct_kern:NN #1#2 + { \tex_kern:D \@@_use_punct_dim:nnn { kern } {#1} {#2} } % \end{macrocode} % \end{macro} % -% \begin{macro}[internal]{\dim_eval:c} +% \begin{macro}[internal,var]{\g_@@_last_punct_tl} +% 用于记录当前的标点符号。 % \begin{macrocode} -\cs_generate_variant:Nn \dim_eval:n { c } +\tl_new:N \g_@@_last_punct_tl % \end{macrocode} % \end{macro} % -% \begin{macro}[internal]{\xeCJK_before_FullLeft:N} +% \begin{macro}[internal]{\xeCJK_after_FullLeft:} % \begin{macrocode} -\cs_new_protected_nopar:Npn \xeCJK_before_FullLeft:N #1 +\cs_new_protected_nopar:Npn \xeCJK_after_FullLeft: { - \tl_set:Nx \l_@@_lastpunct_tl {#1} - \@@_punct_rule:n { l/#1 } - \CJKpunctsymbol {#1} + \xeCJK_no_break: + \@@_punct_if_middle:NT \g_@@_last_punct_tl + { + \xeCJK_get_punct_bounds:NN \c_@@_left_tl \g_@@_last_punct_tl + \@@_punct_glue:NN \c_@@_left_tl \g_@@_last_punct_tl + \@@_punct_rule:NN \c_@@_right_tl \g_@@_last_punct_tl + \xeCJK_no_break: + } } % \end{macrocode} % \end{macro} @@ -1926,9 +2420,9 @@ $URL: https://ctex-kit.googlecode.com/svn/trunk/xeCJK/xeCJK.dtx $ % \begin{macrocode} \cs_new_protected_nopar:Npn \xeCJK_after_FullRight: { - \xeCJK_get_punct_bounds:nV { r } \l_@@_lastpunct_tl - \@@_punct_rule:n { r/\l_@@_lastpunct_tl } - \@@_punct_glue:n { r/\l_@@_lastpunct_tl } + \xeCJK_get_punct_bounds:NN \c_@@_right_tl \g_@@_last_punct_tl + \@@_punct_rule:NN \c_@@_right_tl \g_@@_last_punct_tl + \@@_punct_glue:NN \c_@@_right_tl \g_@@_last_punct_tl } % \end{macrocode} % \end{macro} @@ -1937,16 +2431,14 @@ $URL: https://ctex-kit.googlecode.com/svn/trunk/xeCJK/xeCJK.dtx $ % \begin{macrocode} \cs_new_protected_nopar:Npn \xeCJK_CJK_and_FullLeft:N #1 { - \xeCJK_get_punct_bounds:nN { l } {#1} + \xeCJK_get_punct_bounds:NN \c_@@_left_tl {#1} \int_compare:nNnF \etex_lastnodetype:D = \c_one - { \@@_punct_glue:n { l/#1 } } - \xeCJK_before_FullLeft:N {#1} - \@@_punct_if_middle:NT {#1} - { - \@@_punct_rule:n { lr/#1 } - \@@_punct_glue:n { l/#1 } - } + { \@@_CJK_FullLeft_glue: \@@_punct_glue:NN \c_@@_left_tl {#1} } + \tl_gset:Nx \g_@@_last_punct_tl {#1} + \@@_punct_rule:NN \c_@@_left_tl {#1} + \CJKpunctsymbol {#1} } +\cs_new_protected_nopar:Npn \@@_CJK_FullLeft_glue: { \CJKglue } % \end{macrocode} % \end{macro} % @@ -1954,17 +2446,18 @@ $URL: https://ctex-kit.googlecode.com/svn/trunk/xeCJK/xeCJK.dtx $ % \begin{macrocode} \cs_new_protected_nopar:Npn \xeCJK_CJK_and_FullRight:N #1 { - \xeCJK_get_punct_bounds:nN { r } {#1} - \@@_punct_if_long:NTF {#1} \CJKglue + \xeCJK_get_punct_bounds:NN \c_@@_right_tl {#1} + \@@_punct_if_long:NTF {#1} + { \CJKglue } { \xeCJK_no_break: \@@_punct_if_middle:NT {#1} { - \@@_punct_glue:n { r/#1 } - \@@_punct_rule:n { lr/#1 } + \@@_punct_glue:NN \c_@@_right_tl {#1} + \@@_punct_rule:NN \c_@@_left_tl {#1} } } - \tl_gset:Nx \l_@@_lastpunct_tl {#1} + \tl_gset:Nx \g_@@_last_punct_tl {#1} \CJKpunctsymbol {#1} } % \end{macrocode} @@ -1975,10 +2468,11 @@ $URL: https://ctex-kit.googlecode.com/svn/trunk/xeCJK/xeCJK.dtx $ \cs_new_protected_nopar:Npn \xeCJK_FullLeft_and_FullLeft:N #1 { \xeCJK_no_break: - \xeCJK_get_punct_bounds:nN { l } {#1} - \xeCJK_calc_kern:VN \l_@@_lastpunct_tl {#1} - \@@_punct_kern:n { \l_@@_lastpunct_tl - #1 } - \xeCJK_before_FullLeft:N {#1} + \xeCJK_get_punct_bounds:NN \c_@@_left_tl {#1} + \xeCJK_get_punct_kerning:oN \g_@@_last_punct_tl {#1} + \@@_punct_kern:NN \g_@@_last_punct_tl {#1} + \tl_gset:Nx \g_@@_last_punct_tl {#1} + \CJKpunctsymbol {#1} } % \end{macrocode} % \end{macro} @@ -1988,11 +2482,11 @@ $URL: https://ctex-kit.googlecode.com/svn/trunk/xeCJK/xeCJK.dtx $ \cs_new_protected_nopar:Npn \xeCJK_FullLeft_and_FullRight:N #1 { \xeCJK_no_break: - \xeCJK_get_punct_bounds:nN { r } {#1} - \xeCJK_calc_kern:VN \l_@@_lastpunct_tl {#1} - \@@_punct_kern:n { \l_@@_lastpunct_tl - #1 } + \xeCJK_get_punct_bounds:NN \c_@@_right_tl {#1} + \xeCJK_get_punct_kerning:oN \g_@@_last_punct_tl {#1} + \@@_punct_kern:NN \g_@@_last_punct_tl {#1} + \tl_gset:Nx \g_@@_last_punct_tl {#1} \xeCJK_no_break: - \tl_set:Nx \l_@@_lastpunct_tl {#1} \CJKpunctsymbol {#1} } % \end{macrocode} @@ -2002,13 +2496,13 @@ $URL: https://ctex-kit.googlecode.com/svn/trunk/xeCJK/xeCJK.dtx $ % \begin{macrocode} \cs_new_protected_nopar:Npn \xeCJK_FullRight_and_FullLeft:N #1 { - \@@_punct_rule:n { r/\l_@@_lastpunct_tl } - \xeCJK_get_punct_bounds:nN { l } {#1} - \xeCJK_calc_kern:VN \l_@@_lastpunct_tl {#1} - \@@_punct_kern:n { \l_@@_lastpunct_tl - #1 } - \@@_punct_nobreak: - \xeCJK_before_FullLeft:N {#1} - } + \xeCJK_get_punct_bounds:NN \c_@@_left_tl {#1} + \xeCJK_get_punct_kerning:oN \g_@@_last_punct_tl {#1} + \@@_punct_kern:NN \g_@@_last_punct_tl {#1} + \tl_gset:Nx \g_@@_last_punct_tl {#1} + \@@_punct_break: + \CJKpunctsymbol {#1} + } % \end{macrocode} % \end{macro} % @@ -2016,170 +2510,16 @@ $URL: https://ctex-kit.googlecode.com/svn/trunk/xeCJK/xeCJK.dtx $ % \begin{macrocode} \cs_new_protected_nopar:Npn \xeCJK_FullRight_and_FullRight:N #1 { - \@@_punct_rule:n { r/\l_@@_lastpunct_tl } - \xeCJK_get_punct_bounds:nN { r } {#1} - \xeCJK_calc_kern:VN \l_@@_lastpunct_tl {#1} - \@@_punct_kern:n { \l_@@_lastpunct_tl - #1 } + \xeCJK_get_punct_bounds:NN \c_@@_right_tl {#1} + \xeCJK_get_punct_kerning:oN \g_@@_last_punct_tl {#1} + \@@_punct_kern:NN \g_@@_last_punct_tl {#1} + \tl_gset:Nx \g_@@_last_punct_tl {#1} \xeCJK_no_break: - \tl_set:Nx \l_@@_lastpunct_tl {#1} \CJKpunctsymbol {#1} } % \end{macrocode} % \end{macro} % -% \begin{macro}[pTF,internal]{\xeCJK_if_last_node:n} -% \begin{macrocode} - \prg_new_conditional:Npnn \xeCJK_if_last_node:n #1 { p , T , F , TF } - { - \if_dim:w \dim_use:c { c_@@_#1_node_dim } = \tex_lastkern:D - \prg_return_true: \else: \prg_return_false: \fi: - } -% \end{macrocode} -% \end{macro} -% -% \begin{macro}[internal]{\xeCJK_def_node:nn,\xeCJK_make_node:n} -% 用于判断插入的各种 |kern|。 -% \begin{macrocode} -\cs_new_protected_nopar:Npn \xeCJK_def_node:nn #1#2 - { - \dim_if_exist:cTF { c_@@_#1_node_dim } - { \dim_gset:cn } { \dim_const:cn } - { c_@@_#1_node_dim } {#2} - } -\cs_new_protected_nopar:Npn \xeCJK_make_node:n #1 - { - \tex_kern:D - \dim_use:c { c_@@_#1_node_dim } - \tex_kern:D \dim_use:c { c_@@_#1_node_dim } - } -\xeCJK_def_node:nn { CJK } { 11 sp } -\xeCJK_def_node:nn { CJK_space } { 12 sp } -\xeCJK_def_node:nn { default } { 13 sp } -\xeCJK_def_node:nn { default_space } { 14 sp } -\xeCJK_def_node:nn { default_itcorr } { 15 sp } -% \end{macrocode} -% \end{macro} -% -% \begin{macro}{CJKglue} -% CJK 文字之间插入的 |glue|。 -% \begin{macrocode} -\keys_define:nn { xeCJK / options } - { CJKglue .code:n = { \cs_set_protected:Npn \CJKglue {#1} } } -% \end{macrocode} -% \end{macro} -% -% \begin{macro}{CJKecglue,xCJKecglue} -% CJK 与西文和数学行内数学公式之间自动添加的空白。 -% \begin{macrocode} -\keys_define:nn { xeCJK / options } - { - CJKecglue .code:n = - { - \cs_set_protected:Npn \CJKecglue {#1} - \settowidth \l_@@_ecglue_dim \CJKecglue - }, - xCJKecglue .choice:, - xCJKecglue / true .code:n = - { - \bool_set_true:N \l_@@_xecglue_bool - \cs_set_eq:NN \@@_space_or_xecglue: \CJKecglue - }, - xCJKecglue / false .code:n = - { - \bool_set_false:N \l_@@_xecglue_bool - \cs_set_eq:NN \@@_space_or_xecglue: \c_space_token - }, - xCJKecglue / unknown .code:n = - { - \bool_set_true:N \l_@@_xecglue_bool - \cs_set_protected:Npn \CJKecglue {#1} - \settowidth \l_@@_ecglue_dim \CJKecglue - \cs_set_eq:NN \@@_space_or_xecglue: \CJKecglue - }, - xCJKecglue .default:n = { true } , - } -\dim_new:N \l_@@_ecglue_dim -\bool_new:N \l_@@_xecglue_bool -% \end{macrocode} -% \end{macro} -% -% \begin{macro}{CJKspace} -% 是否保留 CJK 文字间的空白,默认不保留。 -% \begin{macrocode} -\keys_define:nn { xeCJK / options } - { - CJKspace .choice:, - CJKspace / true .code:n = { \CJKspace }, - CJKspace / false .code:n = { \CJKnospace }, - CJKspace .default:n = { true }, - space .meta:n = { CJKspace = true }, - nospace .meta:n = { CJKspace = false }, - } -% \end{macrocode} -% \end{macro} -% -% \begin{macro}[internal]{\CJKspace,\CJKnospace} -% 是否保留 CJK 文字间的空白,默认不保留。 -% \begin{macrocode} -\NewDocumentCommand \CJKspace { } - { - \bool_set_true:N \l_@@_space_bool - \cs_set_eq:NN \xeCJK_ignorespaces: \@@_peek_math: - } -\NewDocumentCommand \CJKnospace { } - { - \bool_set_false:N \l_@@_space_bool - \cs_set_eq:NN \xeCJK_ignorespaces: \@@_ignore_spaces: - } -% \end{macrocode} -% \end{macro} -% -% \begin{macro}[internal]{\@@_ignore_spaces:,\@@_peek_math:} -% \begin{macrocode} -\cs_new_protected_nopar:Npn \@@_ignore_spaces: - { - \peek_catcode:NTF \c_space_token - { - \xeCJK_if_last_node:nT { CJK } - { \tex_unkern:D \tex_unkern:D { \xeCJK_make_node:n { CJK_space } } } - \xeCJK_peek_catcode_ignore_spaces:NTF \c_math_toggle_token - { \@@_space_or_xecglue: } - { - \bool_if:nT - { - \xeCJK_if_outer_macro_p:c { l_peek_token } || - \token_if_cs_p:c { l_peek_token } - } - { \@@_space_or_xecglue: } - } - } - { - \xeCJK_if_outer_macro:cF { l_peek_token } - { - \token_if_math_toggle:cTF { l_peek_token } \CJKecglue - { \cs_if_exist:cF { l_peek_token } \exp_not:N } - } - } - } -\cs_new_protected_nopar:Npn \@@_peek_math: - { - \peek_catcode:NTF \c_space_token - { - \xeCJK_if_last_node:nT { CJK } - { \tex_unkern:D \tex_unkern:D { \xeCJK_make_node:n { CJK_space } } } - \xeCJK_peek_catcode_ignore_spaces:NF \c_space_token - { \@@_space_or_xecglue: } - } - { - \xeCJK_if_outer_macro:cF { l_peek_token } - { - \token_if_math_toggle:cTF { l_peek_token } \CJKecglue - { \cs_if_exist:cF { l_peek_token } \exp_not:N } - } - } - } -% \end{macrocode} -% \end{macro} -% % \subsection{段末孤字处理} % % \begin{macro}{CheckSingle} @@ -2187,11 +2527,11 @@ $URL: https://ctex-kit.googlecode.com/svn/trunk/xeCJK/xeCJK.dtx $ % \begin{macrocode} \keys_define:nn { xeCJK / options } { - CheckSingle .choice:, - CheckSingle / true .code:n = { \xeCJKenablechecksingle }, - CheckSingle / false .code:n = { \xeCJKdisablechecksingle }, - CheckSingle .default:n = { true }, - CJKchecksingle .meta:n = { CheckSingle = true } , + CheckSingle .choice: , + CheckSingle / true .code:n = { \xeCJKenablechecksingle } , + CheckSingle / false .code:n = { \xeCJKdisablechecksingle } , + CheckSingle .default:n = { true } , + CJKchecksingle .meta:n = { CheckSingle = true } } % \end{macrocode} % \end{macro} @@ -2199,79 +2539,77 @@ $URL: https://ctex-kit.googlecode.com/svn/trunk/xeCJK/xeCJK.dtx $ % \begin{macro}[internal]{\xeCJKenablechecksingle,\xeCJKdisablechecksingle} % 孤字处理功能开关。 % \begin{macrocode} -\bool_new:N \l_@@_checksingle_bool +\bool_new:N \l_@@_check_single_bool \NewDocumentCommand \xeCJKenablechecksingle { } { - \bool_if:NF \l_@@_checksingle_bool + \bool_if:NF \l_@@_check_single_bool { - \bool_set_true:N \l_@@_checksingle_bool - \cs_set_eq:NN \@@_checksingle_save_CJKsymbol:N \xeCJK_CJK_and_CJK:N - \cs_set_eq:NN \xeCJK_CJK_and_CJK:N \xeCJK_checksingle:N + \bool_set_true:N \l_@@_check_single_bool + \cs_set_eq:NN \@@_check_single_save:N \xeCJK_CJK_and_CJK:N + \cs_set_eq:NN \xeCJK_CJK_and_CJK:N \xeCJK_check_single:Nw } } \NewDocumentCommand \xeCJKdisablechecksingle { } { - \bool_if:NT \l_@@_checksingle_bool + \bool_if:NT \l_@@_check_single_bool { - \bool_set_false:N \l_@@_checksingle_bool - \cs_set_eq:NN \xeCJK_CJK_and_CJK:N \@@_checksingle_save_CJKsymbol:N + \bool_set_false:N \l_@@_check_single_bool + \cs_set_eq:NN \xeCJK_CJK_and_CJK:N \@@_check_single_save:N } } % \end{macrocode} % \end{macro} % -% \begin{macro}[internal]{\xeCJK_checksingle:N,\xeCJK_checksingle:NN,\xeCJK_checksingle:NNN} +% \begin{macro}[internal] +% {\xeCJK_check_single:Nw,\xeCJK_check_single:NNw,\xeCJK_check_single:NNNw} % \begin{macrocode} -\cs_new_protected_nopar:Npn \xeCJK_checksingle:N #1 +\cs_new_protected_nopar:Npn \xeCJK_check_single:Nw #1 { \peek_catcode:NTF \c_catcode_other_token - { \xeCJK_checksingle:NN {#1} } + { \xeCJK_check_single:NNw {#1} } { \bool_if:nTF { - ! ( \xeCJK_if_outer_macro_p:c { l_peek_token } ) && - \xeCJK_if_blank_x_p:n { \token_get_arg_spec:c { l_peek_token } } && - \exp_args:NNc \exp_args:No \tl_if_single_token_p:n { l_peek_token } && - \exp_args:NNc \exp_after:wN \token_if_other_p:N { l_peek_token } + \xeCJK_if_blank_x_p:n { \token_get_arg_spec:N \l_peek_token } && + \exp_args:No \tl_if_single_token_p:n \l_peek_token && + \exp_after:wN \token_if_other_p:N \l_peek_token } - { \xeCJK_checksingle:NN {#1} } - { \@@_checksingle_save_CJKsymbol:N {#1} } + { \xeCJK_check_single:NNw {#1} } + { \@@_check_single_save:N {#1} } } } -\cs_new_protected_nopar:Npn \xeCJK_checksingle:NN #1#2 +\cs_new_protected_nopar:Npn \xeCJK_check_single:NNw #1#2 { \peek_catcode:NTF \c_catcode_other_token - { \@@_checksingle_save_CJKsymbol:N {#1} #2 } + { \@@_check_single_save:N {#1} #2 } { \bool_if:nTF { - ! ( \xeCJK_if_outer_macro_p:c { l_peek_token } ) && - ( \token_if_space_p:c { l_peek_token } || - \token_if_math_toggle_p:c { l_peek_token } || - \token_if_cs_p:c { l_peek_token } ) + \token_if_space_p:N \l_peek_token || + \token_if_math_toggle_p:N \l_peek_token || + \token_if_cs_p:N \l_peek_token } { - \bool_if:nTF { \token_if_space_p:c { l_peek_token } } + \bool_if:nTF { \token_if_space_p:N \l_peek_token } { - \xeCJK_peek_catcode_ignore_spaces:NTF \c_catcode_other_token - { \@@_checksingle_save_CJKsymbol:N {#1} #2 \c_space_token } + \peek_catcode_ignore_spaces:NTF \c_catcode_other_token + { \@@_check_single_save:N {#1} #2 \c_space_token } { \bool_if:nTF { - ! ( \xeCJK_if_outer_macro_p:c { l_peek_token } ) && - ( \token_if_math_toggle_p:c { l_peek_token } || - \token_if_cs_p:c { l_peek_token } ) + \token_if_math_toggle_p:N \l_peek_token || + \token_if_cs_p:N \l_peek_token } - { \xeCJK_checksingle:NNN {#1} {#2} \c_space_token } - { \@@_checksingle_save_CJKsymbol:N {#1} #2 \c_space_token } + { \xeCJK_check_single:NNNw {#1} {#2} \c_space_token } + { \@@_check_single_save:N {#1} #2 \c_space_token } } } - { \xeCJK_checksingle:NNN {#1} {#2} { } } + { \xeCJK_check_single:NNNw {#1} {#2} { } } } - { \@@_checksingle_save_CJKsymbol:N {#1} #2 } + { \@@_check_single_save:N {#1} #2 } } } -\cs_new_protected_nopar:Npn \xeCJK_checksingle:NNN #1#2#3 +\cs_new_protected_nopar:Npn \xeCJK_check_single:NNNw #1#2#3 { \bool_if:nTF { @@ -2279,35 +2617,36 @@ $URL: https://ctex-kit.googlecode.com/svn/trunk/xeCJK/xeCJK.dtx $ \token_if_eq_meaning_p:NN \l_peek_token \[ % \] } { \CJKsymbol {#1} \xeCJK_no_break: #2 } - { \xeCJK_checksingle_env:NNN {#1} {#2} {#3} } + { \xeCJK_check_single_env:NNNw {#1} {#2} {#3} } } % \end{macrocode} % \end{macro} % -% \begin{macro}[internal]{\xeCJK_checksingle_env:NNN,\xeCJK_checksingle_env:NNNNn} +% \begin{macro}[internal] +% {\xeCJK_check_single_env:NNNw,\xeCJK_check_single_env:NNNNn} % \begin{macrocode} -\cs_new_protected_nopar:Npn \xeCJK_checksingle_env:NNN #1#2#3 +\cs_new_protected_nopar:Npn \xeCJK_check_single_env:NNNw #1#2#3 { \peek_catcode_remove:NTF \c_math_toggle_token { \peek_catcode:NTF \c_math_toggle_token { \CJKsymbol {#1} \xeCJK_no_break: #2 \c_math_toggle_token } - { \@@_checksingle_save_CJKsymbol:N {#1} #2#3 \c_math_toggle_token } + { \@@_check_single_save:N {#1} #2#3 \c_math_toggle_token } } { \peek_meaning_remove:NTF \begin - { \xeCJK_checksingle_env:NNNNn {#1} {#2} {#3} \begin } + { \xeCJK_check_single_env:NNNNn {#1} {#2} {#3} \begin } { \peek_meaning_remove:NTF \end - { \xeCJK_checksingle_env:NNNNn {#1} {#2} {#3} \end } - { \@@_checksingle_save_CJKsymbol:N {#1} #2#3 } + { \xeCJK_check_single_env:NNNNn {#1} {#2} {#3} \end } + { \@@_check_single_save:N {#1} #2#3 } } } } -\cs_new_protected_nopar:Npn \xeCJK_checksingle_env:NNNNn #1#2#3#4#5 +\cs_new_protected_nopar:Npn \xeCJK_check_single_env:NNNNn #1#2#3#4#5 { \clist_if_in:NnTF \g_@@_inline_env_clist {#5} - { \@@_checksingle_save_CJKsymbol:N {#1} #2#3 } + { \@@_check_single_save:N {#1} #2#3 } { \CJKsymbol {#1} \xeCJK_no_break: #2 } \scan_stop: #4 {#5} } @@ -2323,54 +2662,32 @@ $URL: https://ctex-kit.googlecode.com/svn/trunk/xeCJK/xeCJK.dtx $ { \clist_gput_right:Nx \g_@@_inline_env_clist {#1} \clist_gremove_duplicates:N \g_@@_inline_env_clist - }, + } , InlineEnv- .code:n = { \clist_map_inline:xn {#1} { \clist_gremove_all:Nn \g_@@_inline_env_clist {##1} } - }, + } } +\cs_generate_variant:Nn \clist_map_inline:nn { x } % \end{macrocode} % \end{macro} % -% \begin{macrocode} -\cs_generate_variant:Nn \token_if_cs_p:N { c } -\cs_generate_variant:Nn \token_if_space_p:N { c } -\cs_generate_variant:Nn \token_get_arg_spec:N { c } -\cs_generate_variant:Nn \token_if_math_toggle_p:N { c } -\cs_generate_variant:Nn \token_if_math_toggle:NTF { c } -% \end{macrocode} -% % \subsection{增加 CJK 子分区} % -% \begin{macro}[internal]{\@@_UL_subclass_patch_tl,\g_@@_CJK_subclass_clist} -% \begin{macrocode} -\tl_new:N \@@_UL_subclass_patch_tl -\clist_new:N \g_@@_CJK_subclass_clist -% \end{macrocode} -% \end{macro} -% -% \begin{macro}[internal]{\@@_erase_CJKsymbol:, \@@_restore_CJKsymbol:} +% \begin{macro}[internal]{\g_@@_CJK_sub_class_seq} % \begin{macrocode} -\cs_new_protected_nopar:Npn \@@_erase_CJKsymbol: - { - \cs_gset_eq:NN \CJKsymbol_Block \CJKsymbol - \cs_gset_eq:NN \CJKsymbol \prg_do_nothing: - } -\cs_new_protected_nopar:Npn \@@_restore_CJKsymbol: - { - \cs_gset_eq:NN \CJKsymbol \CJKsymbol_Block - \CJKsymbol - } +\seq_new:N \g_@@_CJK_sub_class_seq % \end{macrocode} % \end{macro} % % \begin{macro}{\xeCJKDeclareSubCJKBlock} % 声明 CJK 子区范围,|#1| 为自定义名称,|#2| 为子区的 |Unicode| 范围。 % \begin{macrocode} -\NewDocumentCommand \xeCJKDeclareSubCJKBlock { s m m } +\NewDocumentCommand \xeCJKDeclareSubCJKBlock + { s > { \TrimSpaces } m > { \TrimSpaces } m } { - \xeCJKDeclareSubCharClass { CJK } {#2} {#3} + \xeCJK_declare_sub_char_class:nxx { CJK } {#2} {#3} \IfBooleanT {#1} { \xeCJKResetPunctClass } } \@onlypreamble \xeCJKDeclareSubCJKBlock @@ -2386,7 +2703,7 @@ $URL: https://ctex-kit.googlecode.com/svn/trunk/xeCJK/xeCJK.dtx $ \bool_if:NF \l_@@_sub_cancel_bool { \bool_set_true:N \l_@@_sub_cancel_bool - \@@_sub_restore_or_cancel:n {#2} + \@@_sub_restore_or_cancel:x {#2} \IfBooleanT {#1} { \xeCJKResetPunctClass } } } @@ -2395,23 +2712,29 @@ $URL: https://ctex-kit.googlecode.com/svn/trunk/xeCJK/xeCJK.dtx $ \bool_if:NT \l_@@_sub_cancel_bool { \bool_set_false:N \l_@@_sub_cancel_bool - \@@_sub_restore_or_cancel:n {#2} + \@@_sub_restore_or_cancel:x {#2} \IfBooleanT {#1} { \xeCJKResetPunctClass } } } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\@@_sub_restore_or_cancel:n} +% \begin{macrocode} \cs_new_protected_nopar:Npn \@@_sub_restore_or_cancel:n #1 { - \clist_map_inline:xn {#1} + \clist_map_inline:nn {#1} { \int_if_exist:cTF { c_@@_ CJK/##1 _class_int } { - \@@_declare_char_class:nn + \xeCJK_declare_char_class:nx { CJK \bool_if:NF \l_@@_sub_cancel_bool { /##1 } } { \tl_use:c { g_@@_CJK/##1_range_clist } } } { \@@_error:nx { SubBlock-undefined } {##1} } } } +\cs_generate_variant:Nn \@@_sub_restore_or_cancel:n { x } \@@_msg_new:nn { SubBlock-undefined } { The~CJK~sub~block~'#1'~is~undefined.\\\\ @@ -2421,21 +2744,19 @@ $URL: https://ctex-kit.googlecode.com/svn/trunk/xeCJK/xeCJK.dtx $ % \end{macrocode} % \end{macro} % -% \begin{macro}[internal]{\xeCJKDeclareSubCharClass} +% \begin{macro}[internal]{\xeCJK_declare_sub_char_class:nnn} % \begin{macrocode} -\NewDocumentCommand \xeCJKDeclareSubCharClass - { > { \TrimSpaces } m > { \TrimSpaces } m m } +\cs_new_protected_nopar:Npn \xeCJK_declare_sub_char_class:nnn #1#2#3 { \int_if_exist:cF { c_@@_ #1/#2 _class_int } { - \@@_new_class:n { #1/#2 } + \xeCJK_new_class:n { #1/#2 } \@@_set_sub_class_toks:nn {#1} {#2} \@@_new_sub_key:n {#2} - \@@_UL_subclass_patch:nn {#1} {#2} } - \@@_declare_char_class:nn { #1/#2 } {#3} + \xeCJK_declare_char_class:nn { #1/#2 } {#3} } -\@onlypreamble \xeCJKDeclareSubCharClass +\cs_generate_variant:Nn \xeCJK_declare_sub_char_class:nnn { nxx } % \end{macrocode} % \end{macro} % @@ -2443,117 +2764,80 @@ $URL: https://ctex-kit.googlecode.com/svn/trunk/xeCJK/xeCJK.dtx $ % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_set_sub_class_toks:nn #1#2 { - \clist_map_inline:Nn \g_@@_base_class_clist + \seq_map_inline:Nn \g_@@_base_class_seq { - \@@_copy_inter_class_toks:nnnn { #1/#2 } {##1} {#1} {##1} - \@@_copy_inter_class_toks:nnnn {##1} { #1/#2 } {##1} {#1} - \str_if_eq_x:nnTF {##1} { CJK } + \xeCJK_copy_inter_class_toks:nnnn { #1/#2 } {##1} {#1} {##1} + \xeCJK_copy_inter_class_toks:nnnn {##1} { #1/#2 } {##1} {#1} + \str_if_eq:nnTF {##1} { CJK } { - \@@_pre_inter_class_toks:nnn {##1} { #1/#2 } + \xeCJK_pre_inter_class_toks:nnn {##1} { #1/#2 } { \@@_switch_font:nn {#1} {#2} } } { - \@@_pre_inter_class_toks:nnn {##1} { #1/#2 } - { \@@_erase_CJKsymbol: } - \@@_app_inter_class_toks:nnn {##1} { #1/#2 } - { \@@_switch_font:nn {#1} {#2} \@@_restore_CJKsymbol: } + \xeCJK_replace_inter_class_toks:nnnn {##1} { #1/#2 } + { \CJKsymbol } + { \@@_switch_font:nn {#1} {#2} \CJKsymbol } } } - \@@_copy_inter_class_toks:nnnn { #1/#2 } { #1/#2 } {#1} {#1} - \clist_if_empty:NF \g_@@_CJK_subclass_clist + \xeCJK_copy_inter_class_toks:nnnn { #1/#2 } { #1/#2 } {#1} {#1} + \seq_map_inline:Nn \g_@@_CJK_sub_class_seq { - \clist_map_inline:Nn \g_@@_CJK_subclass_clist - { - \@@_copy_inter_class_toks:nnnn { #1/#2 } { #1/##1 } {#1} {#1} - \@@_copy_inter_class_toks:nnnn { #1/##1 } { #1/#2 } {#1} {#1} - \@@_pre_inter_class_toks:nnn { #1/#2 } { #1/##1 } - { \@@_switch_font:nn {#2} {##1} } - \@@_pre_inter_class_toks:nnn { #1/##1 } { #1/#2 } - { \@@_switch_font:nn {##1} {#2} } - } + \xeCJK_copy_inter_class_toks:nnnn { #1/#2 } { #1/##1 } {#1} {#1} + \xeCJK_copy_inter_class_toks:nnnn { #1/##1 } { #1/#2 } {#1} {#1} + \xeCJK_pre_inter_class_toks:nnn { #1/#2 } { #1/##1 } + { \@@_switch_font:nn {#2} {##1} } + \xeCJK_pre_inter_class_toks:nnn { #1/##1 } { #1/#2 } + { \@@_switch_font:nn {##1} {#2} } } - \clist_gput_right:Nn \g_@@_CJK_subclass_clist {#2} + \seq_gput_right:Nn \g_@@_CJK_sub_class_seq {#2} \@@_save_CJK_class:n { #1/#2 } - \clist_map_inline:nn { CJK, FullLeft, FullRight } + \clist_map_inline:nn { CJK , FullLeft , FullRight } { - \@@_pre_inter_class_toks:nnn { #1/#2 } {##1} + \xeCJK_pre_inter_class_toks:nnn { #1/#2 } {##1} { \@@_switch_font:nn {#2} {#1} } } } % \end{macrocode} % \end{macro} % -% \begin{macro}[internal]{\@@_UL_subclass_patch:nn} +% \subsection{标点处理} +% +% \cs{XeTeXglyphbouds} 可以得到一个字符的左右边距,用于标点压缩。如果它不可用,则 +% 在文档中只能使用 |plain| 这一标点格式原样输出标点。 % \begin{macrocode} -\cs_new_protected_nopar:Npn \@@_UL_subclass_patch:nn #1#2 +\@@_msg_new:nn { XeTeX-too-old } { - \tl_put_right:Nn \@@_UL_subclass_patch_tl - { - \clist_map_inline:nn { Default, HalfLeft, HalfRight } - { - \str_if_eq_x:nnTF {##1} { HalfLeft } - { \@@_inter_class_toks:nnn {#1} { #1/#2 } { \CJKecglue \CJKsymbol } } - { \@@_inter_class_toks:nnn {#1} { #1/#2 } { \CJKsymbol } } - \@@_inter_class_toks:nnn { Boundary } { #1/#2 } - { - \@@_erase_CJKsymbol: - \xeCJK_Boundary_and_CJK: - \@@_switch_font:nn {#1} {#2} - \@@_restore_CJKsymbol: - } - } - } + \token_to_str:N \XeTeXglyphbounds \ is~not~defined.\\ + CJK~punctuation~kerning~will~not~be~available.\\\\ + You~have~to~update~XeTeX~to~the~version~0.9995.0~or~later. + } +\cs_if_exist:NF \XeTeXglyphbounds + { + \@@_error:n { XeTeX-too-old } + \@@_after_end_preamble:n { \xeCJKsetup { PunctStyle = plain } } } % \end{macrocode} -% \end{macro} % -% \subsection{标点处理} -% -% \begin{macro}[internal,var]{\g_@@_punctstyle_clist} -% 标点处理方式。 +% \begin{macro}{\xeCJKsetwidth} +% 手动设置参数中的标点符号的宽度。 % \begin{macrocode} -\clist_new:N \g_@@_punctstyle_clist -\clist_set:Nn \g_@@_punctstyle_clist - { CCT , halfwidth , fullwidth , marginkerning , mixedwidth , plain } -\clist_map_inline:Nn \g_@@_punctstyle_clist - { \tl_const:cn { c_@@_ps_#1_tl } {#1} } +\NewDocumentCommand \xeCJKsetwidth { m m } + { \tl_map_inline:xn {#1} { \tl_gset:cn { g_@@_punct_width/##1/tl } {#2} } } % \end{macrocode} % \end{macro} % -% \begin{macro}[internal]{\keys_define:nx} +% \begin{macro}{\xeCJKsetkern} +% 手动设置相邻标点的距离。 % \begin{macrocode} -\cs_generate_variant:Nn \keys_define:nn { nx } +\NewDocumentCommand \xeCJKsetkern { m m m } + { \tl_gset:cn { g_@@_punct/kern/#1/#2/tl } {#3} } % \end{macrocode} % \end{macro} % -% \begin{macro}{PunctStyle} +% \begin{macro}[internal,var]{\c_@@_left_tl,\c_@@_right_tl} % \begin{macrocode} -\keys_define:nn { xeCJK / options } - { - PunctStyle .choice_code:n = - { - \tl_set:Nx \l_xeCJK_punctstyle_tl { \l_keys_choice_tl } - \tl_if_eq:NNT \l_xeCJK_punctstyle_tl \c_@@_ps_plain_tl - { \xeCJKallowbreakbetweenpuncts } - }, - } -\keys_define:nx { xeCJK / options } - { PunctStyle .generate_choices:n = { \exp_not:V \g_@@_punctstyle_clist } } -\keys_define:nn { xeCJK / options } - { - PunctStyle / banjiao .meta:n = { PunctStyle = halfwidth }, - PunctStyle / quanjiao .meta:n = { PunctStyle = fullwidth }, - PunctStyle / kaiming .meta:n = { PunctStyle = mixedwidth }, - PunctStyle / hangmobanjiao .meta:n = { PunctStyle = marginkerning }, - PunctStyle / unknown .code:n = - { \@@_error:nx { PunctStyle-undefined } \l_keys_value_tl }, - } -\@@_msg_new:nn { PunctStyle-undefined } - { - Punctstyle~"#1"~is~not~available. \\\\ - You~can~only~use~one~of\\\\ - "\g_@@_punctstyle_clist".\\ - } +\tl_const:Nn \c_@@_left_tl { left } +\tl_const:Nn \c_@@_right_tl { right } % \end{macrocode} % \end{macro} % @@ -2563,421 +2847,659 @@ $URL: https://ctex-kit.googlecode.com/svn/trunk/xeCJK/xeCJK.dtx $ % \begin{macrocode} \keys_define:nn { xeCJK / options } { - AllowBreakBetweenPuncts .choice:, - AllowBreakBetweenPuncts / true .code:n = { \xeCJKallowbreakbetweenpuncts }, - AllowBreakBetweenPuncts / false .code:n = { \xeCJKnobreakbetweenpuncts }, - AllowBreakBetweenPuncts .default:n = { true }, - KaiMingPunct .code:n = { \@@_set_special_punct:nn { mixedwidth } {#1} }, - KaiMingPunct+ .code:n = { \@@_add_special_punct:nn { mixedwidth } {#1} }, - KaiMingPunct- .code:n = { \@@_sub_special_punct:nn { mixedwidth } {#1} }, - LongPunct .code:n = { \@@_set_special_punct:nn { long } {#1} }, - LongPunct+ .code:n = { \@@_add_special_punct:nn { long } {#1} }, - LongPunct- .code:n = { \@@_sub_special_punct:nn { long } {#1} }, - MiddlePunct+ .code:n = { \@@_add_special_punct:nn { middle } {#1} }, - MiddlePunct .code:n = { \@@_set_special_punct:nn { middle } {#1} }, - MiddlePunct- .code:n = { \@@_sub_special_punct:nn { middle } {#1} }, - PunctWidth .tl_gset:N = \g_@@_punct_width_tl , + AllowBreakBetweenPuncts .choice: , + AllowBreakBetweenPuncts / true .code:n = + { \cs_set_eq:NN \@@_punct_break: \xeCJK_allow_break: } , + AllowBreakBetweenPuncts / false .code:n = + { \cs_set_eq:NN \@@_punct_break: \xeCJK_no_break: } , + AllowBreakBetweenPuncts .default:n = { true } , + KaiMingPunct .code:n = { \@@_set_special_punct:nn { mixed_width } {#1} } , + KaiMingPunct+ .code:n = { \@@_add_special_punct:nn { mixed_width } {#1} } , + KaiMingPunct- .code:n = { \@@_sub_special_punct:nn { mixed_width } {#1} } , + LongPunct .code:n = { \@@_set_special_punct:nn { long } {#1} } , + LongPunct+ .code:n = { \@@_add_special_punct:nn { long } {#1} } , + LongPunct- .code:n = { \@@_sub_special_punct:nn { long } {#1} } , + MiddlePunct .code:n = { \@@_set_special_punct:nn { middle } {#1} } , + MiddlePunct+ .code:n = { \@@_add_special_punct:nn { middle } {#1} } , + MiddlePunct- .code:n = { \@@_sub_special_punct:nn { middle } {#1} } , + PunctWidth .tl_gset:N = \g_@@_punct_width_tl } % \end{macrocode} % \end{macro} % -% \begin{macro}[internal]{\xeCJKallowbreakbetweenpuncts, \xeCJKnobreakbetweenpuncts} -% \begin{macrocode} -\NewDocumentCommand \xeCJKallowbreakbetweenpuncts { } - { \cs_set_eq:NN \@@_punct_nobreak: \@@_zero_glue: } -\NewDocumentCommand \xeCJKnobreakbetweenpuncts { } - { \cs_set_eq:NN \@@_punct_nobreak: \xeCJK_no_break: } -\cs_new_protected_nopar:Npn \@@_zero_glue: { \skip_horizontal:N \c_zero_skip } -% \end{macrocode} -% \end{macro} -% % \begin{macro}[internal] -% {\g_@@_special_ps_clist, \@@_set_special_punct:nn, +% {\g_@@_special_punct_clist,\@@_set_special_punct:nn, % \@@_add_special_punct:nn, \@@_sub_special_punct:nn} % \begin{macrocode} -\clist_set:Nn \g_@@_special_ps_clist { mixedwidth , long , middle } -\clist_map_inline:Nn \g_@@_special_ps_clist - { - \tl_new:c { l_@@_#1_punct_tl } - \prop_new:c { l_@@_#1_punct_prop } - } +\clist_new:N \g_@@_special_punct_clist +\clist_gset:Nn \g_@@_special_punct_clist { mixed_width , long , middle } +\cs_new_nopar:Npn \@@_special_punct_seq:n #1 { g_@@_special_punct_#1_seq } +\cs_new_nopar:Npn \@@_special_punct_tl:nN #1#2 { g_@@_special_punct_#1_#2_tl } +\clist_map_inline:Nn \g_@@_special_punct_clist + { \seq_new:c { \@@_special_punct_seq:n {#1} } } \cs_new_protected_nopar:Npn \@@_set_special_punct:nn #1#2 { - \tl_set:cx { l_@@_#1_punct_tl } {#2} - \prop_clear:c { l_@@_#1_punct_prop } - \tl_map_inline:cn { l_@@_#1_punct_tl } - { \prop_put:cnn { l_@@_#1_punct_prop } {##1} { } } + \seq_map_inline:cn { \@@_special_punct_seq:n {#1} } + { \cs_undefine:c { \@@_special_punct_tl:nN {#1} {##1} } } + \seq_gclear:c { \@@_special_punct_seq:n {#1} } + \tl_map_inline:xn {#2} + { + \tl_new:c { \@@_special_punct_tl:nN {#1} {##1} } + \seq_gput_right:cn { \@@_special_punct_seq:n {#1} } {##1} + } } \cs_new_protected_nopar:Npn \@@_add_special_punct:nn #1#2 { - \tl_put_right:cx { l_@@_#1_punct_tl } {#2} - \tl_map_inline:cn { l_@@_#1_punct_tl } - { \prop_put:cnn { l_@@_#1_punct_prop } {##1} { } } + \tl_map_inline:xn {#2} + { + \seq_if_in:cnF { \@@_special_punct_seq:n {#1} } {##1} + { + \tl_new:c { \@@_special_punct_tl:nN {#1} {##1} } + \seq_gput_right:cn { \@@_special_punct_seq:n {#1} } {##1} + } + } } \cs_new_protected_nopar:Npn \@@_sub_special_punct:nn #1#2 { \tl_map_inline:xn {#2} { - \tl_remove_all:cn { l_@@_#1_punct_tl } {##1} - \prop_remove:cn { l_@@_#1_punct_prop } {##1} + \cs_undefine:c { \@@_special_punct_tl:nN {#1} {##1} } + \seq_gremove_all:cn { \@@_special_punct_seq:n {#1} } {##1} } } -\cs_generate_variant:Nn \tl_map_inline:nn { x } % \end{macrocode} % \end{macro} % -% \begin{macro}[internal]{\dim_set:Nc,\dim_add:Nc,\dim_min:cc} -% \begin{macrocode} -\cs_generate_variant:Nn \dim_set:Nn { Nc } -\cs_generate_variant:Nn \dim_add:Nn { Nc } -\cs_generate_variant:Nn \dim_min:nn { cc } -% \end{macrocode} -% \end{macro} -% -% \begin{macro}[internal]{\xeCJK_dim_set_max:Nn,\xeCJK_dim_set_min:Nn} -% \begin{macrocode} -\cs_new_protected_nopar:Npn \xeCJK_dim_set_max:Nn #1#2 - { \dim_set:Nn #1 { \dim_max:nn {#1} {#2} } } -\cs_new_protected_nopar:Npn \xeCJK_dim_set_min:Nn #1#2 - { \dim_set:Nn #1 { \dim_min:nn {#1} {#2} } } -% \end{macrocode} -% \end{macro} -% -% \begin{macro}[internal,var]{\l_@@_punct_coor_tl} -% 记录当前字体状态下的标点处理方式。 +% \begin{macro}[pTF,internal] +% {\@@_punct_if_right:N,\@@_punct_if_long:N, +% \@@_punct_if_middle:N,\@@_punct_if_mixed_width:N} % \begin{macrocode} -\tl_set:Nn \l_@@_punct_coor_tl { \l_xeCJK_font_coor_tl/\l_xeCJK_punctstyle_tl } +\prg_new_conditional:Npnn \@@_punct_if_right:N #1 { p , T , F , TF } + { + \if_int_compare:w \xeCJK_value_class:n {`#1} = \xeCJK_class_num:n { FullRight } + \prg_return_true: \else: \prg_return_false: \fi: + } +\cs_generate_variant:Nn \prg_new_conditional:Npnn { c } +\clist_map_inline:Nn \g_@@_special_punct_clist + { + \prg_new_conditional:cpnn { @@_punct_if_#1:N } ##1 { p , T , F , TF } + { + \if_cs_exist:w \@@_special_punct_tl:nN {#1} {##1} \cs_end: + \prg_return_true: \else: \prg_return_false: \fi: + } + } % \end{macrocode} % \end{macro} % -% \begin{macro}[internal]{\xeCJK_get_punct_bounds:nN} -% |#1| 为 |l/r|,|#2| 为标点字符,返回标点的实际左/右空白的负值和根据标点处理方式 -% 决定添加的左/右空白。全角方式直接添加标点的实际左/右空白;半角方式添加标点左右空白 -% 中的最小值;开明方式与半角相同,只在开明标点再增加实际左/右空白的一半。 -% \begin{macrocode} -\cs_new_protected_nopar:Npn \xeCJK_get_punct_bounds:nN #1#2 - { - \tl_if_exist:cF { \l_@@_punct_coor_tl/rule/#1/#2 } +% \begin{macro}[internal] +% {\@@_punct_dim_csname:nn,\@@_punct_dim_csname:nnn,\@@_punct_dim_csname:nnnn, +% \@@_use_punct_dim:nnn,\@@_use_punct_dim:nn, +% \@@_gset_punct_dim:nnx,\@@_gset_punct_dim:nnnx,\@@_gset_punct_dim:nnnnx} +% 一些用于记录的辅助函数。 +% \begin{macrocode} +\cs_new_nopar:Npn \@@_punct_dim_csname:nn #1#2 + { g__\l_xeCJK_current_font_tl/\l_xeCJK_punct_style_tl/#1/#2/tl } +\cs_new_nopar:Npn \@@_punct_dim_csname:nnn + { \@@_punct_dim_csname:nnnn { \l_xeCJK_punct_style_tl } } +\cs_new_nopar:Npn \@@_punct_dim_csname:nnnn #1#2#3#4 + { g__\l_xeCJK_current_font_tl/#1/#2/#3/#4/tl } +\cs_new_nopar:Npn \@@_use_punct_dim:nn #1#2 + { \tl_use:c { \@@_punct_dim_csname:nn {#1} {#2} } } +\cs_new_nopar:Npn \@@_use_punct_dim:nnn #1#2#3 + { \tl_use:c { \@@_punct_dim_csname:nnn {#1} {#2} {#3} } } +\cs_new_protected_nopar:Npn \@@_gset_punct_dim:nnx #1#2#3 + { \tl_gset:cx { \@@_punct_dim_csname:nn {#1} {#2} } {#3} } +\cs_new_protected_nopar:Npn \@@_gset_punct_dim:nnnx #1#2#3#4 + { \tl_gset:cx { \@@_punct_dim_csname:nnn {#1} {#2} {#3} } {#4} } +\cs_new_protected_nopar:Npn \@@_gset_punct_dim:nnnnx #1#2#3#4#5 + { \tl_gset:cx { \@@_punct_dim_csname:nnnn {#1} {#2} {#3} {#4} } {#5} } +% \end{macrocode} +% \end{macro} +% +% \changes{v3.1.0}{2012/11/14}{使用 \pkg{xtemplate} 宏包的机制来组织标点符号的处理。} +% +% 定义标点处理模板。 +% \begin{macrocode} +\DeclareObjectType { xeCJK / punctuation } { 3 } +% \end{macrocode} +% +% \begin{macrocode} +\DeclareTemplateInterface { xeCJK / punctuation } { basic } { 3 } + { + enabled-global-setting : boolean = true , + fixed-punct-width : length = \c_max_dim , + fixed-punct-ratio : real = \c_one_fp , + mixed-punct-width : length = \KeyValue { fixed-punct-width } , + mixed-punct-ratio : real = \KeyValue { fixed-punct-ratio } , + middle-punct-width : length = \KeyValue { fixed-punct-width } , + middle-punct-ratio : real = \KeyValue { fixed-punct-ratio } , + fixed-margin-width : length = \c_max_dim , + fixed-margin-ratio : real = \c_one_fp , + mixed-margin-width : length = \KeyValue { fixed-margin-width } , + mixed-margin-ratio : real = \KeyValue { fixed-margin-ratio } , + middle-margin-width : length = \KeyValue { fixed-margin-width } , + middle-margin-ratio : real = \KeyValue { fixed-margin-ratio } , + add-min-bound-to-margin : boolean = false , + optimize-margin : boolean = false , + margin-minimum : length = \c_zero_dim , + enabled-kerning : boolean = true , + min-bound-to-kerning : boolean = false , + kerning-total-width : length = \c_max_dim , + kerning-total-ratio : real = 0.75 , + optimize-kerning : boolean = false , + same-align-margin : length = \c_max_dim , + same-align-ratio : real = \c_zero_fp , + different-align-margin : length = \c_max_dim , + different-align-ratio : real = \c_zero_fp , + kerning-margin-width : length = \c_max_dim , + kerning-margin-ratio : real = \c_one_fp , + kerning-margin-minimum : length = \c_zero_dim + } +% \end{macrocode} +% +% \begin{macrocode} +\DeclareTemplateCode { xeCJK / punctuation } { basic } { 3 } + { + enabled-global-setting = \l_@@_enabled_global_setting_bool , + fixed-punct-width = \l_@@_fixed_punct_width_dim , + fixed-punct-ratio = \l_@@_fixed_punct_ratio_fp , + mixed-punct-width = \l_@@_mixed_punct_width_dim , + mixed-punct-ratio = \l_@@_mixed_punct_ratio_fp , + middle-punct-width = \l_@@_middle_punct_width_dim , + middle-punct-ratio = \l_@@_middle_punct_ratio_fp , + fixed-margin-width = \l_@@_fixed_margin_width_dim , + fixed-margin-ratio = \l_@@_fixed_margin_ratio_fp , + mixed-margin-width = \l_@@_mixed_margin_width_dim , + mixed-margin-ratio = \l_@@_mixed_margin_ratio_fp , + middle-margin-width = \l_@@_middle_margin_width_dim , + middle-margin-ratio = \l_@@_middle_margin_ratio_fp , + add-min-bound-to-margin = \l_@@_add_min_bound_to_margin_bool , + optimize-margin = \l_@@_optimize_margin_bool , + margin-minimum = \l_@@_margin_minimum_dim , + enabled-kerning = \l_@@_enabled_kerning_bool , + min-bound-to-kerning = \l_@@_min_bound_to_kerning_bool , + kerning-total-width = \l_@@_kerning_total_width_dim , + kerning-total-ratio = \l_@@_kerning_total_ratio_fp , + optimize-kerning = \l_@@_optimize_kerning_bool , + same-align-margin = \l_@@_same_align_margin_dim , + same-align-ratio = \l_@@_same_align_ratio_fp , + different-align-margin = \l_@@_different_align_margin_dim , + different-align-ratio = \l_@@_different_align_ratio_fp , + kerning-margin-width = \l_@@_kerning_margin_width_dim , + kerning-margin-ratio = \l_@@_kerning_margin_ratio_fp , + kerning-margin-minimum = \l_@@_kerning_margin_minimum_dim + } + { + \AssignTemplateKeys + \tl_if_blank:nTF {#3} + { \xeCJK_punct_margin_process:NN {#1} {#2} } + { \xeCJK_punct_kerning_process:NN {#2} {#3} } + } +% \end{macrocode} +% +% \begin{macro}[internal]{\xeCJK_punct_margin_process:NN} +% \begin{macrocode} +\cs_new_protected_nopar:Npn \xeCJK_punct_margin_process:NN #1#2 + { + \tl_set:Nx \l_@@_tmpa_tl { \@@_use_punct_dim:nnn { bound } {#1} {#2} } + \tl_set:Nx \l_@@_tmpb_tl { - \tl_if_eq:NNTF \l_xeCJK_punctstyle_tl \c_@@_ps_plain_tl + \@@_use_punct_dim:nnn { bound } + { \xeCJK_reverse:nnn {#1} \c_@@_left_tl \c_@@_right_tl } {#2} + } + \dim_set:Nn \l_@@_tmp_dim + { + \bool_if:NTF \l_@@_enabled_global_setting_bool { - \tl_set:NV \l_@@_tmpa_tl \c_zero_dim - \tl_gset_eq:cN { \l_@@_punct_coor_tl/glue/#1/#2 } \l_@@_tmpa_tl - \tl_gset_eq:cN { \l_@@_punct_coor_tl/rule/#1/#2 } \l_@@_tmpa_tl - \tl_gset_eq:cN { \l_@@_punct_coor_tl/rule/lr/#2 } \l_@@_tmpa_tl - \tl_gset_eq:cN { \l_@@_punct_coor_tl/bound/#1/#2 } \l_@@_tmpa_tl - \tl_gset_eq:cN { \l_@@_punct_coor_tl/bound/lr/#2 } \l_@@_tmpa_tl + \cs_if_exist_use:cTF { g_@@_punct_width/#2/tl } + { \use_none:n } + { + \xeCJK_if_blank_x:nTF \g_@@_punct_width_tl + { \use:n } + { \g_@@_punct_width_tl \use_none:n } + } } + { \use:n } { - \tl_if_exist:cF { \l_@@_punct_coor_tl/bound/#1/#2 } - { { \xeCJK_select_font: \xeCJK_calc_punct_dimen:N {#2} } } - \@@_punct_if_long:NTF {#2} + \@@_punct_if_middle:NTF {#2} + { \@@_punct_width_or_ratio:nN { middle } {#2} } { - \dim_zero:N \l_@@_tmpa_dim - \dim_zero:N \l_@@_tmpb_dim - \dim_zero:N \l_@@_tmpc_dim + \@@_punct_if_mixed_width:NTF {#2} + { \@@_punct_width_or_ratio:nN { mixed } {#2} } + { \@@_punct_width_or_ratio:nN { fixed } {#2} } } + } + } + \@@_gset_punct_dim:nnnx { glue } {#1} {#2} + { + \dim_max:nn + { \l_@@_margin_minimum_dim } + { + \dim_compare:nNnTF \l_@@_tmp_dim < \c_max_dim { - \dim_set:Nc \l_@@_tmpa_dim { \l_@@_punct_coor_tl/bound/#1/#2 } - \dim_set:Nc \l_@@_tmpb_dim - { \l_@@_punct_coor_tl/bound/\str_if_eq_x:nnTF {#1} lrl/#2 } - \dim_set:Nn \l_@@_tmpc_dim + \@@_punct_if_middle:NTF {#2} { - \cs_if_exist_use:cF { g_@@_punct_width/#2 } - { - \xeCJK_if_blank_x:nTF \g_@@_punct_width_tl - { \c_zero_dim } { \g_@@_punct_width_tl } - } + ( + \l_@@_tmp_dim - ( \@@_use_punct_dim:nn { dimen } {#2} ) + ) / \c_two } - \@@_punct_if_middle:NTF {#2} { - \dim_set:Nn \l_@@_tmpc_dim + \bool_if:NTF \l_@@_optimize_margin_bool + { \dim_max:nn { \dim_min:nn \l_@@_tmpa_tl \l_@@_tmpb_tl } } + { \use:n } { - \dim_compare:nNnTF \l_@@_tmpc_dim > \c_zero_dim - { \l_@@_tmpc_dim } - { - \tl_case:Nnn \l_xeCJK_punctstyle_tl - { - \c_@@_ps_halfwidth_tl { .5 em } - \c_@@_ps_mixedwidth_tl { .5 em } - \c_@@_ps_CCT_tl { .7 em } - \c_@@_ps_fullwidth_tl { 1 em } - } - { 1 em } - } - - ( \tl_use:c { \l_@@_punct_coor_tl/dimen/#2 } ) - } - \dim_compare:nNnTF \l_@@_tmpc_dim > \c_zero_dim - { \dim_set:Nn \l_@@_tmpc_dim { .5 \l_@@_tmpc_dim } } - { - \dim_set:Nn \l_@@_tmpc_dim - { \dim_min:nn \l_@@_tmpa_dim \l_@@_tmpb_dim } + \l_@@_tmp_dim - ( \l_@@_tmpb_tl ) + - ( \@@_use_punct_dim:nn { dimen } {#2} ) } } + } + { + \bool_if:NTF \l_@@_optimize_margin_bool + { \dim_min:nn { \l_@@_tmpa_tl } } + { \use:n } { - \dim_compare:nNnTF \l_@@_tmpc_dim > \c_zero_dim + \@@_punct_if_middle:NTF {#2} { - \dim_set:Nn \l_@@_tmpc_dim + \dim_compare:nNnTF \l_@@_middle_margin_width_dim < \c_max_dim + { \l_@@_middle_margin_width_dim } { - \l_@@_tmpc_dim - \l_@@_tmpb_dim - - ( \tl_use:c { \l_@@_punct_coor_tl/dimen/#2 } ) + \fp_use:N \l_@@_middle_margin_ratio_fp + \etex_dimexpr:D + ( \l_@@_tmpa_tl + \l_@@_tmpb_tl ) / \c_two + \scan_stop: } } { - \dim_set:Nn \l_@@_tmpc_dim - { \dim_min:nn \l_@@_tmpa_dim \l_@@_tmpb_dim } - \tl_case:Nnn \l_xeCJK_punctstyle_tl - { - \c_@@_ps_halfwidth_tl { \prg_do_nothing: } - \c_@@_ps_mixedwidth_tl - { - \@@_punct_if_mixedwidth:NT {#2} - { - \dim_add:Nn \l_@@_tmpc_dim { .5 \l_@@_tmpa_dim } - \xeCJK_dim_set_min:Nn \l_@@_tmpc_dim \l_@@_tmpa_dim - } - } - \c_@@_ps_CCT_tl - { - \@@_punct_if_mixedwidth:NTF {#2} - { \dim_add:Nn \l_@@_tmpc_dim { .5 \l_@@_tmpa_dim } } - { \dim_add:Nn \l_@@_tmpc_dim { .3 \l_@@_tmpa_dim } } - \xeCJK_dim_set_min:Nn \l_@@_tmpc_dim \l_@@_tmpa_dim - } - } - { \dim_set_eq:NN \l_@@_tmpc_dim \l_@@_tmpa_dim } + \@@_punct_if_mixed_width:NTF {#2} + { \@@_margin_width_or_ratio:n { mixed } } + { \@@_margin_width_or_ratio:n { fixed } } } } - \xeCJK_dim_set_max:Nn \l_@@_tmpc_dim \c_zero_dim } - \tl_gset:cx { \l_@@_punct_coor_tl/rule/#1/#2 } - { - \dim_use:N \l_@@_tmpa_dim } - \tl_gset:cx { \l_@@_punct_coor_tl/rule/lr/#2 } - { - \dim_use:N \l_@@_tmpb_dim } - \tl_gset:cV { \l_@@_punct_coor_tl/glue/#1/#2 } \l_@@_tmpc_dim } } } -\cs_generate_variant:Nn \xeCJK_get_punct_bounds:nN { nV } % \end{macrocode} % \end{macro} % -% \begin{macro}{\xeCJKsetwidth} +% \begin{macro}[internal]{\@@_punct_width_or_ratio:nN} % \begin{macrocode} -\NewDocumentCommand \xeCJKsetwidth { m m } - { \tl_map_inline:xn {#1} { \tl_gset:cn { g_@@_punct_width/##1 } {#2} } } -% \end{macrocode} -% \end{macro} -% -% \begin{macro}[pTF,internal] -% {\@@_punct_if_right:N,\@@_punct_if_both_left_right:NN, -% \@@_punct_if_long:N,\@@_punct_if_middle:N, -% \@@_punct_if_mixedwidth:N} -% \begin{macrocode} -\prg_new_conditional:Npnn \@@_punct_if_right:N #1 { p , T , F , TF } +\cs_new_nopar:Npn \@@_punct_width_or_ratio:nN #1#2 { - \tl_if_exist:cTF { \l_@@_punct_coor_tl/glue/r/#1 } - \prg_return_true: \prg_return_false: - } -\prg_new_conditional:Npnn \@@_punct_if_both_left_right:NN #1#2 { p , T , F , TF } - { - \bool_if:nTF + \dim_compare:nNnTF { \use:c { l_@@_#1_punct_width_dim } } < \c_max_dim + { \use:c { l_@@_#1_punct_width_dim } } { - ( \tl_if_exist_p:c { \l_@@_punct_coor_tl/glue/r/#1 } && - \tl_if_exist_p:c { \l_@@_punct_coor_tl/glue/r/#2 } ) || - ( \tl_if_exist_p:c { \l_@@_punct_coor_tl/glue/l/#1 } && - \tl_if_exist_p:c { \l_@@_punct_coor_tl/glue/l/#2 } ) + \fp_compare:nNnTF { \use:c { l_@@_#1_punct_ratio_fp } } = \c_zero_fp + { \c_max_dim } + { + \fp_use:c { l_@@_#1_punct_ratio_fp } + \etex_dimexpr:D \@@_use_punct_dim:nn { width } {#2} \scan_stop: + } } - \prg_return_true: \prg_return_false: } -\cs_generate_variant:Nn \prg_new_conditional:Npnn { c } -\clist_map_inline:Nn \g_@@_special_ps_clist +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\@@_margin_width_or_ratio:n} +% \begin{macrocode} +\cs_new_nopar:Npn \@@_margin_width_or_ratio:n #1 { - \prg_new_conditional:cpnn { @@_punct_if_#1:N } ##1 { p , T , F , TF } + \dim_compare:nNnTF { \use:c { l_@@_#1_margin_width_dim } } < \c_max_dim + { \use:c { l_@@_#1_margin_width_dim } } { - \prop_if_in:cnTF { l_@@_#1_punct_prop } {##1} - \prg_return_true: \prg_return_false: + \fp_use:c { l_@@_#1_margin_ratio_fp } + \etex_dimexpr:D \l_@@_tmpa_tl \scan_stop: } + \bool_if:NT \l_@@_add_min_bound_to_margin_bool + { + \dim_min:nn \l_@@_tmpa_tl \l_@@_tmpb_tl } } % \end{macrocode} % \end{macro} % -% \begin{macro}[internal]{\xeCJK_calc_kern:NN,\@@_calc_kern:NNN} -% 标点挤压。行末半角方式,相邻标点不挤压;全角方式,相邻两个标点占 1.5 汉字宽度, -% 半角、开明和 CCT 方式相邻标点占一个汉字宽度。 +% \begin{macro}[internal]{\xeCJK_punct_kerning_process:NN} % \begin{macrocode} -\cs_new_protected_nopar:Npn \xeCJK_calc_kern:NN #1#2 +\cs_new_protected_nopar:Npn \xeCJK_punct_kerning_process:NN #1#2 { - \tl_if_exist:cF { \l_@@_punct_coor_tl/kern/#1-#2 } + \@@_gset_punct_dim:nnnx { kern } {#1} {#2} { - \dim_zero:N \l_@@_tmpa_dim - \tl_if_eq:NNF \l_xeCJK_punctstyle_tl \c_@@_ps_plain_tl + \dim_eval:n { - \tl_if_exist:cTF { g_@@_punct/kern/#1-#2 } - { \dim_set:Nc \l_@@_tmpa_dim { g_@@_punct/kern/#1-#2 } } - { \@@_calc_kern:NNN \l_@@_tmpa_dim {#1} {#2} } + \bool_if:nTF + { + \l_@@_enabled_global_setting_bool && + \tl_if_exist_p:c { g_@@_punct/kern/#1/#2/tl } + } + { \tl_use:c { g_@@_punct/kern/#1/#2/tl } } + { + \bool_if:NTF \l_@@_enabled_kerning_bool + { \@@_calc_kerning_margin:NN {#1} {#2} } + { \@@_original_kerning_margin:NN {#1} {#2} } + } + - ( \@@_use_punct_dim:nnn { bound } \c_@@_right_tl {#1} ) + - ( \@@_use_punct_dim:nnn { bound } \c_@@_left_tl {#2} ) } - \tl_gset:cV { \l_@@_punct_coor_tl/kern/#1-#2 } \l_@@_tmpa_dim } } -\cs_new_protected_nopar:Npn \@@_calc_kern:NNN #1#2#3 +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\@@_original_kerning_margin:NN} +% 相邻两个标点符号之间的本来空白宽度。 +% \begin{macrocode} +\cs_new_nopar:Npn \@@_original_kerning_margin:NN #1#2 { - \tl_if_eq:NNTF \l_xeCJK_punctstyle_tl \c_@@_ps_marginkerning_tl + \dim_eval:n { - \dim_zero:N #1 - \@@_punct_if_right:NT {#2} - { \dim_add:Nc #1 { \l_@@_punct_coor_tl/bound/r/#2 } } - \@@_punct_if_right:NF {#3} - { \dim_add:Nc #1 { \l_@@_punct_coor_tl/bound/l/#3 } } + \@@_use_punct_dim:nnn + { \@@_punct_if_right:NTF {#1} { glue } { bound } } + { \c_@@_right_tl } {#1} + + \@@_use_punct_dim:nnn + { \@@_punct_if_right:NTF {#2} { bound } { glue } } + { \c_@@_left_tl } {#2} } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\@@_calc_kerning_margin:NN} +% \begin{macrocode} +\cs_new_nopar:Npn \@@_calc_kerning_margin:NN #1#2 + { + \dim_max:nn + { \l_@@_kerning_margin_minimum_dim } { - \tl_if_eq:NNTF \l_xeCJK_punctstyle_tl \c_@@_ps_fullwidth_tl - { \dim_set:Nn #1 { \xeCJK_calc_kern:nNN { 1.5 em } {#2} {#3} } } + \bool_if:NTF \l_@@_min_bound_to_kerning_bool + { \@@_punct_min_bound:NN {#1} {#2} } { - \@@_punct_if_both_left_right:NNTF {#2} {#3} - { - \@@_punct_if_mixedwidth:NT {#2} - { - \dim_set:Nn #1 { \xeCJK_calc_kern:nNN { 1 em } {#2} {#3} } - \dim_compare:nNnT #1 < { .1 em } - { \dim_set:Nc #1 { \l_@@_punct_coor_tl/bound/l/#2 } } - } - } + \bool_if:NTF \l_@@_optimize_kerning_bool + { \dim_max:nn { \@@_punct_min_bound:NN {#1} {#2} } } + { \use:n } { - \bool_if:nTF - { - \@@_punct_if_mixedwidth_p:N {#2} && - ! ( \tl_if_eq_p:NN \l_xeCJK_punctstyle_tl \c_@@_ps_halfwidth_tl ) - } - { - \dim_set:Nn #1 { \tl_use:c { \l_@@_punct_coor_tl/glue/r/#2 } } - \dim_set:Nn #1 { .7 #1 } - } + \dim_compare:nNnTF \l_@@_kerning_total_width_dim < \c_max_dim + { \@@_calc_kerning_margin:nNN \l_@@_kerning_total_width_dim } { - \dim_set:Nn #1 { \xeCJK_calc_kern:nNN { 1 em } {#2} {#3} } - \dim_compare:nNnT #1 < { .1 em } + \fp_compare:nNnTF \l_@@_kerning_total_ratio_fp = \c_zero_fp { - \dim_set:Nn #1 + \xeCJK_if_same_class:NNTF {#1} {#2} + { \@@_kerning_width_or_ratio:nNN { same } } + { \@@_kerning_width_or_ratio:nNN { different } } + } + { + \@@_calc_kerning_margin:nNN { - \dim_max:nn - { - \dim_min:cc - { \l_@@_punct_coor_tl/bound/l/#2 } - { \l_@@_punct_coor_tl/bound/r/#2 } - } - { - \dim_min:cc - { \l_@@_punct_coor_tl/bound/l/#3 } - { \l_@@_punct_coor_tl/bound/r/#3 } - } + \fp_use:N \l_@@_kerning_total_ratio_fp + \etex_dimexpr:D + \@@_use_punct_dim:nn { width } {#1} + + \@@_use_punct_dim:nn { width } {#2} + \scan_stop: } } } + {#1} {#2} } } - \bool_if:nT - { \@@_punct_if_long_p:N {#2} || \@@_punct_if_long_p:N {#3} } - { \xeCJK_dim_set_max:Nn #1 { .1 em } } } - \xeCJK_dim_set_max:Nn #1 \c_zero_dim } -\cs_generate_variant:Nn \xeCJK_calc_kern:NN { V } % \end{macrocode} % \end{macro} % -% \begin{macro}[internal]{\xeCJK_calc_kern:nNN} +% \begin{macro}[internal]{\@@_kerning_width_or_ratio:nNN} +% \begin{macrocode} +\cs_new_nopar:Npn \@@_kerning_width_or_ratio:nNN #1#2#3 + { + \dim_compare:nNnTF { \use:c { l_@@_#1_align_margin_dim } } < \c_max_dim + { \use:c { l_@@_#1_align_margin_dim } \use_none:nn } + { + \fp_compare:nNnTF { \use:c { l_@@_#1_align_ratio_fp } } = \c_zero_fp + { \use:n } + { \fp_use:c { l_@@_#1_align_ratio_fp } \use_ii:nn } + } + { + \dim_compare:nNnTF \l_@@_kerning_margin_width_dim < \c_max_dim + { \l_@@_kerning_margin_width_dim \use_none:n } + { \fp_use:N \l_@@_kerning_margin_ratio_fp \use:n } + } + { \etex_dimexpr:D \@@_original_kerning_margin:NN {#2} {#3} \scan_stop: } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\@@_punct_min_bound:NN} +% \begin{macrocode} +\cs_new_nopar:Npn \@@_punct_min_bound:NN #1#2 + { + \dim_max:nn + { + \dim_min:nn + { \@@_use_punct_dim:nnn { bound } \c_@@_left_tl {#1} } + { \@@_use_punct_dim:nnn { bound } \c_@@_right_tl {#1} } + } + { + \dim_min:nn + { \@@_use_punct_dim:nnn { bound } \c_@@_left_tl {#2} } + { \@@_use_punct_dim:nnn { bound } \c_@@_right_tl {#2} } + } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\@@_calc_kerning_margin:nNN} % |#2| 和 |#3| 为相邻的两个标点,|#1| 为要确定的相邻两个标点总共占的宽度。 % \begin{macrocode} -\cs_new_protected_nopar:Npn \xeCJK_calc_kern:nNN #1#2#3 +\cs_new_nopar:Npn \@@_calc_kerning_margin:nNN #1#2#3 { \dim_eval:n { - #1 - - \tl_use:c { \l_@@_punct_coor_tl/ - \@@_punct_if_right:NTF {#2} { bound } { glue } /l/#2 } - - \tl_use:c { \l_@@_punct_coor_tl/ - \@@_punct_if_right:NTF {#3} { glue } { bound } /r/#3 } - - \tl_use:c { \l_@@_punct_coor_tl/dimen/#2 } - - \tl_use:c { \l_@@_punct_coor_tl/dimen/#3 } - \@@_punct_if_both_left_right:NNT {#2} {#3} - { + \tl_use:c { \l_@@_punct_coor_tl/rule/lr/#3 } } + (#1) + - ( \@@_use_punct_dim:nnn + { \@@_punct_if_right:NTF {#2} { bound } { glue } } + { \c_@@_left_tl } {#2} ) + - ( \@@_use_punct_dim:nnn + { \@@_punct_if_right:NTF {#3} { glue } { bound } } + { \c_@@_right_tl } {#3} ) + - ( \@@_use_punct_dim:nn { dimen } {#2} ) + - ( \@@_use_punct_dim:nn { dimen } {#3} ) } } % \end{macrocode} % \end{macro} % -% \begin{macro}[internal]{\xeCJK_calc_punct_dimen:N} -% 返回标点的左右空白和实际尺寸。对于破折号,计算两标点之间的空白,保证它中间不被断开。 +% \begin{macro}[internal]{\xeCJK_get_punct_bounds:NN} +% |#1| 为 \cs{c_@@_left_tl} 或 \cs{c_@@_right_tl},|#2| 为标点符号。 % \begin{macrocode} -\cs_new_protected_nopar:Npn \xeCJK_calc_punct_dimen:N #1 +\cs_new_protected_nopar:Npn \xeCJK_get_punct_bounds:NN #1#2 { - \tl_gset:cx { \l_@@_punct_coor_tl/bound/l/#1 } - { \xeCJK_glyph_bounds:nN { left } {#1} } - \tl_gset:cx { \l_@@_punct_coor_tl/bound/r/#1 } - { \xeCJK_glyph_bounds:nN { right } {#1} } - \tl_gset:cx { \l_@@_punct_coor_tl/bound/lr/#1 } + \tl_if_exist:cF { \@@_punct_dim_csname:nnn { glue } {#1} {#2} } { - \dim_eval:n + \tl_if_eq:NNTF \l_xeCJK_punct_style_tl \c_@@_punct_style_plain_tl { - ( \tl_use:c { \l_@@_punct_coor_tl/bound/l/#1 } ) + - ( \tl_use:c { \l_@@_punct_coor_tl/bound/r/#1 } ) + \@@_gset_punct_dim:nnnx { glue } {#1} {#2} { \c_zero_dim } + \@@_gset_punct_dim:nnnx { bound } \c_@@_left_tl {#2} { \c_zero_dim } + \@@_gset_punct_dim:nnnx { bound } \c_@@_right_tl {#2} { \c_zero_dim } } - } - \tl_gset:cx { \l_@@_punct_coor_tl/dimen/#1 } - { - \dim_eval:n { - ( \etex_fontcharwd:D \tex_font:D `#1 ) - - ( \tl_use:c { \l_@@_punct_coor_tl/bound/lr/#1 } ) + { \xeCJK_select_font: \xeCJK_calc_punct_dimen:f {#2} } + \@@_punct_if_long:NTF {#2} + { \@@_gset_punct_dim:nnnx { glue } {#1} {#2} { \c_zero_dim } } + { + \UseInstance { xeCJK / punctuation } + { \l_xeCJK_punct_style_tl } {#1} {#2} { } + } } } - \bool_if:nT + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\xeCJK_calc_punct_dimen:N} +% 计算标点的左右实际边距和实际尺寸。对于破折号,计算两标点之间的空白,保证它中间 +% 不被断开。 +% \begin{macrocode} +\cs_new_protected_nopar:Npn \xeCJK_calc_punct_dimen:N #1 + { + \@@_gset_punct_dim:nnnx { bound } \c_@@_left_tl {#1} + { \xeCJK_glyph_bounds:NN \c_one {#1} } + \@@_gset_punct_dim:nnnx { bound } \c_@@_right_tl {#1} + { \xeCJK_glyph_bounds:NN \c_three {#1} } + \dim_set:Nn \l_@@_tmp_dim { - \@@_punct_if_long_p:N {#1} && - ! ( \str_if_eq_x_p:nn {#1} { ^^^^2025 } || \str_if_eq_x_p:nn {#1} { ^^^^2026 } ) + ( \@@_use_punct_dim:nnn { bound } \c_@@_left_tl {#1} ) + + ( \@@_use_punct_dim:nnn { bound } \c_@@_right_tl {#1} ) } + \@@_gset_punct_dim:nnx { width } {#1} + { \dim_use:N \etex_fontcharwd:D \tex_font:D `#1 } + \@@_gset_punct_dim:nnx { dimen } {#1} + { \dim_eval:n { \@@_use_punct_dim:nn { width } {#1} - \l_@@_tmp_dim } } + \@@_punct_if_long:NT {#1} { - \clist_map_inline:Nn \g_@@_punctstyle_clist + \seq_map_inline:Nn \g_@@_punct_style_seq { - \str_if_eq_x:nnF \c_@@_ps_plain_tl {##1} + \@@_gset_punct_dim:nnnnx {##1} { kern } {#1} {#1} { - \tl_gset:cx { \l_xeCJK_font_coor_tl/##1/kern/#1-#1 } - { - \tl_use:c { \l_@@_punct_coor_tl/bound/lr/#1 } } + \bool_if:nTF + { + \str_if_eq_p:nn {#1} { ^^^^2025 } || + \str_if_eq_p:nn {#1} { ^^^^2026 } + } + { \c_zero_dim } + { - \dim_use:N \l_@@_tmp_dim } } } } } +\cs_generate_variant:Nn \xeCJK_calc_punct_dimen:N { f } % \end{macrocode} % \end{macro} % -% \begin{macro}[internal]{\xeCJK_glyph_bounds:nN} -% 用 \cs{XeTeXglyphbounds} 计算标点的上下左右空白。 +% \begin{macro}[internal]{\xeCJK_glyph_bounds:NN} +% 用 \cs{XeTeXglyphbounds} 取得标点符号的上下左右空白。 % \begin{macrocode} -\cs_new_protected_nopar:Npn \xeCJK_glyph_bounds:nN #1#2 +\cs_new_nopar:Npn \xeCJK_glyph_bounds:NN #1#2 + { \dim_use:N \XeTeXglyphbounds #1 ~ \XeTeXcharglyph `#2 \exp_stop_f: } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\xeCJK_get_punct_kerning:NN} +% 标点挤压。 +% \begin{macrocode} +\cs_new_protected_nopar:Npn \xeCJK_get_punct_kerning:NN #1#2 { - \dim_eval:n + \tl_if_exist:cF { \@@_punct_dim_csname:nnn { kern } {#1} {#2} } { - \XeTeXglyphbounds - \str_case_x:nnn {#1} - { - { left } { \c_one } { top } { \c_two } - { right } { \c_three } { bottom } { \c_four } - } - { \c_three } - \int_eval:n { \XeTeXcharglyph `#2 } + \tl_if_eq:NNTF \l_xeCJK_punct_style_tl \c_@@_punct_style_plain_tl + { \@@_gset_punct_dim:nnnx { kern } {#1} {#2} { \c_zero_dim } } + { + \UseInstance { xeCJK / punctuation } + { \l_xeCJK_punct_style_tl } { } {#1} {#2} + } } } +\cs_generate_variant:Nn \xeCJK_get_punct_kerning:NN { o } % \end{macrocode} % \end{macro} % -% \begin{macro}{\xeCJKsetkern} -% 手动设置相邻标点的距离,仅在当前字体状态下有效。 +% \begin{macro}{PunctStyle} % \begin{macrocode} -\NewDocumentCommand \xeCJKsetkern { m m m } - { \tl_gset:cn { g_@@_punct/kern/#1-#2 } {#3} } +\keys_define:nn { xeCJK / options } + { + PunctStyle .choice: , + PunctStyle .default:n = { quanjiao } , + PunctStyle / halfwidth .meta:n = { PunctStyle = banjiao } , + PunctStyle / fullwidth .meta:n = { PunctStyle = quanjiao } , + PunctStyle / mixedwidth .meta:n = { PunctStyle = kaiming } , + PunctStyle / marginkerning .meta:n = { PunctStyle = hangmobanjiao } , + PunctStyle / plain .code:n = + { \tl_set_eq:NN \l_xeCJK_punct_style_tl \c_@@_punct_style_plain_tl } , + PunctStyle / unknown .code:n = + { + \IfInstanceExistTF { xeCJK / punctuation } { \l_keys_value_tl } + { \tl_set:Nx \l_xeCJK_punct_style_tl { \l_keys_value_tl } } + { \@@_error:nx { punct-style-unknown } { \l_keys_value_tl } } + } + } +\tl_const:Nn \c_@@_punct_style_plain_tl { plain } +\@@_msg_new:nn { punct-style-unknown } + { + Punctuation~style~"#1"~is~unknown. \\\\ + The~available~styles~are~listed~as~follow.\\\\ + "plain,~\seq_use:Nnnn \g_@@_punct_style_seq { ~and~ } { ,~ } { ,~and~ }".\\ + } % \end{macrocode} % \end{macro} % +% \begin{macro}{\xeCJKDeclarePunctStyle} +% 定义新的标点处理风格,已经存在的同名风格将被覆盖。 +% \begin{macrocode} +\NewDocumentCommand \xeCJKDeclarePunctStyle { > { \TrimSpaces } m m } + { + \IfInstanceExistTF { xeCJK / punctuation } {#1} + { \@@_warning:nx { punct-style-already-defined } {#1} } + { \seq_gput_right:Nn \g_@@_punct_style_seq {#1} } + \DeclareInstance { xeCJK / punctuation } {#1} { basic } {#2} + } +\seq_new:N \g_@@_punct_style_seq +\@@_msg_new:nn { punct-style-already-defined } + { + Punctuation~style~"#1"~is~already~defined!. \\\\ + The~existing~style~of~"#1"~will~be~overwritten.\\ + } +\@onlypreamble \xeCJKDeclarePunctStyle +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\xeCJKEditPunctStyle} +% 对已有的标点处理风格进行修改。 +% \begin{macrocode} +\NewDocumentCommand \xeCJKEditPunctStyle { > { \TrimSpaces } m m } + { + \IfInstanceExistTF { xeCJK / punctuation } {#1} + { \EditInstance { xeCJK / punctuation } {#1} {#2} } + { \@@_error:nx { punct-style-unknown } {#1} } + } +\@onlypreamble \xeCJKEditPunctStyle +% \end{macrocode} +% \end{macro} +% +% 默认设置即为全角格式。 +% \begin{macrocode} +\xeCJKDeclarePunctStyle { quanjiao } { } +% \end{macrocode} +% +% \begin{macrocode} +\xeCJKDeclarePunctStyle { hangmobanjiao } { enabled-kerning = false } +% \end{macrocode} +% +% \begin{macrocode} +\xeCJKDeclarePunctStyle { banjiao } + { + fixed-punct-ratio = 0.5 , + optimize-margin = true , + kerning-total-ratio = 0.5 , + optimize-kerning = true + } +% \end{macrocode} +% +% \begin{macrocode} +\xeCJKDeclarePunctStyle { kaiming } + { + fixed-punct-ratio = 0.5 , + mixed-punct-ratio = 0.8 , + optimize-margin = true , + kerning-total-ratio = 0.5 , + optimize-kerning = true + } +% \end{macrocode} +% +% \begin{macrocode} +\xeCJKDeclarePunctStyle { CCT } + { + fixed-punct-ratio = 0.7 , + optimize-margin = true , + kerning-total-ratio = 0.6 , + optimize-kerning = true + } +% \end{macrocode} +% % \subsection{后备字体} % % \begin{macro}{AutoFallBack} @@ -2985,11 +3507,11 @@ $URL: https://ctex-kit.googlecode.com/svn/trunk/xeCJK/xeCJK.dtx $ % \begin{macrocode} \keys_define:nn { xeCJK / options } { - AutoFallBack .choice:, - AutoFallBack / true .code:n = { \xeCJKenablefallback }, - AutoFallBack / false .code:n = { \xeCJKdisablefallback }, - AutoFallBack .default:n = { true }, - fallback .meta:n = { AutoFallBack = true }, + AutoFallBack .choice: , + AutoFallBack / true .code:n = { \xeCJKenablefallback } , + AutoFallBack / false .code:n = { \xeCJKdisablefallback } , + AutoFallBack .default:n = { true } , + fallback .meta:n = { AutoFallBack = true } } % \end{macrocode} % \end{macro} @@ -2997,14 +3519,13 @@ $URL: https://ctex-kit.googlecode.com/svn/trunk/xeCJK/xeCJK.dtx $ % \begin{macro}[internal]{\xeCJKenablefallback, \xeCJKdisablefallback} % 后备字体的启用开关,默认关闭。 % \begin{macrocode} -\bool_new:N \l_@@_fallback_bool \NewDocumentCommand \xeCJKenablefallback { } { \bool_if:NF \l_@@_fallback_bool { \bool_set_true:N \l_@@_fallback_bool \cs_set_eq:NN \@@_fallback_save_CJKsymbol:N \CJKsymbol - \cs_set_eq:NN \CJKsymbol \xeCJK_fallback_testsymbol:N + \cs_set_eq:NN \CJKsymbol \xeCJK_fallback_test_glyph:N } } \NewDocumentCommand \xeCJKdisablefallback { } @@ -3015,76 +3536,96 @@ $URL: https://ctex-kit.googlecode.com/svn/trunk/xeCJK/xeCJK.dtx $ \cs_set_eq:NN \CJKsymbol \@@_fallback_save_CJKsymbol:N } } +\bool_new:N \l_@@_fallback_bool % \end{macrocode} % \end{macro} % -% \begin{macro}[internal]{\xeCJK_fallback_testsymbol:N} +% \begin{macro}[internal]{\xeCJK_fallback_test_glyph:N} % 测试当前字体中是否存在当前字符,如存在则直接输出,否则启用后备字体。 % \begin{macrocode} -\cs_new_protected_nopar:Npn \xeCJK_fallback_testsymbol:N #1 +\cs_new_protected_nopar:Npn \xeCJK_fallback_test_glyph:N #1 { - \font_glyph_if_exist:NnTF \tex_font:D {`#1} + \xeCJK_glyph_if_exist:NTF {#1} { \@@_fallback_save_CJKsymbol:N {#1} } + { { \xeCJK_fallback_loop:Nn {#1} { \l_xeCJK_family_tl/FallBack } } } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\xeCJK_fallback_loop:Nn} +% \changes{v3.1.0}{2012/11/19}{调整备用字体的循环方式。} +% 循环测试后备字体是否包含字符 |#1|。若后备字体中存在该字符或者再没有后备字体,则 +% 结束循环。 +% \begin{macrocode} +\cs_new_protected_nopar:Npn \xeCJK_fallback_loop:Nn #1#2 + { + \xeCJK_family_if_exist:xTF {#2} { - \xeCJK_family_if_exist:xTF { \l_xeCJK_family_tl/FallBack } - { { - \tl_put_right:Nn \l_xeCJK_family_tl { /FallBack } - \xeCJK_select_font: - \xeCJK_fallback_testsymbol:N {#1} - } } - { - \@@_warning:nx { fallback } {#1} - \@@_fallback_save_CJKsymbol:N {#1} - } + \xeCJK_select_font:x {#2} + \xeCJK_glyph_if_exist:NTF {#1} + { \@@_fallback_save_CJKsymbol:N {#1} } + { \xeCJK_fallback_loop:Nn {#1} { #2/FallBack } } + } + { + \@@_warning:nxx { fallback } {#1} {#2} + \@@_fallback_save_CJKsymbol:N {#1} } } \@@_msg_new:nn { fallback } { - CJKfamily~'\l_xeCJK_family_tl'~ - ( \prop_get:NV \g_@@_family_prop \l_xeCJK_family_tl )~ + CJKfamily~'#2'~ + ( \prop_get:No \g_@@_family_font_name_prop {#2} )~ does~not~contain~glyph~'#1'~(U+\int_to_hexadecimal:n {`#1}).\\ } +\cs_generate_variant:Nn \prop_get:Nn { No } % \end{macrocode} % \end{macro} % % \begin{macro}{\setCJKfallbackfamilyfont} -% \begin{macro}[internal]{\xeCJK_set_family_fallback:xnn} % \begin{macrocode} \NewDocumentCommand \setCJKfallbackfamilyfont { m O{} m } { - \exp_args:Nx \tl_if_in:nnTF {#3} { , } - { \xeCJK_set_family_fallback:xnn {#1} {#2} {#3} } - { \xeCJK_set_family:xnn { #1/FallBack } {#2} {#3} } + \clist_set:Nx \l_@@_tmpa_clist {#3} + \int_compare:nNnTF { \clist_count:N \l_@@_tmpa_clist } > \c_one + { \xeCJK_set_family_fallback:xxN {#1} {#2} \l_@@_tmpa_clist } + { \xeCJK_set_family:xxx { #1/FallBack } {#2} {#3} } } -\cs_new_protected_nopar:Npn \xeCJK_set_family_fallback:xnn #1#2#3 +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\xeCJK_set_family_fallback:nnN} +% \begin{macrocode} +\cs_new_protected_nopar:Npn \xeCJK_set_family_fallback:nnN #1#2#3 { \group_begin: - \tl_set:Nx \l_@@_family_fb_tl {#1} - \prop_get:NVNF \g_@@_family_prop \l_@@_family_fb_tl \l_@@_fontname_tl - { \tl_clear:N \l_@@_fontname_tl } - \clist_map_inline:xn {#3} + \tl_set:Nn \l_@@_fallback_family_tl {#1} + \prop_get:NVNF \g_@@_family_font_name_prop + \l_@@_fallback_family_tl \l_@@_font_name_tl + { \tl_clear:N \l_@@_font_name_tl } + \clist_map_inline:Nn #3 { - \tl_put_right:Nn \l_@@_family_fb_tl { /FallBack } - \@@_get_sub_features:nn \l_@@_family_fb_tl {##1} - \clist_put_left:cx { l_@@_ \l_@@_family_fb_tl _fontfeat_clist } {#2} - \xeCJK_set_family:xcc \l_@@_family_fb_tl - { l_@@_ \l_@@_family_fb_tl _fontfeat_clist } - { l_@@_ \l_@@_family_fb_tl _fontname_tl } + \tl_put_right:Nn \l_@@_fallback_family_tl { /FallBack } + \@@_get_sub_features:Vn \l_@@_fallback_family_tl {##1} + \clist_put_left:cn + { l_@@_ \l_@@_fallback_family_tl _font_options_clist } {#2} + \xeCJK_set_family:Vvv \l_@@_fallback_family_tl + { l_@@_ \l_@@_fallback_family_tl _font_options_clist } + { l_@@_ \l_@@_fallback_family_tl _font_name_tl } } \group_end: } +\cs_generate_variant:Nn \xeCJK_set_family_fallback:nnN { xx } % \end{macrocode} % \end{macro} -% \end{macro} % % % \subsection{CJK 字体族声明方式} % % \begin{macrocode} -\bool_new:N \g_@@_AutoFakeBold_bool -\bool_new:N \g_@@_AutoFakeSlant_bool -\fp_new:N \g_@@_EmboldenFactor_fp -\fp_new:N \g_@@_SlantFactor_fp +\bool_new:N \g_@@_auto_fake_bold_bool +\bool_new:N \g_@@_auto_fake_slant_bool +\fp_new:N \g_@@_embolden_factor_fp +\fp_new:N \g_@@_slant_factor_fp % \end{macrocode} % % \begin{macro}{AutoFakeBold, AutoFakeSlant,EmboldenFactor,SlantFactor} @@ -3092,64 +3633,52 @@ $URL: https://ctex-kit.googlecode.com/svn/trunk/xeCJK/xeCJK.dtx $ % \begin{macrocode} \keys_define:nn { xeCJK / options } { - AutoFakeBold .choice:, - AutoFakeBold / true .code:n = - { \bool_set_true:N \g_@@_AutoFakeBold_bool }, - AutoFakeBold / false .code:n = - { \bool_set_false:N \g_@@_AutoFakeBold_bool }, + AutoFakeBold .choices:nn = { true , false } + { \use:c { bool_gset_ \l_keys_choice_tl :N } \g_@@_auto_fake_bold_bool } , AutoFakeBold / unknown .code:n = { - \bool_set_true:N \g_@@_AutoFakeBold_bool - \fp_set:Nn \g_@@_EmboldenFactor_fp { \l_keys_value_tl } - }, - AutoFakeBold .default:n = { true }, - AutoFakeSlant .choice:, - AutoFakeSlant / true .code:n = - { \bool_set_true:N \g_@@_AutoFakeSlant_bool }, - AutoFakeSlant / false .code:n = - { \bool_set_false:N \g_@@_AutoFakeSlant_bool }, + \bool_gset_true:N \g_@@_auto_fake_bold_bool + \fp_gset:Nn \g_@@_embolden_factor_fp { \l_keys_value_tl } + } , + AutoFakeBold .default:n = { true } , + AutoFakeSlant .choices:nn = { true , false } + { \use:c { bool_gset_ \l_keys_choice_tl :N } \g_@@_auto_fake_slant_bool } , AutoFakeSlant / unknown .code:n = { - \bool_set_true:N \g_@@_AutoFakeSlant_bool - \fp_set:Nn \g_@@_SlantFactor_fp { \l_keys_value_tl } - }, - AutoFakeSlant .default:n = { true }, - EmboldenFactor .fp_set:N = \g_@@_EmboldenFactor_fp, - SlantFactor .fp_set:N = \g_@@_SlantFactor_fp, - BoldFont .meta:n = { AutoFakeBold = true }, - boldfont .meta:n = { AutoFakeBold = true }, - SlantFont .meta:n = { AutoFakeSlant = true }, - slantfont .meta:n = { AutoFakeSlant = true }, + \bool_gset_true:N \g_@@_auto_fake_slant_bool + \fp_gset:Nn \g_@@_slant_factor_fp { \l_keys_value_tl } + } , + AutoFakeSlant .default:n = { true } , + EmboldenFactor .fp_gset:N = \g_@@_embolden_factor_fp , + SlantFactor .fp_gset:N = \g_@@_slant_factor_fp , + BoldFont .meta:n = { AutoFakeBold = true } , + boldfont .meta:n = { AutoFakeBold = true } , + SlantFont .meta:n = { AutoFakeSlant = true } , + slantfont .meta:n = { AutoFakeSlant = true } } % \end{macrocode} % \end{macro} % -% \begin{macro}[internal]{\keys_set_known:nxN} -% \begin{macrocode} -\cs_generate_variant:Nn \keys_set_known:nnN { nx } -% \end{macrocode} -% \end{macro} -% -% \begin{macro}[internal]{\@@_new_sub_key:n,\g_@@_sub_key_clist} +% \begin{macro}[internal]{\@@_new_sub_key:n,\g_@@_sub_key_seq} % 用于定义 CJK 子区字体和备用字体的选项。 % \begin{macrocode} -\clist_new:N \g_@@_sub_key_clist +\seq_new:N \g_@@_sub_key_seq \cs_new_protected_nopar:Npn \@@_new_sub_key:n #1 { - \clist_gput_right:Nx \g_@@_sub_key_clist {#1} + \seq_gput_right:Nn \g_@@_sub_key_seq {#1} \keys_define:nn { xeCJK / features } { #1 .code:n = { - \xeCJK_if_blank_x:nTF {##1} + \tl_if_blank:nTF {##1} { \bool_set_false:c { l_@@_copy_#1_bool } \bool_set_false:c { l_@@_add_#1_bool } - \tl_put_right:Nx \l_@@_family_aux_tl { /#1 } + \tl_put_right:Nn \l_@@_family_name_tl { /#1 } } { - \clist_put_right:Nx \l_@@_sub_key_clist {#1} - \str_if_eq_x:nnTF {##1} * + \seq_put_right:Nn \l_@@_sub_key_seq {#1} + \str_if_eq:nnTF {##1} { * } { \bool_set_true:c { l_@@_copy_#1_bool } \bool_set_false:c { l_@@_add_#1_bool } @@ -3160,51 +3689,46 @@ $URL: https://ctex-kit.googlecode.com/svn/trunk/xeCJK/xeCJK.dtx $ \@@_get_sub_features:nn {#1} {##1} } } - }, - #1 .default:n = \c_empty_tl, + } , + #1 .default:n = { } } } \cs_generate_variant:Nn \@@_new_sub_key:n { x } -\cs_new_protected_nopar:Npn \@@_get_sub_features:nn #1#2 - { - \tl_set:Nx \l_@@_tmpa_tl {#2} - \clist_clear:N \l_@@_sub_fontfeat_clist - \@@_gobble_brace:N \l_@@_tmpa_tl - \exp_args:No \tl_if_head_eq_charcode:nNTF \l_@@_tmpa_tl [ % ] - { - \exp_after:wN \@@_get_sub_features_aux:n \l_@@_tmpa_tl \c_empty_tl - \xeCJK_if_blank_x:nT \l_@@_sub_fontname_tl - { - \tl_set:Nx \l_@@_sub_fontname_tl \l_@@_tmpa_tl - \clist_clear:N \l_@@_sub_fontfeat_clist - } - } - { \tl_set:Nx \l_@@_sub_fontname_tl \l_@@_tmpa_tl } - \xeCJK_if_blank_x:nTF \l_@@_sub_fontname_tl - { \tl_set:Nx \l_@@_sub_fontname_tl \l_@@_fontname_tl } - { \tl_replace_all:Nnx \l_@@_sub_fontname_tl * \l_@@_fontname_tl } - \clist_set:cx { l_@@_#1_fontfeat_clist } \l_@@_sub_fontfeat_clist - \tl_set:cx { l_@@_#1_fontname_tl } \l_@@_sub_fontname_tl - } % \end{macrocode} % \end{macro} % -% \begin{macro}[aux] -% {\@@_gobble_brace:N,\@@_get_sub_features:nn,\@@_get_sub_features_aux:n} +% \begin{macro}[internal]{\@@_get_sub_features:nn,\@@_get_sub_features:wn} % \begin{macrocode} -\cs_new_protected_nopar:Npn \@@_gobble_brace:N #1 +\cs_new_protected_nopar:Npn \@@_get_sub_features:nn #1#2 { - \exp_args:No \tl_if_head_is_group:nT #1 + \tl_set:Nx \l_@@_tmpa_tl { \xeCJK_tl_remove_outer_braces:n {#2} } + \clist_clear:N \l_@@_sub_font_options_clist + \tl_if_head_eq_meaning:VNTF \l_@@_tmpa_tl [ % ] { - \exp_last_unbraced:NNo \tl_set:Nn #1 #1 - \@@_gobble_brace:N #1 + \exp_after:wN \@@_get_sub_features:wn \l_@@_tmpa_tl \c_empty_tl + \tl_if_blank:VT \l_@@_sub_font_name_tl + { + \tl_set_eq:NN \l_@@_sub_font_name_tl \l_@@_tmpa_tl + \clist_clear:N \l_@@_sub_font_options_clist + } } + { \tl_set_eq:NN \l_@@_sub_font_name_tl \l_@@_tmpa_tl } + \tl_if_blank:VTF \l_@@_sub_font_name_tl + { \tl_set_eq:NN \l_@@_sub_font_name_tl \l_@@_font_name_tl } + { \tl_replace_all:NnV \l_@@_sub_font_name_tl { * } \l_@@_font_name_tl } + \clist_set_eq:cN { l_@@_#1_font_options_clist } \l_@@_sub_font_options_clist + \tl_set_eq:cN { l_@@_#1_font_name_tl } \l_@@_sub_font_name_tl } -\cs_new_protected_nopar:Npn \@@_get_sub_features_aux:n [#1] #2 +\cs_new_protected_nopar:Npn \@@_get_sub_features:wn [#1] #2 { - \clist_set:Nx \l_@@_sub_fontfeat_clist {#1} - \tl_set:Nx \l_@@_sub_fontname_tl {#2} + \clist_set:Nn \l_@@_sub_font_options_clist {#1} + \str_if_eq:nnTF {#2} { \c_empty_tl } + { \tl_set_eq:NN \l_@@_sub_font_name_tl \c_empty_tl } + { \tl_set:Nn \l_@@_sub_font_name_tl {#2} } } +\cs_generate_variant:Nn \@@_get_sub_features:nn { V } +\cs_generate_variant:Nn \tl_if_head_eq_meaning:nNTF { V } +\cs_generate_variant:Nn \tl_replace_all:Nnn { NnV } % \end{macrocode} % \end{macro} % @@ -3214,13 +3738,12 @@ $URL: https://ctex-kit.googlecode.com/svn/trunk/xeCJK/xeCJK.dtx $ % \end{macrocode} % \end{macro} % -% \begin{macro}[internal]{\g_@@_features_id_prop, BoldFont, ItalicFont, BoldItalicFont, -% SlantedFont, BoldSlantedFont,BoldFeatures, ItalicFeatures, BoldItalicFeatures, -% SlantedFeatures, BoldSlantedFeatures} +% \begin{macro}[internal] +% {\g_@@_features_id_prop, BoldFont, ItalicFont, BoldItalicFont, +% SlantedFont, BoldSlantedFont,BoldFeatures, ItalicFeatures, +% BoldItalicFeatures, SlantedFeatures, BoldSlantedFeatures} % 调用字体的属性声明,同 \pkg{fontspec} 宏包。 % \begin{macrocode} -\cs_new_nopar:Npn \@@_map_features_id:n #1 - { \prop_get:Nn \g_@@_features_id_prop {#1} } \prop_new:N \g_@@_features_id_prop \prop_put:Nnn \g_@@_features_id_prop { bf } { Bold } \prop_put:Nnn \g_@@_features_id_prop { it } { Italic } @@ -3231,115 +3754,131 @@ $URL: https://ctex-kit.googlecode.com/svn/trunk/xeCJK/xeCJK.dtx $ { \keys_define:nn { xeCJK / features } { - #2Font .tl_set_x:c = { l_@@_fontname_#1_tl }, - #2Features .tl_set_x:c = { l_@@_fontfeat_#1_clist } , + #2Font .tl_set:c = { l_@@_font_name_#1_tl } , + #2Features .clist_set:c = { l_@@_font_feat_#1_clist } } } % \end{macrocode} % \end{macro} % -% \begin{macro}[internal]{AutoFakeBold, AutoFakeSlant, Mono} +% \begin{macro}[internal]{AutoFakeBold, AutoFakeSlant} % \begin{macrocode} \keys_define:nn { xeCJK / features } { - AutoFakeBold .choice:, + AutoFakeBold .choice: , AutoFakeBold / false .code:n = - { \bool_set_false:N \l_@@_AutoFakeBold_bool }, + { \bool_set_false:N \l_@@_auto_fake_bold_bool } , AutoFakeBold / unknown .code:n = { - \bool_set_true:N \l_@@_AutoFakeBold_bool - \fp_set:Nn \l_@@_EmboldenFactor_fp { \l_keys_value_tl } - }, - AutoFakeBold .default:n = { \g_@@_EmboldenFactor_fp }, - AutoFakeSlant .choice:, + \bool_set_true:N \l_@@_auto_fake_bold_bool + \fp_set:Nn \l_@@_embolden_factor_fp { \l_keys_value_tl } + } , + AutoFakeBold .default:n = { \g_@@_embolden_factor_fp } , + AutoFakeSlant .choice: , AutoFakeSlant / false .code:n = - { \bool_set_false:N \l_@@_AutoFakeSlant_bool }, + { \bool_set_false:N \l_@@_auto_fake_slant_bool } , AutoFakeSlant / unknown .code:n = { - \bool_set_true:N \l_@@_AutoFakeSlant_bool - \fp_set:Nn \l_@@_SlantFactor_fp { \l_keys_value_tl } - }, - AutoFakeSlant .default:n = { \g_@@_SlantFactor_fp }, - Mono .choice:, - Mono / Exspace .code:n = - { - \xeCJK_set_monoexspace: - \tl_clear:N \l_@@_monoscale_tl - }, - Mono / Scale .code:n = - { - \xeCJK_set_monoscale: - \tl_set:Nx \l_@@_monoscale_tl { Scale = { \fp_use:N \g_@@_monoscale_fp } } - } + \bool_set_true:N \l_@@_auto_fake_slant_bool + \fp_set:Nn \l_@@_slant_factor_fp { \l_keys_value_tl } + } , + AutoFakeSlant .default:n = { \g_@@_slant_factor_fp } } % \end{macrocode} % \end{macro} % -% \begin{macro}[internal]{\@@_set_init:} +% \begin{macro}[internal]{\@@_set_family_initial:} % \begin{macrocode} -\cs_new_protected_nopar:Npn \@@_set_init: +\cs_new_protected_nopar:Npn \@@_set_family_initial: { - \cs_set_eq:NN \CJKfamily \use_none:n - \tl_clear:N \l_@@_monoscale_tl - \int_gincr:N \g_@@_fontspec_int + \@@_gobble_CJKfamily: + \int_gincr:N \g_@@_family_int \prop_clear:N \l_@@_add_font_prop \prop_map_inline:Nn \g_@@_features_id_prop { - \tl_clear:c { l_@@_fontname_##1_tl } - \clist_clear:c { l_@@_fontfeat_##1_clist } + \tl_clear:c { l_@@_font_name_##1_tl } + \clist_clear:c { l_@@_font_feat_##1_clist } } - \clist_clear:N \l_@@_pass_features_clist - \clist_clear:N \l_@@_sub_key_clist - \clist_map_inline:Nn \g_@@_sub_key_clist + \clist_clear:N \l_@@_fontspec_options_clist + \seq_clear:N \l_@@_sub_key_seq + \seq_map_inline:Nn \g_@@_sub_key_seq { \bool_set_false:c { l_@@_copy_##1_bool } \bool_set_false:c { l_@@_add_##1_bool } } - \bool_set_eq:NN \l_@@_AutoFakeBold_bool \g_@@_AutoFakeBold_bool - \bool_set_eq:NN \l_@@_AutoFakeSlant_bool \g_@@_AutoFakeSlant_bool - \fp_set_eq:NN \l_@@_EmboldenFactor_fp \g_@@_EmboldenFactor_fp - \fp_set_eq:NN \l_@@_SlantFactor_fp \g_@@_SlantFactor_fp + \bool_set_eq:NN \l_@@_auto_fake_bold_bool \g_@@_auto_fake_bold_bool + \bool_set_eq:NN \l_@@_auto_fake_slant_bool \g_@@_auto_fake_slant_bool + \fp_set_eq:NN \l_@@_embolden_factor_fp \g_@@_embolden_factor_fp + \fp_set_eq:NN \l_@@_slant_factor_fp \g_@@_slant_factor_fp } +\int_new:N \g_@@_family_int % \end{macrocode} % \end{macro} % -% \begin{macro}[internal]{\xeCJK_set_family:xnn} +% \begin{macro}[internal]{\xeCJK_set_family:nnn} % 设置一个 CJK 新字体族,与 \cs{newfontfamily} 类似,增加 |FallBack| 选项。 % \begin{macrocode} -\cs_new_protected_nopar:Npn \xeCJK_set_family:xnn #1#2#3 +\cs_new_protected_nopar:Npn \xeCJK_set_family:nnn #1#2#3 { \group_begin: - \@@_set_init: - \tl_set:Nx \l_@@_family_aux_tl {#1} - \clist_set:Nx \l_@@_fontoptions_clist {#2} - \tl_set:Nx \l_@@_fontname_tl {#3} - \keys_set_known:nxN { xeCJK / features } - { \g_@@_default_features_clist, #2 } \l_@@_pass_features_clist + \@@_set_family_initial: + \tl_set:Nn \l_@@_family_name_tl {#1} + \clist_set:Nn \l_@@_font_options_clist {#2} + \tl_set:Nn \l_@@_font_name_tl {#3} + \clist_concat:NNN \l_@@_font_features_clist + \g_@@_default_features_clist \l_@@_font_options_clist + \@@_remove_duplicate_keys:N \l_@@_font_features_clist + \keys_set_known:nVN { xeCJK / features } + \l_@@_font_features_clist \l_@@_fontspec_options_clist \@@_parse_features: \@@_pass_features: - \@@_check_family:V \l_@@_family_aux_tl - \cs_gset_protected_nopar:cpx { @@/family/\l_@@_family_aux_tl } + \@@_check_family:V \l_@@_family_name_tl + \@@_gset_family_cs:x { \l_@@_family_name_tl } + \@@_save_family_info: + \@@_set_sub_block_family: + \group_end: + } +\cs_generate_variant:Nn \xeCJK_set_family:nnn { Vnn , xxx , Vvv } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\@@_remove_duplicate_keys:N} +% \begin{macrocode} +\cs_new_protected_nopar:Npn \@@_remove_duplicate_keys:N #1 + { + \prop_clear:N \l_@@_tmp_prop + \keyval_parse:NNV \@@_prop_put_aux:n \@@_prop_put_aux:nn #1 + \clist_clear:N #1 + \prop_map_inline:Nn \l_@@_tmp_prop + { + \tl_if_blank:nTF {##2} + { \clist_put_right:Nn #1 {##1} } + { \clist_put_right:Nn #1 { ##1 = {##2} } } + } + } +\cs_generate_variant:Nn \keyval_parse:NNn { NNV } +\cs_new_protected_nopar:Npn \@@_prop_put_aux:n #1 + { \prop_put:Nnn \l_@@_tmp_prop {#1} { } } +\cs_new_protected_nopar:Npn \@@_prop_put_aux:nn #1#2 + { \prop_put:Nnn \l_@@_tmp_prop {#1} {#2} } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\@@_gset_family_cs:x} +% \begin{macrocode} +\cs_new_protected_nopar:Npn \@@_gset_family_cs:x #1 + { + \cs_gset_protected_nopar:cpx { \@@_family_csname:n {#1} } { \group_begin: - \exp_not:n { \cs_set_eq:NN \CJKfamily \use_none:n } + \@@_gobble_CJKfamily: \exp_not:n { \fontspec_set_family:Nnn \l_@@_fontspec_family_tl } - { \l_@@_pass_features_clist } { \l_@@_fontname_tl } - \prop_gput:NnV \exp_not:N \g_@@_family_name_prop - { \l_@@_family_aux_tl } \exp_not:N \l_@@_fontspec_family_tl - \cs_gset_protected_nopar:cpx { @@/family/\l_@@_family_aux_tl } - \exp_not:n - { { - \exp_not:N \fontencoding { \c_@@_encoding_tl } - \exp_not:N \fontfamily { \l_@@_fontspec_family_tl } - \exp_not:N \selectfont - } } + { \exp_not:V \l_@@_fontspec_options_clist } + { \exp_not:V \l_@@_font_name_tl } + \@@_gset_family_nfss_cs:xx {#1} { \exp_not:N \l_@@_fontspec_family_tl } \group_end: } - \@@_save_family_info: - \@@_add_sub_block: - \group_end: } -\cs_generate_variant:Nn \xeCJK_set_family:xnn { xcc } % \end{macrocode} % \end{macro} % @@ -3347,140 +3886,131 @@ $URL: https://ctex-kit.googlecode.com/svn/trunk/xeCJK/xeCJK.dtx $ % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_check_family:n #1 { - \prop_get:NnNT \g_@@_family_prop {#1} \l_@@_tmpa_tl + \prop_get:NnNT \g_@@_family_font_name_prop {#1} \l_@@_tmpa_tl { - \prop_gpop:NnNT \g_@@_family_name_prop {#1} \l_@@_tmpa_tl { } - \@@_warning:nxx { CJKfamily-redef } {#1} \l_@@_tmpa_tl + \prop_gpop:NnNT \g_@@_family_name_prop {#1} \l_@@_tmpa_tl + { \cs_undefine:c { \@@_family_nfss_csname:n {#1} } } + \@@_warning:nxx { CJKfamily-redef } {#1} { \l_@@_tmpa_tl } } } \cs_generate_variant:Nn \@@_check_family:n { V } -\@@_msg_new:nn { CJKfamily-redef } { Redefining~CJKfamily~`#1'~(#2). } +\@@_msg_new:nn { CJKfamily-redef } + { Redefining~CJKfamily~`\@@_msg_family_map:n {#1}'~(#2). } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\@@_add_font:nn,\@@_add_font_if_new:nn} % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_add_font:nn #1#2 - { - \prop_put:Nxx \l_@@_add_font_prop - { \@@_map_features_id:n {#1} Font } {#2} - } + { \prop_put:Nnn \l_@@_add_font_prop { #1 Font } {#2} } \cs_new_protected_nopar:Npn \@@_add_font_if_new:nn #1#2 - { - \prop_put_if_new:Nxx \l_@@_add_font_prop - { \@@_map_features_id:n {#1} Font } {#2} - } -\cs_generate_variant:Nn \@@_add_font:nn { nx, nc, nV, nv } -\cs_generate_variant:Nn \@@_add_font_if_new:nn { nx, nc, nV, nv } + { \prop_put_if_new:Nnn \l_@@_add_font_prop { #1 Font } {#2} } +\cs_generate_variant:Nn \@@_add_font:nn { nx , nV , nv } +\cs_generate_variant:Nn \@@_add_font_if_new:nn { nx , nV , nv } % \end{macrocode} % \end{macro} % -% \begin{macrocode} -\cs_generate_variant:Nn \prop_put:Nnn { Nxx } -\cs_generate_variant:Nn \prop_get:Nn { NV } -\cs_generate_variant:Nn \prop_get:NnNF { Nx } -\cs_generate_variant:Nn \prop_if_in:NnF { Nx } -\cs_generate_variant:Nn \prop_put_if_new:Nnn { Nxx } -% \end{macrocode} -% % \begin{macro}[internal]{\@@_add_fake_bold:n,\@@_add_fake_slant:n} % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_add_fake_bold:n #1 { - \clist_put_left:cx { l_@@_fontfeat_#1_clist } - { FakeBold = { \fp_use:N \l_@@_EmboldenFactor_fp } } + \clist_put_left:cx { l_@@_font_feat_#1_clist } + { FakeBold = { \fp_use:N \l_@@_embolden_factor_fp } } } \cs_new_protected_nopar:Npn \@@_add_fake_slant:n #1 { - \clist_put_left:cx { l_@@_fontfeat_#1_clist } - { FakeSlant = { \fp_use:N \l_@@_SlantFactor_fp } } + \clist_put_left:cx { l_@@_font_feat_#1_clist } + { FakeSlant = { \fp_use:N \l_@@_slant_factor_fp } } } % \end{macrocode} % \end{macro} % -% \begin{macro}[internal]{\@@_parse_features:,\@@_parse_features:n} +% \begin{macro}[internal]{\@@_parse_features:,\@@_parse_features:nn} % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_parse_features: - { \prop_map_inline:Nn \g_@@_features_id_prop { \@@_parse_features:n {##1} } } -\cs_new_protected_nopar:Npn \@@_parse_features:n #1 + { \prop_map_function:NN \g_@@_features_id_prop \@@_parse_features:nn } +\cs_new_protected_nopar:Npn \@@_parse_features:nn #1#2 { \@@_if_font_select:nTF {#1} { - \@@_add_font:nv {#1} { l_@@_fontname_#1_tl } + \@@_add_font:nv {#2} { l_@@_font_name_#1_tl } \@@_if_it_or_sl:nTF {#1} { - \@@_if_font_select:nF {bf#1} - { \@@_add_font_if_new:nv {bf#1} { l_@@_fontname_#1_tl } } + \@@_if_font_select:nF { bf #1 } + { \@@_add_font_if_new:nv {#2} { l_@@_font_name_#1_tl } } } { - \str_if_eq_x:nnT {#1} {bf} + \str_if_eq:nnT {#1} { bf } { - \clist_map_inline:nn { it , sl } - { - \@@_if_font_select:nF {bf##1} - { \@@_add_font:nV {bf##1} \l_@@_fontname_bf_tl } - } + \@@_if_font_select:nF { bfit } + { \@@_add_font:nV { BoldItalic } \l_@@_font_name_bf_tl } + \@@_if_font_select:nF { bfsl } + { \@@_add_font:nV { BoldSlanted } \l_@@_font_name_bf_tl } } } } - { \@@_set_fake:n {#1} } + { \@@_set_fake_font:nn {#1} {#2} } } % \end{macrocode} % \end{macro} % % \begin{macro}[pTF,internal]{\@@_if_font_select:n,\@@_if_it_or_sl:n} % \begin{macrocode} -\prg_new_conditional:Npnn \@@_if_font_select:n #1 { p, T, F, TF } +\prg_new_conditional:Npnn \@@_if_font_select:n #1 { p , T , F , TF } { - \exp_args:Nc \xeCJK_if_blank_x:nTF { l_@@_fontname_#1_tl } - \prg_return_false: \prg_return_true: + \tl_if_blank:vTF { l_@@_font_name_#1_tl } + { \prg_return_false: } { \prg_return_true: } } -\prg_new_conditional:Npnn \@@_if_it_or_sl:n #1 { p, T, F, TF } +\prg_new_conditional:Npnn \@@_if_it_or_sl:n #1 { p , T , F , TF } { - \bool_if:nTF { \str_if_eq_x_p:nn { it } {#1} || \str_if_eq_x_p:nn { sl } {#1} } - \prg_return_true: \prg_return_false: + \if_predicate:w + \bool_if_p:n { \str_if_eq_p:nn { it } {#1} || \str_if_eq_p:nn { sl } {#1} } + \prg_return_true: \else: \prg_return_false: \fi: } +\cs_generate_variant:Nn \tl_if_blank:nTF { v } % \end{macrocode} % \end{macro} % -% \begin{macro}[internal]{\@@_set_fake:n} +% \begin{macro}[internal]{\@@_set_fake_font:nn} % \begin{macrocode} -\cs_new_protected_nopar:Npn \@@_set_fake:n #1 +\cs_new_protected_nopar:Npn \@@_set_fake_font:nn #1#2 { - \str_if_eq_x:nnTF {#1} { bf } - { \bool_if:NT \l_@@_AutoFakeBold_bool { \@@_add_fake_bold:n {#1} } } + \str_if_eq:nnTF {#1} { bf } + { \bool_if:NT \l_@@_auto_fake_bold_bool { \@@_add_fake_bold:n {#1} } } { - \bool_if:NTF \l_@@_AutoFakeSlant_bool + \bool_if:NTF \l_@@_auto_fake_slant_bool { \bool_if:nT - { \@@_if_it_or_sl_p:n {#1} || - ( \str_if_eq_x_p:nn {#1} {bfit} && ! ( \@@_if_font_select_p:n {it} ) ) || - ( \str_if_eq_x_p:nn {#1} {bfsl} && ! ( \@@_if_font_select_p:n {sl} ) ) + { \@@_if_it_or_sl_p:n {#1} + || ( \str_if_eq_p:nn {#1} { bfit } + && ! ( \@@_if_font_select_p:n { it } ) ) + || ( \str_if_eq_p:nn {#1} { bfsl } + && ! ( \@@_if_font_select_p:n { sl } ) ) } { \@@_add_fake_slant:n {#1} } } - { \@@_if_it_or_sl:nT {#1} { \@@_map_it_sl:n {#1} } } + { \@@_if_it_or_sl:nT {#1} { \@@_map_it_sl:nn {#1} {#2} } } \bool_if:nT - { \l_@@_AutoFakeBold_bool + { \l_@@_auto_fake_bold_bool && ! ( \@@_if_it_or_sl_p:n {#1} ) - && ! ( \@@_if_font_select_p:n {bf} ) + && ! ( \@@_if_font_select_p:n { bf } ) } { \@@_add_fake_bold:n {#1} } } - \@@_add_font_if_new:nn {#1} * + \@@_add_font_if_new:nn {#2} { * } } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\@@_map_it_sl:n} % \begin{macrocode} -\cs_new_protected_nopar:Npn \@@_map_it_sl:n #1 +\cs_new_protected_nopar:Npn \@@_map_it_sl:nn #1#2 { \@@_if_map_font_select:nT {#1} { - \@@_add_font:nx {#1} { \@@_get_map_font:n {#1} } - \@@_if_font_select:nF {bf#1} - { \@@_add_font_if_new:nx {bf#1} { \@@_get_map_font:n {#1} } } + \@@_add_font:nx {#2} { \@@_get_map_font:n {#1} } + \@@_if_font_select:nF { bf #1 } + { \@@_add_font_if_new:nx { Bold #2 } { \@@_get_map_font:n {#1} } } } } % \end{macrocode} @@ -3489,16 +4019,16 @@ $URL: https://ctex-kit.googlecode.com/svn/trunk/xeCJK/xeCJK.dtx $ % \begin{macro}[internal]{\@@_get_map_font:n} % \begin{macrocode} \cs_new_nopar:Npn \@@_get_map_font:n #1 - { \tl_use:c { l_@@_fontname_\str_if_eq_x:nnTF {#1} {it} {sl} {it} _tl } } + { \exp_not:v { l_@@_font_name_ \xeCJK_reverse:nnn {#1} { it } { sl } _tl } } % \end{macrocode} % \end{macro} % % \begin{macro}[pTF,internal]{\@@_if_map_font_select:n} % \begin{macrocode} -\prg_new_conditional:Npnn \@@_if_map_font_select:n #1 { p, T, F, TF } +\prg_new_conditional:Npnn \@@_if_map_font_select:n #1 { p , T , F , TF } { \xeCJK_if_blank_x:nTF { \@@_get_map_font:n {#1} } - \prg_return_false: \prg_return_true: + { \prg_return_false: } { \prg_return_true: } } % \end{macrocode} % \end{macro} @@ -3509,26 +4039,24 @@ $URL: https://ctex-kit.googlecode.com/svn/trunk/xeCJK/xeCJK.dtx $ { \prop_map_inline:Nn \g_@@_features_id_prop { - \clist_if_empty:cF { l_@@_fontfeat_##1_clist } + \clist_if_empty:cF { l_@@_font_feat_##1_clist } { - \clist_put_right:Nx \l_@@_pass_features_clist - { ##2Features = { \tl_use:c { l_@@_fontfeat_##1_clist } } } + \clist_put_right:Nx \l_@@_fontspec_options_clist + { ##2Features = { \exp_not:v { l_@@_font_feat_##1_clist } } } } } \prop_map_inline:Nn \l_@@_add_font_prop - { \clist_put_right:Nx \l_@@_pass_features_clist { ##1 = { ##2 } } } - \xeCJK_if_blank_x:nF \l_@@_monoscale_tl - { \clist_put_left:Nx \l_@@_pass_features_clist \l_@@_monoscale_tl } + { \clist_put_right:Nn \l_@@_fontspec_options_clist { ##1 = { ##2 } } } } % \end{macrocode} % \end{macro} % % \begin{macro}[internal,var] -% {\g_@@_family_prop,\g_@@_family_name_prop,\g_@@_family_options_prop} +% {\g_@@_family_name_prop,\g_@@_family_font_name_prop,\g_@@_family_font_options_prop} % \begin{macrocode} -\prop_new:N \g_@@_family_prop \prop_new:N \g_@@_family_name_prop -\prop_new:N \g_@@_family_options_prop +\prop_new:N \g_@@_family_font_name_prop +\prop_new:N \g_@@_family_font_options_prop % \end{macrocode} % \end{macro} % @@ -3537,60 +4065,58 @@ $URL: https://ctex-kit.googlecode.com/svn/trunk/xeCJK/xeCJK.dtx $ \cs_new_protected_nopar:Npn \@@_save_family_info: { \group_begin: - \clist_map_inline:Nn \g_@@_CJK_subclass_clist - { - \clist_remove_all:Nn \l_@@_fontoptions_clist {##1} - \clist_remove_all:Nn \l_@@_fontoptions_clist { ##1 = } - } - \prop_gput:NVV \g_@@_family_prop \l_@@_family_aux_tl \l_@@_fontname_tl - \prop_gput:NVV \g_@@_family_options_prop \l_@@_family_aux_tl \l_@@_fontoptions_clist + \seq_map_inline:Nn \g_@@_CJK_sub_class_seq + { \clist_remove_all:Nn \l_@@_font_options_clist {##1} } + \prop_gput:NVV \g_@@_family_font_name_prop + \l_@@_family_name_tl \l_@@_font_name_tl + \prop_gput:NVV \g_@@_family_font_options_prop + \l_@@_family_name_tl \l_@@_font_options_clist \group_end: } % \end{macrocode} % \end{macro} % -% \begin{macro}[internal]{\@@_add_sub_block:} +% \begin{macro}[internal]{\@@_set_sub_block_family:} % \begin{macrocode} -\cs_new_protected_nopar:Npn \@@_add_sub_block: +\cs_new_protected_nopar:Npn \@@_set_sub_block_family: { - \clist_remove_duplicates:N \l_@@_sub_key_clist - \clist_map_inline:Nn \l_@@_sub_key_clist + \seq_map_inline:Nn \l_@@_sub_key_seq { - \tl_set:Nx \l_@@_sub_family_tl { \l_@@_family_aux_tl/##1 } - \bool_if:cT { l_@@_copy_##1_bool } + \tl_set:Nx \l_@@_sub_family_tl { \l_@@_family_name_tl/##1 } + \bool_if:cT { l_@@_copy_##1_bool } { \@@_copy_sub_family:n {##1} } + \bool_if:cT { l_@@_add_##1_bool } { - \@@_check_family:V \l_@@_sub_family_tl - \prop_get:NVNT \g_@@_family_prop \l_@@_family_aux_tl \l_@@_tmpa_tl - { \prop_gput:NVV \g_@@_family_prop \l_@@_sub_family_tl \l_@@_tmpa_tl } - \prop_get:NVNT \g_@@_family_options_prop \l_@@_family_aux_tl \l_@@_tmpa_clist - { - \clist_remove_all:Nn \l_@@_tmpa_clist { ##1 = * } - \prop_gput:NVV \g_@@_family_options_prop \l_@@_sub_family_tl \l_@@_tmpa_clist - } - \cs_gset_protected_nopar:cpx { @@/family/\l_@@_sub_family_tl } - { - \xeCJK_family_if_exist:xT { \l_@@_family_aux_tl } - { - \prop_get:NnNT \exp_not:N \g_@@_family_name_prop - { \l_@@_family_aux_tl } \exp_not:N \l_@@_tmpa_tl - { - \prop_gput:NnV \exp_not:N \g_@@_family_name_prop - { \l_@@_sub_family_tl } \exp_not:N \l_@@_tmpa_tl - \cs_gset_protected_nopar:cpx { @@/family/\l_@@_sub_family_tl } - \exp_not:n - { { - \exp_not:N \fontencoding { \c_@@_encoding_tl } - \exp_not:N \fontfamily { \l_@@_tmpa_tl } - \exp_not:N \selectfont - } } - } - } - } + \xeCJK_set_family:Vvv \l_@@_sub_family_tl + { l_@@_##1_font_options_clist } { l_@@_##1_font_name_tl } } - \bool_if:cT { l_@@_add_##1_bool } + } + } +\cs_new_protected_nopar:Npn \@@_copy_sub_family:n #1 + { + \@@_check_family:V \l_@@_sub_family_tl + \prop_get:NVNT \g_@@_family_font_name_prop + \l_@@_family_name_tl \l_@@_tmpa_tl + { + \prop_gput:NVV \g_@@_family_font_name_prop + \l_@@_sub_family_tl \l_@@_tmpa_tl + } + \prop_get:NVNT \g_@@_family_font_options_prop + \l_@@_family_name_tl \l_@@_tmpa_clist + { + \clist_remove_all:Nn \l_@@_tmpa_clist { #1 = * } + \prop_gput:NVV \g_@@_family_font_options_prop + \l_@@_sub_family_tl \l_@@_tmpa_clist + } + \cs_gset_protected_nopar:cpx { \@@_family_csname:n { \l_@@_sub_family_tl } } + { + \xeCJK_family_if_exist:xT { \l_@@_family_name_tl } { - \xeCJK_set_family:xcc \l_@@_sub_family_tl - { l_@@_##1_fontfeat_clist } { l_@@_##1_fontname_tl } + \prop_get:NnNT \exp_not:N \g_@@_family_name_prop + { \l_@@_family_name_tl } \exp_not:N \l_@@_tmpa_tl + { + \@@_gset_family_nfss_cs:xx + { \l_@@_sub_family_tl } { \exp_not:N \l_@@_tmpa_tl } + } } } } @@ -3604,9 +4130,18 @@ $URL: https://ctex-kit.googlecode.com/svn/trunk/xeCJK/xeCJK.dtx $ \xeCJK_family_if_exist:xT {#2} { \tl_map_inline:nn - { \g_@@_family_prop \g_@@_family_options_prop \g_@@_family_name_prop } - { \prop_get:NnNT ##1 {#2} \l_@@_tmpa_tl { \prop_gput:NnV ##1 {#1} \l_@@_tmpa_tl } } - \cs_gset_eq:cc { @@/family/#1 } { @@/family/#2 } + { + \g_@@_family_name_prop + \g_@@_family_font_name_prop + \g_@@_family_font_options_prop + } + { + \prop_get:NnNT ##1 {#2} \l_@@_tmpa_tl + { \prop_gput:NnV ##1 {#1} \l_@@_tmpa_tl } + } + \cs_gset_eq:cc + { \@@_family_nfss_csname:n {#1} } + { \@@_family_nfss_csname:n {#2} } } } \cs_generate_variant:Nn \@@_copy_family:nn { xx } @@ -3615,57 +4150,108 @@ $URL: https://ctex-kit.googlecode.com/svn/trunk/xeCJK/xeCJK.dtx $ % % \subsection{字体切换} % -% \begin{macro}[internal]{\l_xeCJK_font_coor_tl,\xeCJK_select_font:,\@@_switch_font:nn} +% \begin{macro}[internal]{\l_xeCJK_current_font_tl,\xeCJK_select_font:,\xeCJK_select_font:x} % 缓存当前字体的原始格式,以加速编译。 % \begin{macrocode} -\tl_set:Nn \l_xeCJK_font_coor_tl { @@/\l_xeCJK_family_tl/\f@series/\f@shape/\f@size } +\tl_new:N \l_xeCJK_current_font_tl +\tl_set:Nn \l_xeCJK_current_font_tl { \@@_font_csname:n { \l_xeCJK_family_tl } } +\cs_new_nopar:Npn \@@_font_csname:n #1 { xeCJK/#1/\f@series/\f@shape/\f@size } \cs_new_protected_nopar:Npn \xeCJK_select_font: { - \cs_if_exist_use:cF { \l_xeCJK_font_coor_tl } + \cs_if_exist_use:cF { \l_xeCJK_current_font_tl } { - \tl_set:Nx \l_@@_current_coor_tl \l_xeCJK_font_coor_tl - \cs_if_exist_use:cT { @@/family/\l_xeCJK_family_tl } - { \exp_last_unbraced:NNV \cs_gset_eq:cN \l_@@_current_coor_tl \tex_font:D } + \tl_set:Nx \l_@@_current_coor_tl { \l_xeCJK_current_font_tl } + \@@_family_use:x { \l_xeCJK_family_tl } + \xeCJK_font_gset_to_current:c { \l_@@_current_coor_tl } + } + } +\cs_new_protected_nopar:Npn \xeCJK_select_font:x #1 + { + \cs_if_exist_use:cF { \@@_font_csname:n {#1} } + { + \tl_set:Nx \l_@@_current_coor_tl { \@@_font_csname:n {#1} } + \@@_family_use:x {#1} + \xeCJK_font_gset_to_current:c { \l_@@_current_coor_tl } } } \cs_new_eq:NN \xeCJK@setfont \xeCJK_select_font: +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\@@_switch_font:nn} +% \changes{v3.1.0}{2012/11/18}{改进 \cs{@@_switch_font:nn} 的定义。} +% 两个 CJK 分区之间的字体切换。 +% \begin{macrocode} \cs_new_protected_nopar:Npn \@@_switch_font:nn #1#2 { - \str_if_eq_x:nnF {#1} {#2} + \str_if_eq:nnF {#1} {#2} { \@@_info:nxx { CJK-block } {#1} {#2} - \tl_remove_all:Nn \l_xeCJK_family_tl { /#1 } - \str_if_eq_x:nnF {#2} { CJK } + \str_if_eq:nnTF {#2} { CJK } + { \xeCJK_select_font: } + { \@@_block_select_font:n {#2} } + } + } +\@@_msg_new:nn { CJK-block } { Switch~from~block~'#1'~to~'#2'. } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\@@_block_select_font:n} +% 若当前 CJK 字体族没有定义子分区 |#1| 的字体,则使用 \cs{CJKfamilydefault} 的对应 +% 分区字体;若 \cs{CJKfamilydefault} 也没有定义该分区字体,则使用当前 CJK 字体族的 +% 主分区字体。 +% \begin{macrocode} +\cs_new_protected_nopar:Npn \@@_block_select_font:n #1 + { + \cs_if_exist_use:cF { \@@_font_csname:n { \l_xeCJK_family_tl/#1 } } + { + \tl_set:Nx \l_@@_current_coor_tl + { \@@_font_csname:n { \l_xeCJK_family_tl/#1 } } + \xeCJK_family_if_exist:xF { \l_xeCJK_family_tl/#1 } { - \tl_set:Nx \l_@@_tmpa_tl \l_xeCJK_family_tl - \tl_put_right:Nx \l_xeCJK_family_tl { /#2 } - \xeCJK_family_if_exist:xF \l_xeCJK_family_tl + \@@_copy_family:xx { \l_xeCJK_family_tl/#1 } { - \xeCJK_family_if_exist:xTF { \CJKfamilydefault/#2 } - { \@@_copy_family:xx \l_xeCJK_family_tl { \CJKfamilydefault/#2 } } - { \@@_copy_family:xx \l_xeCJK_family_tl \l_@@_tmpa_tl } + \cs_if_exist:cTF { \@@_family_csname:n { \CJKfamilydefault/#1 } } + { \CJKfamilydefault/#1 } { \l_xeCJK_family_tl } } } + \@@_family_use:x { \l_xeCJK_family_tl/#1 } + \xeCJK_font_gset_to_current:c { \l_@@_current_coor_tl } } - \xeCJK_select_font: } -\@@_msg_new:nn { CJK-block } { Switch~from~block~'#1'~to~'#2'. } % \end{macrocode} % \end{macro} % -% \begin{macro}[TF,internal]{\xeCJK_family_if_exist:x} +% \begin{macro}[internal] +% {\@@_family_csname:n,\@@_family_nfss_csname:n, +% \@@_family_use:x,\@@_gset_family_nfss_cs:xx} % \begin{macrocode} -\prg_new_protected_conditional:Npnn \xeCJK_family_if_exist:x #1 { T, F, TF } +\cs_new_nopar:Npn \@@_family_csname:n #1 { xeCJK/family/#1 } +\cs_new_nopar:Npn \@@_family_nfss_csname:n #1 { xeCJK/family/nfss/#1 } +\cs_new_nopar:Npn \@@_family_use:x #1 { \use:c { \@@_family_nfss_csname:n {#1} } } +\cs_new_protected_nopar:Npn \@@_gset_family_nfss_cs:xx #1#2 { - \cs_if_free:cTF { @@/family/#1 } - { \prg_return_false: } + \prop_gput:Nxx \g_@@_family_name_prop {#1} {#2} + \cs_gset_protected_nopar:cpx { \@@_family_nfss_csname:n {#1} } { - \prop_get:NxNF \g_@@_family_name_prop {#1} \l_@@_family_name_tl - { \use:c { @@/family/#1 } } - \prg_return_true: + \exp_not:N \fontencoding { \c_@@_encoding_tl } + \exp_not:N \fontfamily {#2} + \exp_not:N \selectfont } } -\cs_generate_variant:Nn \prop_get:NnNTF { Nx } +\cs_generate_variant:Nn \prop_gput:Nnn { Nxx } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[TF,internal]{\xeCJK_family_if_exist:x} +% \begin{macrocode} +\prg_new_protected_conditional:Npnn \xeCJK_family_if_exist:x #1 { T , F , TF } + { + \cs_if_exist:cTF { \@@_family_nfss_csname:n {#1} } + { \use_i:nn } + { \cs_if_exist_use:cTF { \@@_family_csname:n {#1} } } + { \prg_return_true: } { \prg_return_false: } + } % \end{macrocode} % \end{macro} % @@ -3686,7 +4272,7 @@ $URL: https://ctex-kit.googlecode.com/svn/trunk/xeCJK/xeCJK.dtx $ { \tl_set:Nx \l_xeCJK_family_tl {#3} \tl_set_eq:NN \xeCJK@family \l_xeCJK_family_tl - \IfBooleanT {#1} { \use:c { @@/family/#3 } } + \IfBooleanT {#1} { \@@_family_use:x {#3} } } { \@@_family_unknown_warning:x {#3} } } @@ -3696,35 +4282,44 @@ $URL: https://ctex-kit.googlecode.com/svn/trunk/xeCJK/xeCJK.dtx $ % \end{macrocode} % \end{macro} % -% \begin{macro} -% {\xeCJK_family_if_exist_use:x,\@@_family_unknown_warning:x,\g_@@_unknown_family_seq} +% \begin{macro}[var,internal]{\l_xeCJK_family_tl} +% 用于保存文档当前正在使用的 CJK 字体族。 +% \begin{macrocode} +\tl_new:N \l_xeCJK_family_tl +\tl_set:Nn \l_xeCJK_family_tl { \CJKfamilydefault } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\@@_gobble_CJKfamily:} +% \begin{macrocode} +\cs_new_protected_nopar:Npn \@@_gobble_CJKfamily: + { \cs_set_eq:NN \CJKfamily \@@_gobble_CJKfamily:wn } +\DeclareExpandableDocumentCommand \@@_gobble_CJKfamily:wn { t+ t- m } { } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal] +% {\xeCJK_family_if_exist_use:x,\@@_family_unknown_warning:n} % \begin{macrocode} \cs_new_protected_nopar:Npn \xeCJK_family_if_exist_use:x #1 { \xeCJK_family_if_exist:xTF {#1} - { \use:c { @@/family/#1 } } + { \@@_family_use:x {#1} } { \@@_family_unknown_warning:x {#1} } } -\cs_new_protected_nopar:Npn \@@_family_unknown_warning:x #1 +\cs_new_protected_nopar:Npn \@@_family_unknown_warning:n #1 { - \seq_if_in:NxF \g_@@_unknown_family_seq {#1} + \seq_if_in:NnF \g_@@_unknown_family_seq {#1} { - \seq_gput_right:Nx \g_@@_unknown_family_seq {#1} + \seq_gput_right:Nn \g_@@_unknown_family_seq {#1} \@@_warning:nx { CJKfamily-Unknown } {#1} } } +\cs_generate_variant:Nn \@@_family_unknown_warning:n { x } \seq_new:N \g_@@_unknown_family_seq \@@_msg_new:nn { CJKfamily-Unknown } { - Unknown~CJK~family~' - \str_case_x:nnn {#1} - { - \CJKrmdefault { \token_to_str:N \CJKrmdefault } - \CJKsfdefault { \token_to_str:N \CJKsfdefault } - \CJKttdefault { \token_to_str:N \CJKttdefault } - } - {#1} - '~is~ignored.\\\\ + Unknown~CJK~family~`\@@_msg_family_map:n {#1}'~is~being~ignored.\\\\ Try~to~use~ \str_case_x:nnn {#1} { @@ -3735,36 +4330,74 @@ $URL: https://ctex-kit.googlecode.com/svn/trunk/xeCJK/xeCJK.dtx $ { \token_to_str:N \setCJKfamilyfont {#1} } [...]{...}~to~define~it. } +\cs_new_nopar:Npn \@@_msg_family_map:n #1 + { + \str_case_x:nnn {#1} + { + \CJKrmdefault { \token_to_str:N \CJKrmdefault } + \CJKsfdefault { \token_to_str:N \CJKsfdefault } + \CJKttdefault { \token_to_str:N \CJKttdefault } + } + {#1} + } % \end{macrocode} % \end{macro} % +% \begin{macro}{\setCJKmainfont,\setCJKsansfont,\setCJKmonofont} +% 设置文档的 CJK 普通字体、无衬线和等宽字体。 +% \begin{macrocode} +\NewDocumentCommand \setCJKmainfont { O{} m } + { \xeCJK_set_family:xxx { \CJKrmdefault } {#1} {#2} } +\cs_new_eq:NN \setCJKromanfont \setCJKmainfont +\NewDocumentCommand \setCJKsansfont { O{} m } + { \xeCJK_set_family:xxx { \CJKsfdefault } {#1} {#2} } +\NewDocumentCommand \setCJKmonofont { O{} m } + { \xeCJK_set_family:xxx { \CJKttdefault } {#1} {#2} } +% \end{macrocode} +% \end{macro} +% +% \begin{macrocode} +\@onlypreamble \setCJKmainfont +\@onlypreamble \setCJKmathfont +\@onlypreamble \setCJKsansfont +\@onlypreamble \setCJKmonofont +\@onlypreamble \setCJKromanfont +% \end{macrocode} +% % \begin{macro}{\setCJKfamilyfont, \newCJKfontfamily, \CJKfontspec} % 分别用于预声明 CJK 字体和随机调用 CJK 字体。 % \begin{macrocode} \NewDocumentCommand \setCJKfamilyfont { m O{} m } - { \xeCJK_set_family:xnn {#1} {#2} {#3} } + { \xeCJK_set_family:xxx {#1} {#2} {#3} } \NewDocumentCommand \newCJKfontfamily { o m O{} m } { - \tl_set:Nx \l_@@_family_aux_tl { \IfNoValueTF {#1} { \cs_to_str:N #2 } {#1} } - \xeCJK_set_family:xnn \l_@@_family_aux_tl {#3} {#4} - \cs_new_protected_nopar:Npx #2 { \exp_not:N \CJKfamily { \l_@@_family_aux_tl } } + \tl_set:Nx \l_@@_tmpa_tl { \IfNoValueTF {#1} { \cs_to_str:N #2 } {#1} } + \cs_new_protected_nopar:Npx #2 { \CJKfamily { \l_@@_tmpa_tl } } + \xeCJK_set_family:xxx { \l_@@_tmpa_tl } {#3} {#4} } -\int_new:N \g_@@_fontspec_int -\int_gdecr:N \g_@@_fontspec_int \NewDocumentCommand \CJKfontspec { O{} m } { - \tl_set:Nx \l_@@_CJKfontspec_id_tl { CJKfontspec/#1/#2/id } - \cs_if_free:cT \l_@@_CJKfontspec_id_tl + \xeCJK_fontspec:xx {#1} {#2} + \tex_ignorespaces:D + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\xeCJK_fontspec:nn} +% \begin{macrocode} +\cs_new_protected_nopar:Npn \xeCJK_fontspec:nn #1#2 + { + \tl_set:Nx \l_@@_tmpa_tl { \tl_to_str:n { CJKfontspec/#1/#2/id } } + \tl_if_exist:cF { \l_@@_tmpa_tl } { - \int_gincr:N \g_@@_fontspec_int - \tl_gset:Nx \g_@@_family_spec_tl - { CJKfontspec ( \int_use:N \g_@@_fontspec_int ) } - \xeCJK_set_family:xnn \g_@@_family_spec_tl {#1} {#2} - \tl_gset:cx \l_@@_CJKfontspec_id_tl \g_@@_family_spec_tl + \tl_set:Nx \l_@@_tmpb_tl + { CJKfontspec ( \int_eval:n { \g_@@_family_int + \c_one } ) } + \tl_gset_eq:cN { \l_@@_tmpa_tl } \l_@@_tmpb_tl + \xeCJK_set_family:Vnn \l_@@_tmpb_tl {#1} {#2} } - \exp_args:Nv \CJKfamily \l_@@_CJKfontspec_id_tl - \tex_ignorespaces:D + \exp_args:Nc \CJKfamily { \l_@@_tmpa_tl } } +\cs_generate_variant:Nn \xeCJK_fontspec:nn { VV , xx } % \end{macrocode} % \end{macro} % @@ -3774,47 +4407,36 @@ $URL: https://ctex-kit.googlecode.com/svn/trunk/xeCJK/xeCJK.dtx $ \clist_new:N \g_@@_default_features_clist \NewDocumentCommand \defaultCJKfontfeatures { m } { \clist_gset:Nn \g_@@_default_features_clist {#1} } -\defaultCJKfontfeatures { Script = CJK } \@onlypreamble \defaultCJKfontfeatures \NewDocumentCommand \addCJKfontfeatures { m } { - \prop_if_in:NVTF \g_@@_family_prop \l_xeCJK_family_tl + \xeCJK_add_font_features:x {#1} + \tex_ignorespaces:D + } +\cs_new_eq:NN \addCJKfontfeature \addCJKfontfeatures +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\xeCJK_add_font_features:n} +% \begin{macrocode} +\cs_new_protected_nopar:Npn \xeCJK_add_font_features:n #1 + { + \prop_get:NVNTF \g_@@_family_font_name_prop \l_xeCJK_family_tl \l_@@_tmpa_tl { - \group_begin: - \clist_set:Nx \l_@@_tmpa_clist {#1} - \prop_get:NVN \g_@@_family_prop \l_xeCJK_family_tl \l_@@_tmpa_tl - \clist_map_inline:Nn \g_@@_CJK_subclass_clist + \clist_set:Nn \l_@@_tmpa_clist {#1} + \seq_map_function:NN + \g_@@_CJK_sub_class_seq \@@_parse_sub_class_features:n + \prop_get:NVNT \g_@@_family_font_options_prop + \l_xeCJK_family_tl \l_@@_tmpb_clist { - \clist_if_in:NnT \l_@@_tmpa_clist {##1} - { - \clist_remove_all:Nn \l_@@_tmpa_clist {##1} - \prop_get:NxNF \g_@@_family_prop { \l_xeCJK_family_tl/##1 } \l_@@_tmpb_tl - { - \prop_get:NxNF \g_@@_family_prop - { \CJKfamilydefault/##1 } \l_@@_tmpb_tl - { \tl_set:Nx \l_@@_tmpb_tl \l_@@_tmpa_tl } - } - \clist_set:Nx \l_@@_tmpa_clist - { ##1 = { [ \l_@@_tmpa_clist ] { \l_@@_tmpb_tl } } } - \clist_map_break: - } - } - \prop_get:NVNF \g_@@_family_options_prop \l_xeCJK_family_tl \l_@@_tmpb_clist - { \clist_clear:N \l_@@_tmpb_clist } - \clist_clear:N \l_@@_tmpc_clist - \clist_map_inline:Nn \l_@@_tmpb_clist - { - \clist_if_in:NnF \l_@@_tmpa_clist {##1} - { \clist_put_right:Nn \l_@@_tmpc_clist {##1} } + \clist_concat:NNN + \l_@@_tmpa_clist \l_@@_tmpb_clist \l_@@_tmpa_clist } - \clist_put_left:NV \l_@@_tmpa_clist \l_@@_tmpc_clist - \use:x - { \group_end: \CJKfontspec [ \l_@@_tmpa_clist ] { \l_@@_tmpa_tl } } + \xeCJK_fontspec:VV \l_@@_tmpa_clist \l_@@_tmpa_tl } { \@@_warning:n { addCJKfontfeature-ignored } } - \tex_ignorespaces:D } -\cs_new_eq:NN \addCJKfontfeature \addCJKfontfeatures +\cs_generate_variant:Nn \xeCJK_add_font_features:n { x } \@@_msg_new:nn { addCJKfontfeature-ignored } { \token_to_str:N \addCJKfontfeature (s)~ignored.\\\\ @@ -3823,267 +4445,310 @@ $URL: https://ctex-kit.googlecode.com/svn/trunk/xeCJK/xeCJK.dtx $ % \end{macrocode} % \end{macro} % -% \begin{macro}{\setCJKmainfont,\setCJKsansfont} -% 设置文档的 CJK 普通字体、无衬线字体。 +% \begin{macro}[internal]{\@@_parse_sub_class_features:n} % \begin{macrocode} -\NewDocumentCommand \setCJKmainfont { O{} m } - { \xeCJK_set_family:xnn \CJKrmdefault {#1} {#2} } -\cs_new_eq:NN \setCJKromanfont \setCJKmainfont -\NewDocumentCommand \setCJKsansfont { O{} m } - { \xeCJK_set_family:xnn \CJKsfdefault {#1} {#2} } +\cs_new_protected_nopar:Npn \@@_parse_sub_class_features:n #1 + { + \clist_if_in:NnT \l_@@_tmpa_clist {#1} + { + \clist_remove_all:Nn \l_@@_tmpa_clist {#1} + \prop_get:NoNF \g_@@_family_font_name_prop + { \l_xeCJK_family_tl/#1 } \l_@@_tmpb_tl + { + \prop_get:NxNF \g_@@_family_font_name_prop + { \CJKfamilydefault/#1 } \l_@@_tmpb_tl + { \tl_set_eq:NN \l_@@_tmpb_tl \l_@@_tmpa_tl } + } + \clist_set:Nx \l_@@_tmpa_clist + { #1 = { [ \exp_not:V \l_@@_tmpa_clist ] { \exp_not:V \l_@@_tmpb_tl } } } + \clist_map_break: + } + } +\cs_generate_variant:Nn \prop_get:NnNF { Nx } % \end{macrocode} % \end{macro} % -% \begin{macro}{\CJKrmdefault,\CJKsfdefault,\CJKttdefault,\CJKfamilydefault} +% 在导言区结束的时候,若没有声明 CJK 字体,则给出一个警告。并在此时设置数学字体。 % \begin{macrocode} -\tl_if_exist:NF \CJKrmdefault { \tl_set:Nn \CJKrmdefault { rm } } -\tl_if_exist:NF \CJKsfdefault { \tl_set:Nn \CJKsfdefault { sf } } -\tl_if_exist:NF \CJKttdefault { \tl_set:Nn \CJKttdefault { tt } } -\tl_if_exist:NF \CJKfamilydefault { \tl_set:Nn \CJKfamilydefault { \CJKrmdefault } } -\tl_new:c { @@/family/\CJKfamilydefault } -% \end{macrocode} -% \end{macro} -% -% 补丁 \cs{normalfont},\cs{rmfamily},\cs{n\sffamily} 和 \cs{ttfamily},使其同时对 -% CJK 字体族有效。 -% \begin{macrocode} -\AtEndOfPackage +\@@_at_end_preamble:n { - \etex_protected:D \tl_put_right:Nn \normalfont { \CJKfamily \CJKfamilydefault } - \etex_protected:D \tl_put_right:Nn \rmfamily { \CJKfamily \CJKrmdefault } - \etex_protected:D \tl_put_right:Nn \sffamily { \CJKfamily \CJKsfdefault } - \etex_protected:D \tl_put_right:Nn \ttfamily { \CJKfamily \CJKttdefault } - \cs_set_eq:NN \reset@font \normalfont + \prop_if_empty:NTF \g_@@_family_font_name_prop + { \@@_warning:n { no-CJKfamily } } + { + \CJKfamily { \CJKfamilydefault } + \bool_if:NT \g_@@_math_bool { \xeCJK_set_mathfont: } + } + } +\@@_msg_new:nn { no-CJKfamily } + { + It~seems~that~you~have~not~declare~a~CJKfamily.\\ + If~you~want~to~use~xeCJK~in~the~right~way,~you~should~use\\\\ + \token_to_str:N \xeCJKmainfont[...]{...}\\\\ + in~the~preamble~to~declare~the~main~CJKfamily.\\ } % \end{macrocode} % -% 为了保证 CJK 数学字体的正确设置,应在导言区内设置 CJK 字体。 -% \begin{macrocode} -\@onlypreamble \setCJKmainfont -\@onlypreamble \setCJKmathfont -\@onlypreamble \setCJKsansfont -\@onlypreamble \setCJKmonofont -\@onlypreamble \setCJKromanfont -% \end{macrocode} % % \subsection{数学字体设置} % +% \begin{macro}{CJKmath} +% 是否启用 CJK 数学字体的宏包选项。 +% \begin{macrocode} +\keys_define:nn { xeCJK / options } { CJKmath .bool_gset:N = \g_@@_math_bool } +% \end{macrocode} +% \end{macro} +% % \begin{macro}{\setCJKmathfont} % 设置 CJK 数学字体。 % \begin{macrocode} \NewDocumentCommand \setCJKmathfont { O{} m } - { \xeCJK_set_family:xnn \c_@@_math_tl {#1} {#2} } + { \xeCJK_set_family:xxx { \c_@@_math_tl } {#1} {#2} } +\tl_const:Nn \c_@@_math_tl { CJKmath } % \end{macrocode} % \end{macro} % -% \begin{macro}{CJKmath} -% 数学公式内的 CJK 字体。 +% \begin{macro}[internal]{\xeCJK_set_mathfont:} +% 当没有设置 CJK 数学字体时,使用 \cs{CJKfamilydefault} 作为数学字体。 % \begin{macrocode} -\tl_const:Nn \c_@@_math_tl { CJKmath } -\keys_define:nn { xeCJK / options } { CJKmath .bool_gset:N = \g_@@_math_bool } +\cs_new_protected_nopar:Npn \xeCJK_set_mathfont: + { + \xeCJK_family_if_exist:xTF { \c_@@_math_tl } + { \tl_set:Nx \l_@@_tmpa_tl { \c_@@_math_tl } } + { + \xeCJK_family_if_exist:xTF { \CJKfamilydefault } + { \tl_set:Nx \l_@@_tmpa_tl { \CJKfamilydefault } } + { \use_none:nnnnn } + } + \prop_get:NVNT \g_@@_family_name_prop \l_@@_tmpa_tl \l_@@_tmpb_tl + { + \tl_const:Nx \c_@@_math_family_tl { \l_@@_tmpb_tl } + \DeclareSymbolFont \c_@@_math_tl + \c_@@_encoding_tl \c_@@_math_family_tl \mddefault \shapedefault + \SetSymbolFont \c_@@_math_tl { bold } + \c_@@_encoding_tl \c_@@_math_family_tl \bfdefault \shapedefault + \int_const:Nn \c_xeCJK_math_fam_int { \use:c { sym \c_@@_math_tl } } + \clist_concat:NNN + \l_@@_tmpa_clist \c_@@_CJK_chars_clist \c_@@_FullLeft_chars_clist + \clist_concat:NNN + \l_@@_tmpa_clist \l_@@_tmpa_clist \c_@@_FullRight_chars_clist + \clist_map_inline:Nn \l_@@_tmpa_clist + { + \@@_set_char_class_aux:Nnw \xeCJK_gset_mathcode:nnnn {##1} + { \c_seven } { \c_xeCJK_math_fam_int } + } + } + } % \end{macrocode} % \end{macro} % -% \begin{macro}[internal]{\xeCJKsetmathcode} +% \begin{macro}[internal]{\xeCJK_gset_mathcode:nnnn} % \begin{macrocode} -\NewDocumentCommand \xeCJKsetmathcode { m m m m } +\cs_new_protected_nopar:Npn \xeCJK_gset_mathcode:nnnn #1#2#3#4 { \@@_check_num_range:nnNN {#1} {#2} \l_@@_tmpa_int \l_@@_tmpb_int - \int_set:Nn \l_@@_tmpc_int { \@@_math_type:n {#3} } - \int_set:Nn \l_tmpa_int { \use:c { sym #4 } } \xeCJK_int_until_do:nn { \l_@@_tmpa_int > \l_@@_tmpb_int } { - \XeTeXmathcode \l_@@_tmpa_int = \l_@@_tmpc_int \l_tmpa_int \l_@@_tmpa_int + \tex_global:D \XeTeXmathcode \l_@@_tmpa_int = #3 ~ #4 \l_@@_tmpa_int \int_incr:N \l_@@_tmpa_int } } -\cs_new_eq:NN \@@_math_type:n \mathchar@type % \end{macrocode} % \end{macro} % -% \begin{macro}[internal]{\xeCJK_set_mathfont:} +% +% \subsection{抄录环境中的间距调整} +% +% \changes{v3.1.0}{2012/11/19}{放弃使用放缩字体大小的方式,而只采用调整间距的方式 +% 与西文等宽字体对齐。并且只适用于与抄录环境下。} +% +% \begin{macro}{\xeCJKVerbAddon} +% \changes{v3.1.0}{2012/11/19}{新增 \cs{xeCJKVerbAddon} 用于抄录环境中的间距调整。} +% \cs{xeCJKVerbAddon} 进行了比较大的调整,应该只在分组环境里使用。为了方便调整间距 +% 以利于对齐,这里只把字符分成了两类,并且在 CJK 类与边界(空格)之间也插入 +% \cs{CJKecglue}。当然,这样做之后,关于标点符号的禁则就没有了。 % \begin{macrocode} -\cs_new_protected_nopar:Npn \xeCJK_set_mathfont: +\NewDocumentCommand \xeCJKVerbAddon { } { - \xeCJK_family_if_exist:xTF \c_@@_math_tl - { \tl_set:Nx \l_@@_tmpa_tl \c_@@_math_tl } - { - \xeCJK_family_if_exist:xTF \CJKfamilydefault - { \tl_set:Nx \l_@@_tmpa_tl \CJKfamilydefault } - { \tl_set_eq:NN \l_@@_tmpa_tl \q_no_value } - } - \prop_get:NVNT \g_@@_family_name_prop \l_@@_tmpa_tl \l_@@_math_family_tl + \int_compare:nNnF \etex_currentgrouplevel:D = \c_zero { - \DeclareSymbolFont \c_@@_math_tl \c_@@_encoding_tl - \l_@@_math_family_tl \mddefault \shapedefault - \SetSymbolFont \c_@@_math_tl { bold } \c_@@_encoding_tl - \l_@@_math_family_tl \bfdefault \shapedefault - \clist_map_inline:nn { CJK, FullLeft, FullRight } + \@@_set_verb_exspace: + \bool_if:NF \l_@@_verb_addon_bool { - \clist_map_inline:cn { g_@@_##1_range_clist } - { - \@@_set_char_class_aux:Nn \xeCJKsetmathcode {####1} - \mathalpha \c_@@_math_tl - } + \bool_set_true:N \l_@@_verb_addon_bool + \@@_set_char_class_eq:nn { CJK } { FullLeft } + \@@_set_char_class_eq:nn { CJK } { FullRight } + \@@_set_char_class_eq:nn { Default } { HalfLeft } + \@@_set_char_class_eq:nn { Default } { HalfRight } + \@@_set_char_class_eq:nn { Default } { NormalSpace } + \xeCJKsetup { xCJKecglue = false } + \cs_set_protected_nopar:Npn \CJKglue + { \skip_horizontal:N \g_@@_verb_exspace_skip } + \cs_set_protected_nopar:Npn \CJKecglue + { \skip_horizontal:N 0.5 \g_@@_verb_exspace_skip } + \cs_set_eq:NN \xeCJK_check_for_glue: \CJKecglue + \cs_set_eq:NN \xeCJK_ignore_spaces:w \CJKecglue + \skip_set:Nn \tex_rightskip:D { \c_zero_dim plus 1 fil } } } } +\bool_new:N \l_@@_verb_addon_bool +\cs_new_eq:NN \CJKfixedspacing \xeCJKVerbAddon % \end{macrocode} % \end{macro} % -% 当没有设置 CJK 数学字体时,使用 \cs{CJKfamilydefault} 作为数学字体。 -% \begin{macrocode} -\@@_AtEndPreamble:n - { - \normalfont - \prop_if_empty:NTF \g_@@_family_prop - { \@@_warning:n { no-CJKfamily } } - { \bool_if:NT \g_@@_math_bool { \xeCJK_set_mathfont: } } - } -\@@_msg_new:nn { no-CJKfamily } - { - It~seems~that~you~have~not~declare~a~CJKfamily.\\ - If~you~want~to~use~xeCJK~in~the~right~way,~you~should~use\\\\ - \token_to_str:N \xeCJKmainfont[...]{...}\\\\ - in~the~preamble~to~declare~the~main~CJKfamily.\\ - } -% \end{macrocode} -% -% \subsection{处理等宽字体和抄录环境} -% -% \begin{macro}[internal,var]{\g_@@_monoscale_fp,\g_@@_exspace_dim} +% 总是在 \LaTeX 的抄录环境(包括 \cs{verb})里使用 \cs{xeCJKVerbAddon},以保证代码 +% 的对齐。 % \begin{macrocode} -\fp_new:N \g_@@_monoscale_fp -\fp_set_eq:NN \g_@@_monoscale_fp \c_one_fp -\dim_new:N \g_@@_exspace_dim +\@@_after_preamble:n + { \xeCJK_cs_add:Nnn \verbatim@font { } { \xeCJKVerbAddon } } % \end{macrocode} -% \end{macro} % -% \begin{macro}{\setCJKmonoscale} +% \begin{macro}[internal]{\@@_set_verb_exspace:} +% 在抄录环境中,CJK 文字之间的间距为当前西文字体两个空格的宽度与当前字体大小之差, +% 而与西文和空格的间距为 CJK 文字之间的间距的一半。这里的问题是, +% \cs{g_@@_verb_exspace_skip} 有可能为负么?现在的处理是保证它非负。如果真的出现 +% 负间距的情况,也可以像下面对后备可视空格符号一样,在 \cs{xeCJK_select_font:} 里 +% 对 CJK 文字的字体大小做调整,并让间距为零。 % \begin{macrocode} -\NewDocumentCommand \setCJKmonoscale { } - { - \CJKflexiblespacing - \xeCJK_set_monoscale: - \addCJKfontfeatures { Scale = \fp_use:N \g_@@_monoscale_fp } - } -\cs_new_protected_nopar:Npn \xeCJK_set_monoscale: +\cs_new_protected_nopar:Npn \@@_set_verb_exspace: { - \group_begin: - \fontfamily \ttdefault \selectfont - \fp_gset:Nn \g_@@_monoscale_fp - { \dim_to_fp:n { \c_two \tex_fontdimen:D \c_two \tex_font:D } / ( \f@size ) } - \group_end: + \tl_if_exist:cTF { xeCJK/verb/\curr@fontshape/\f@size } + { + \skip_gset:Nn \g_@@_verb_exspace_skip + { \tl_use:c { xeCJK/verb/\curr@fontshape/\f@size } } + } + { + \skip_gset:Nn \g_@@_verb_exspace_skip + { + \dim_max:nn + { \c_zero_dim } + { \c_two \tex_fontdimen:D \c_two \tex_font:D - \f@size pt } + } + \tl_gset:cV { xeCJK/verb/\curr@fontshape/\f@size } \g_@@_verb_exspace_skip + } } +\skip_new:N \g_@@_verb_exspace_skip % \end{macrocode} % \end{macro} % -% \begin{macro}{\setCJKmonoexspace} +% \begin{macro}[internal]{\xeCJK_visible_space_fallback:} +% \changes{v3.1.0}{2012/11/19}{调整 \pkg{fontspec} 的后备可视空格符号,以便于使用 +% 时对齐。} +% \pkg{fontspec} 使用 |lmtt| 字体中的可视空格符号(|U+2423|)作为当前字体中相应符号 +% 的后备。但是 |lmtt| 的字体大小未必与当前字体匹配。因此,我们在这里做一些调整,以 +% 保证使用后备可视空格符号时,也能保证对齐。这里加入 \cs{scan_stop:} 的目的是强制 +% 发生状态转移。这样当空格出现在 CJK 文字后面时,使字体回到西文,以便让 +% \pkg{fontspec} 在当前西文字体而不是在 CJK 字体中检查有没有 |U+2423|。 % \begin{macrocode} -\NewDocumentCommand \setCJKmonoexspace { } { \xeCJK_set_monoexspace: } -\cs_new_protected_nopar:Npn \xeCJK_set_monoexspace: +\cs_new_protected_nopar:Npn \xeCJK_visible_space_fallback: + { { + \cs_if_exist_use:cF { xeCJK/space/\curr@fontshape/\f@size } + { \xeCJK_set_visible_space_font: } + \textvisiblespace + } } +\AtEndOfPackage { - \group_begin: - \fontfamily \ttdefault \selectfont - \dim_gset:Nn \g_@@_exspace_dim - { - \c_two \tex_fontdimen:D \c_two \tex_font:D - - \fp_to_dim:n { \g_@@_monoscale_fp * ( \f@size ) } - } - \group_end: + \xeCJK_cs_add:Nnn \fontspec_visible_space: { \scan_stop: } { } + \cs_gset_eq:NN \fontspec_visible_space_fallback: \xeCJK_visible_space_fallback: } % \end{macrocode} % \end{macro} % -% \begin{macro}{\CJKfixedspacing,\CJKflexiblespacing} +% \begin{macro}[internal]{\xeCJK_set_visible_space_font:} +% 当前字体空格的宽度与后备字体 |lmtt| 不一样时,就对 \cs{textvisiblespace} 的字体尺寸 +% 按相应的比例放缩。 % \begin{macrocode} -\NewDocumentCommand \CJKfixedspacing { } +\cs_new_protected_nopar:Npn \xeCJK_set_visible_space_font: { - \bool_if:NF \l_@@_fixed_spacing_bool + \tl_set:Nx \l_@@_current_coor_tl { xeCJK/space/\curr@fontshape/\f@size } + \dim_set:Nn \l_@@_tmp_dim { \tex_fontdimen:D \c_two \tex_font:D } + \fontencoding { \g_fontspec_encoding_tl } + \fontfamily { lmtt } + \selectfont + \dim_compare:nNnF \l_@@_tmp_dim = { \tex_fontdimen:D \c_two \tex_font:D } { - \bool_set_true:N \l_@@_fixed_spacing_bool - \tl_set_eq:NN \l_@@_flexible_punctstyle_tl \l_xeCJK_punctstyle_tl - \bool_set_eq:NN \l_@@_fixed_xecglue_bool \l_@@_xecglue_bool - \cs_set_eq:NN \@@_flexible_ecglue: \CJKecglue - \cs_set_eq:NN \@@_flexible_cjkglue: \CJKglue - \xeCJK_set_monoexspace: - \xeCJKsetup + \fontsize { - PunctStyle = plain , - CJKglue = { \skip_horizontal:N \g_@@_exspace_dim } , - CJKecglue = { \skip_horizontal:n { .5\g_@@_exspace_dim } } , - xCJKecglue = false , + \dim_eval:n + { + \f@size pt * \dim_ratio:nn + { \l_@@_tmp_dim } { \tex_fontdimen:D \c_two \tex_font:D } + } } + { \f@baselineskip } + \selectfont } + \xeCJK_font_gset_to_current:c { \l_@@_current_coor_tl } } -\NewDocumentCommand \CJKflexiblespacing { } +% \end{macrocode} +% \end{macro} +% +% \subsection{\pkg{xeCJK} 其它选项} +% +% \begin{macro}{LocalConfig} +% \changes{v3.1.0}{2012/11/20}{增加 \texttt{LocalConfig} 选项用于载入本地配置文件。} +% 声明载入本地配置文件的选项。 +% \begin{macrocode} +\keys_define:nn { xeCJK / options } { - \bool_if:NT \l_@@_fixed_spacing_bool + LocalConfig .choice: , + LocalConfig / false .code:n = + { \bool_gset_false:N \g_@@_config_bool } , + LocalConfig / true .code:n = { - \bool_set_false:N \l_@@_fixed_spacing_bool - \exp_args:Nx \xeCJKsetup - { - PunctStyle = { \l_@@_flexible_punctstyle_tl } , - CJKglue = { \exp_not:o { \@@_flexible_cjkglue: } } , - CJKecglue = { \exp_not:o { \@@_flexible_ecglue: } } , - xCJKecglue = { \bool_if:NTF \l_@@_fixed_xecglue_bool { true } { false } } , - } - } + \bool_gset_true:N \g_@@_config_bool + \tl_gset:Nn \g_@@_config_name_tl { xeCJK } + } , + LocalConfig / unknown .code:n = + { + \bool_gset_true:N \g_@@_config_bool + \tl_gset:Nx \g_@@_config_name_tl { xeCJK - \l_keys_value_tl } + } , + LocalConfig .default:n = { true } } -\bool_new:N \l_@@_fixed_spacing_bool -\@@_AfterPreamble:n { \tl_put_right:Nn \verbatim@font \CJKfixedspacing } +\tl_new:N \g_@@_config_name_tl +\bool_new:N \g_@@_config_bool % \end{macrocode} % \end{macro} % -% \begin{macro}{\setCJKmonofont} -% 设置文档的 CJK 等宽字体族。 +% \begin{macro}{CJKnumber,indentfirst} +% 是否启用 \pkg{CJKnumb} 宏包和首行是否缩进。 % \begin{macrocode} -\NewDocumentCommand \setCJKmonofont { s t+ O{} m } +\keys_define:nn { xeCJK / options } { - \IfBooleanTF {#1} - { \xeCJK_set_family:xnn \CJKttdefault { Mono = Scale, #3 } {#4} } - { - \IfBooleanTF {#2} - { \xeCJK_set_family:xnn \CJKttdefault { Mono = Exspace, #3 } {#4} } - { \xeCJK_set_family:xnn \CJKttdefault {#3} {#4} } - } + CJKnumber .bool_gset:N = \g_@@_number_bool , + indentfirst .bool_gset:N = \g_@@_indent_bool , + normalindentfirst .meta:n = { indentfirst = false } } % \end{macrocode} % \end{macro} % -% \subsection{\pkg{xeCJK} 其它选项} -% -% \begin{macro}{CJKnumber,indentfirst} -% 是否启用 \pkg{CJKnumber} 宏包和首行是否缩进,其中 |CJKnumber| 选项仅 -% 在 \pkg{xeCJK} 宏包调用的时候有效。并将 \pkg{xeCJK} 中未知的选项传递给 -% \pkg{fontspec} 宏包。 +% \begin{macro}{quiet,silent} +% 将调用 \pkg{xeCJK} 时使用的未知的选项传递给 \pkg{fontspec} 宏包。 +% 对 \pkg{fontspec} 的 |quiet| 和 |silent| 选项进行修改,使其适用于 \pkg{xeCJK}。 % \begin{macrocode} -\bool_new:N \g_@@_indent_bool \keys_define:nn { xeCJK / options } { - CJKnumber .bool_set:N = \g_@@_number_bool , - indentfirst .bool_set:N = \g_@@_indent_bool , - normalindentfirst .meta:n = { indentfirst = false } , quiet .code:n = { \msg_redirect_module:nnn { xeCJK } { warning } { info } \msg_redirect_module:nnn { xeCJK } { info } { none } \xeCJK_if_package_loaded:nF { fontspec } { \PassOptionsToPackage { quiet } { fontspec } } - }, + } , silent .code:n = { \msg_redirect_module:nnn { xeCJK } { warning } { none } \msg_redirect_module:nnn { xeCJK } { info } { none } \xeCJK_if_package_loaded:nF { fontspec } { \PassOptionsToPackage { silent } { fontspec } } - }, + } , unknown .code:n = { \xeCJK_if_package_loaded:nTF { fontspec } { \@@_error:nx { key-unknown } { \l_keys_key_tl } } { \PassOptionsToPackage { \l_keys_key_tl } { fontspec } } - }, + } } \@@_msg_new:nn { key-unknown } { @@ -4095,54 +4760,83 @@ $URL: https://ctex-kit.googlecode.com/svn/trunk/xeCJK/xeCJK.dtx $ % % \subsection{\pkg{xeCJK} 初始化设置} % +% \begin{macro}[internal]{\CJKsymbol, \CJKpunctsymbol} +% \begin{macrocode} +\cs_new_nopar:Npn \CJKsymbol #1 {#1} +\cs_new_nopar:Npn \CJKpunctsymbol #1 {#1} +% \end{macrocode} +% \end{macro} +% % \pkg{xeCJK} 宏包的初始化设置。 +% % \begin{macrocode} \keys_set:nn { xeCJK / options } { - CJKglue = { \skip_horizontal:n { \c_zero_skip \@plus .08\baselineskip } } , + CJKglue = { \skip_horizontal:n { \c_zero_dim plus 0.08 \tex_baselineskip:D } } , CJKecglue = \c_space_token , xCJKecglue = false , CheckSingle = false , CJKspace = false , CJKmath = false , + CJKnumber = false , xeCJKactive = true , + LocalConfig = true , indentfirst = true , - EmboldenFactor = 4 , - SlantFactor = .167 , + EmboldenFactor = 4 , + SlantFactor = 0.167 , PunctStyle = quanjiao , KaiMingPunct = { ^^^^3002 ^^^^ff0e ^^^^ff1f ^^^^ff01 } , LongPunct = { ^^^^2014 ^^^^2015 ^^^^2500 ^^^^2025 ^^^^2026 } , MiddlePunct = { ^^^^2014 ^^^^2015 ^^^^2500 ^^^^00b7 ^^^^30fb ^^^^ff65 } , - AllowBreakBetweenPuncts = false , + AllowBreakBetweenPuncts = false } +\defaultCJKfontfeatures { Script = CJK } % \end{macrocode} % -% \begin{macro}[internal]{\CJKsymbol, \CJKpunctsymbol} -% \begin{macrocode} -\cs_new_nopar:Npn \CJKsymbol #1 {#1} -\cs_new_nopar:Npn \CJKpunctsymbol #1 {#1} -% \end{macrocode} -% \end{macro} -% % 执行宏包选项,并载入 \pkg{fontspec} 宏包。 % \begin{macrocode} \ProcessKeysOptions { xeCJK / options } \RequirePackage { fontspec } [ 2011/09/13 ] % \end{macrocode} % -% \begin{macro}[internal]{\c_@@_encoding_tl} +% \begin{macro}[internal,var]{\c_@@_encoding_tl} +% 保存 \pkg{fontspec} 声明字体时使用的字体编码。 % \begin{macrocode} \tl_const:Nx \c_@@_encoding_tl { \g_fontspec_encoding_tl } % \end{macrocode} % \end{macro} % +% 章节标题后面的首个段落的首行是否缩进。 +% \changes{v3.1.0}{2012/11/21}{改用 \pkg{indentfirst} 宏包处理缩进的问题。} % \begin{macrocode} -\bool_if:NT \g_@@_indent_bool +\bool_if:NT \g_@@_indent_bool { \RequirePackage { indentfirst } } +% \end{macrocode} +% +% 对不能通过 \cs{xeCJKsetup} 设置的选项给出警告。 +% \begin{macrocode} +\keys_define:nn { xeCJK / options } { - \cs_set_eq:NN \@afterindentfalse \@afterindenttrue - \@afterindenttrue + LocalConfig .code:n = { \@@_warning:nx { option-invalid } { \l_keys_key_tl } } , + CJKnumber .code:n = { \@@_warning:nx { option-invalid } { \l_keys_key_tl } } , + indentfirst .code:n = { \@@_warning:nx { option-invalid } { \l_keys_key_tl } } } +\@@_msg_new:nn { option-invalid } + { + The~`#1'~option~only~can~be~set~in~the~optional~argument~to~the\\ + \token_to_str:N \usepackage \ command~when~xeCJK~is~being~loaded.\\\\ + Please~do~not~set~it~via~the~\token_to_str:N \xeCJKsetup \ command. + } +% \end{macrocode} +% +% \begin{macro}[var]{\CJKrmdefault,\CJKsfdefault,\CJKttdefault,\CJKfamilydefault} +% \begin{macrocode} +\tl_if_exist:NF \CJKrmdefault { \tl_gset:Nn \CJKrmdefault { rm } } +\tl_if_exist:NF \CJKsfdefault { \tl_gset:Nn \CJKsfdefault { sf } } +\tl_if_exist:NF \CJKttdefault { \tl_gset:Nn \CJKttdefault { tt } } +\tl_if_exist:NF \CJKfamilydefault { \tl_gset:Nn \CJKfamilydefault { \CJKrmdefault } } +\tl_new:c { \@@_family_csname:n { \CJKfamilydefault } } % \end{macrocode} +% \end{macro} % % \begin{macro}{\xeCJKsetup} % 在导言区或文档中设置 \pkg{xeCJK} 的接口。 @@ -4167,7 +4861,7 @@ $URL: https://ctex-kit.googlecode.com/svn/trunk/xeCJK/xeCJK.dtx $ % \begin{macro}[internal]{\punctstyle, \xeCJKplainchr} % \begin{macrocode} \NewDocumentCommand \punctstyle { m } { \xeCJKsetup { PunctStyle = {#1} } } -\NewDocumentCommand \xeCJKplainchr { } { \punctstyle { plain } } +\NewDocumentCommand \xeCJKplainchr { } { \xeCJKsetup { PunctStyle = plain } } % \end{macrocode} % \end{macro} % @@ -4178,47 +4872,120 @@ $URL: https://ctex-kit.googlecode.com/svn/trunk/xeCJK/xeCJK.dtx $ % \end{macrocode} % \end{macro} % +% \begin{macro}[internal]{\CJKspace,\CJKnospace} +% \begin{macrocode} +\NewDocumentCommand \CJKspace { } { \xeCJKsetup { CJKspace = true } } +\NewDocumentCommand \CJKnospace { } { \xeCJKsetup { CJKspace = false } } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\xeCJKallowbreakbetweenpuncts, \xeCJKnobreakbetweenpuncts} +% \begin{macrocode} +\NewDocumentCommand \xeCJKallowbreakbetweenpuncts { } + { \xeCJKsetup { AllowBreakBetweenPuncts = true } } +\NewDocumentCommand \xeCJKnobreakbetweenpuncts { } + { \xeCJKsetup { AllowBreakBetweenPuncts = false } } +% \end{macrocode} +% \end{macro} +% % \subsection{兼容性修补} % -% \begin{macro}[internal]{\@@_fix_itcorr:} -% 修复倾斜校正。 +% 补丁 \cs{normalfont},\cs{rmfamily},\cs{sffamily} 和 \cs{ttfamily},使其同时对 +% CJK 字体族有效。 +% \begin{macrocode} +\xeCJK_cs_add:Nnn \rmfamily { \CJKfamily { \CJKrmdefault } } { } +\xeCJK_cs_add:Nnn \sffamily { \CJKfamily { \CJKsfdefault } } { } +\xeCJK_cs_add:Nnn \ttfamily { \CJKfamily { \CJKttdefault } } { } +\xeCJK_cs_add:Nnn \normalfont { \CJKfamily { \CJKfamilydefault } } { } +\cs_set_eq:NN \reset@font \normalfont +% \end{macrocode} +% +% 因为我们在上面把 \cs{CJKfamily} 加在了 \cs{rmfamily} 里面,而 \pkg{fontspec} 在 +% 调用字体时,某些选项要使用它。为减少影响,下面使 \cs{CJKfamily} 在通过 +% \pkg{fontspec} 来实际调用字体时无效。 % \begin{macrocode} -\cs_new_protected_nopar:Npn \@@_fix_itcorr: - { - \scan_stop: - \xeCJK_if_last_node:nTF { default } - { - \tex_unkern:D \tex_unkern:D - \@@_itcorr_aux - { \xeCJK_make_node:n { default_itcorr } } - } - { \@@_itcorr_aux } - } -\cs_new_eq:NN \@@_itcorr_aux \/ -\cs_set_protected_nopar:Npn \/ - { - \int_compare:nNnTF \XeTeXinterchartokenstate > \c_zero - { \@@_fix_itcorr: } { \@@_itcorr_aux } - } +\xeCJK_cs_add:Nnn \fontspec_init: { \@@_gobble_CJKfamily: } { } % \end{macrocode} % +% \newbox\xeCJKtmpbox +% \setbox\xeCJKtmpbox\vbox\bgroup % \begin{macrocode} %<@@=> -% \end{macrocode} +% \end{macrocode}\egroup % +% \begin{macro}[internal]{\xeCJK@fix@penalty} +% \changes{v3.1.0}{2012/11/13}{采用通过不修改原语 \cs{/} 的方式对修复倾斜校正。} +% 对 \LaTeXe 内核中的 \cs{fix@penalty} 被用于诸如 \cs{textit} 之类的文档 +% 字体转换命令的定义之中。这里对它进行补丁的目的是修复其中的倾斜校正,并使得这些 +% 文档命令与紧随其后的汉字之间可以正确的插入 \cs{CJKecglue} 或者忽略其中的空格。 +% 例如 \verb*|这是 \emph{强调} 文本|,第二个空格可以被忽略掉。如果使用 |xCJKecglue| +% 选项,第一个空格也可以被省略。事实上,在 \cs{sw@slant} 的定义中,\cs{@@italiccorr} +% 前面的 \cs{lastskip} 和 \cs{lastpenalty} 有四种情况,这里只对它们都为零的情况进行 +% 处理。 % \begin{macrocode} -\cs_set_eq:NN \@@italiccorr \/ +\cs_new_eq:NN \xeCJK@fix@penalty \fix@penalty +\xeCJK_cs_patch:Nnn \xeCJK@fix@penalty \@@italiccorr \xeCJK@patch@italiccorr +\xeCJK_cs_patch:Nnn \sw@slant \fix@penalty \xeCJK@fix@penalty % \end{macrocode} +% \end{macro} % +% \begin{macro}[internal]{\xeCJK@patch@italiccorr} +% 修复倾斜校正,并处理汉字后面的空格。 % \begin{macrocode} -%<@@=xeCJK> +\cs_new_protected_nopar:Npn \xeCJK@patch@italiccorr + { + \int_compare:nNnTF \XeTeXinterchartokenstate > \c_zero + { + \xeCJK_if_last_node:nTF { default } + { + \tex_unkern:D \tex_unkern:D \@@italiccorr + { \xeCJK_make_node:n { default } } + } + { + \xeCJK_if_last_node:nTF { CJK } + { + \tex_unkern:D \tex_unkern:D \@@italiccorr + { \xeCJK_make_node:n { CJK } } \use:n + } + { + \xeCJK_if_last_node:nTF { CJK-space } + { + \tex_unkern:D \tex_unkern:D \@@italiccorr + { \xeCJK_make_node:n { CJK-space } } \use:n + } + { \@@italiccorr \use_none:n } + } +% \end{macrocode} +% \cs{xeCJK_ignore_spaces:w} 里面用到 |peek| 函数来判断后面是不是空格,而此时它 +% 后面还有 $4$ 个 \cs{fi} 或者 |\else...\fi| 没有被展开,将影响 |peek| 函数的 +% 判断。因此我们需要用 $2^4-1=15$ 个 \cs{exp_after:wN} 来展开它们。 +% 显然,这里用 \cs{exp_last_unbraced:Nf} 会比较方便,但是它会吃掉 +% \verb*|\textit{...} | 等后面原来存在的空格作为完全展开的结束。要正确使用它还 +% 需要另外的处理(使用 \cs{exp_stop_f:})。 +% \begin{macrocode} + { + \exp_after:wN \exp_after:wN \exp_after:wN + \exp_after:wN \exp_after:wN \exp_after:wN \exp_after:wN + \exp_after:wN \exp_after:wN \exp_after:wN \exp_after:wN + \exp_after:wN \exp_after:wN \exp_after:wN \exp_after:wN + \xeCJK_ignore_spaces:w + } + } + } + { \@@italiccorr } + } % \end{macrocode} % \end{macro} % +% \setbox\xeCJKtmpbox\vbox\bgroup +% \begin{macrocode} +%<@@=xeCJK> +% \end{macrocode}\egroup +% % \begin{macro}[internal]{\@@_set_others_toks:n,\c_@@_Others_class_int} % 简单处理与同样使用 \cs{XeTeXinterchartoks} 机制的宏包的兼容问题。 -% \begin{macrocode} -\@@_AfterEndPreamble:n +% \begin{macrocode} +\@@_after_end_preamble:n { \int_compare:nNnF { \c_three + ( \seq_count:N \g_@@_class_seq ) } = \xe@alloc@intercharclass @@ -4233,44 +5000,36 @@ $URL: https://ctex-kit.googlecode.com/svn/trunk/xeCJK/xeCJK.dtx $ \cs_new_protected_nopar:Npn \@@_set_others_toks:n #1 { \int_set:Nn \c_@@_Others_class_int {#1} - \clist_map_inline:Nn \g_@@_CJK_class_clist + \seq_map_inline:Nn \g_@@_CJK_class_seq { - \@@_copy_inter_class_toks:nnnn {##1} { Others } {##1} { NormalSpace } - \@@_copy_inter_class_toks:nnnn { Others } {##1} { NormalSpace } {##1} - \exp_args:Nnnx \@@_app_inter_class_toks:nnn {##1} { Others } - { \@@_get_inter_class_toks:nn { Default } { Others } } - \exp_args:Nnnx \@@_pre_inter_class_toks:nnn { Others } {##1} - { \@@_get_inter_class_toks:nn { Others } { Default } } + \xeCJK_copy_inter_class_toks:nnnn {##1} { Others } {##1} { NormalSpace } + \xeCJK_copy_inter_class_toks:nnnn { Others } {##1} { NormalSpace } {##1} + \xeCJK_app_inter_class_toks:nnx {##1} { Others } + { \xeCJK_get_inter_class_toks:nn { Default } { Others } } + \xeCJK_pre_inter_class_toks:nnx { Others } {##1} + { \xeCJK_get_inter_class_toks:nn { Others } { Default } } \xeCJK_if_blank_x:nT - { \@@_get_inter_class_toks:nn { Others } { Boundary } } + { \xeCJK_get_inter_class_toks:nn { Others } { Boundary } } { - \@@_copy_inter_class_toks:nnnn + \xeCJK_copy_inter_class_toks:nnnn { Others } { Boundary } { Default } { Boundary } } \xeCJK_if_blank_x:nT - { \@@_get_inter_class_toks:nn { Boundary } { Others } } + { \xeCJK_get_inter_class_toks:nn { Boundary } { Others } } { - \@@_copy_inter_class_toks:nnnn + \xeCJK_copy_inter_class_toks:nnnn { Boundary } { Others } { Boundary } { Default } } } } -\int_new:N \c_@@_Others_class_int -% \end{macrocode} -% \end{macro} -% -% \begin{macro}[internal]{\@@_patch:Nnn} -% 给已有宏内容前后附加补丁。 -% \begin{macrocode} -\cs_new_protected_nopar:Npn \@@_patch:Nnn #1#2#3 - { \tl_put_left:Nn #1 {#2} \tl_put_right:Nn #1 {#3} } +\cs_new_eq:NN \c_@@_Others_class_int \l_@@_tmpa_int % \end{macrocode} % \end{macro} % % 单独处理宽度有分歧的几个标点:包括省略号、破折号、间隔号、引号等中西文混用的 % 符号, 保证其命令形式输出的是西文字体。并对一些编码的符号宏包做特殊处理。 % \begin{macrocode} -\@@_AfterPreamble:n +\@@_after_preamble:n { \tl_map_inline:nn { @@ -4278,18 +5037,14 @@ $URL: https://ctex-kit.googlecode.com/svn/trunk/xeCJK/xeCJK.dtx $ \textquoteleft \textquoteright \textquotedblleft \textquotedblright } { - \@@_patch:Nnn #1 - { \@@_group_begin: \makexeCJKinactive } - { \@@_group_end: } + \xeCJK_cs_add:Nnn #1 + { \@@_group_begin: \makexeCJKinactive } { \@@_group_end: } } - \@@_patch:Nnn \tipaencoding { \makexeCJKinactive } { } - \cs_set_eq:NN \@@_aux_r \r - \cs_set_protected_nopar:Npn \r #1 { { \makexeCJKinactive \@@_aux_r {#1} } } + \xeCJK_cs_add:Nnn \tipaencoding { \makexeCJKinactive } { } + \cs_new_eq:NN \@@_aux_r:n \r + \cs_set_nopar:Npn \r #1 { { \makexeCJKinactive \@@_aux_r:n {#1} } } \xeCJK_if_package_loaded:nT { pifont } - { - \RenewDocumentCommand \Pifont { m } - { \makexeCJKinactive \usefont {U} {#1} {m} {n} } - } + { \xeCJK_cs_add:Nnn \Pifont { \makexeCJKinactive } { } } } \cs_new_eq:NN \@@_group_begin: \group_begin: \cs_new_eq:NN \@@_group_end: \group_end: @@ -4297,121 +5052,134 @@ $URL: https://ctex-kit.googlecode.com/svn/trunk/xeCJK/xeCJK.dtx $ % % 简单处理与 \pkg{hyperref} 宏包的兼容问题。 % \begin{macrocode} -\@@_AfterEndPreamble:n +\@@_after_end_preamble:n { - \bool_if:nT - { - \xeCJK_if_package_loaded_p:n { hyperref } && - \tl_if_exist_p:N \pdfstringdefPreHook - } + \xeCJK_if_package_loaded:nT { hyperref } { \tl_gput_right:Nn \pdfstringdefPreHook { - \cs_set_eq:NN \makexeCJKinactive \prg_do_nothing: - \cs_set_eq:NN \@@_group_begin: \prg_do_nothing: - \cs_set_eq:NN \@@_group_end: \prg_do_nothing: - \cs_set_eq:NN \CJKfamily \use_none:n + \@@_gobble_CJKfamily: + \xeCJK_cs_clear:N \makexeCJKinactive + \xeCJK_cs_clear:N \@@_group_begin: + \xeCJK_cs_clear:N \@@_group_end: } } } % \end{macrocode} % -% 禁止在 \pkg{xeCJK} 宏包后再载入 \pkg{CJK} 宏包。 +% \changes{v3.1.0}{2012/11/13}{取消 \cs{cprotect} 的外部宏限制。} +% 当探测到 \pkg{cprotect} 宏包被引入时,则取消 \cs{cprotect} 宏的 \cs{outer} 定义。 % \begin{macrocode} -\tl_set:cn { ver@CJK.sty } { 2100/01/01 } +\@@_after_end_preamble:n + { + \bool_if:nT + { \xeCJK_if_package_loaded_p:n { cprotect } && \cs_if_exist_p:N \icprotect } + { \exp_after:wN \tex_let:D \cs:w cprotect \cs_end: \icprotect } + } +% \end{macrocode} +% +% 禁止在 \pkg{xeCJK} 宏包后再载入 \pkg{CJK} 宏包,并使得 +% \pkg{CJKnumb} 和 \pkg{CJKfntef} 宏包可以使用。 +% \begin{macrocode} +\tl_set:cn { ver@CJK.sty } { 9999/99/99 } +\tl_set_eq:cc { ver@CJKpunct.sty } { ver@CJK.sty } % \end{macrocode} % % \begin{macro}[internal]{\xeCJKcaption} % 可以使用 \pkg{CJK} 宏包中的 |.cpx| 文件。 % \begin{macrocode} -\cs_if_free:NT \CJK@ifundefined +\cs_if_exist:NF \CJK@ifundefined { \cs_set_eq:NN \CJK@ifundefined \cs_if_free:NTF } \NewDocumentCommand \xeCJKcaption { o m } { \IfNoValueF {#1} { \XeTeXdefaultencoding "#1" } - \cs_set_nopar:Npx \@@_reset_at_catcode: + \use:x { - \exp_not:n { \char_set_catcode:nn { `\@ } } - { \char_value_catcode:n { `\@ } } + \char_set_catcode_letter:n { 64 } + \file_input:n { #2.cpx } + \char_set_catcode:nn { 64 } { \char_value_catcode:n { 64 } } } - \char_set_catcode_letter:N \@ - \file_input:n { #2.cpx } - \@@_reset_at_catcode: \XeTeXdefaultencoding "UTF-8" } % \end{macrocode} % \end{macro} % -% \begin{macro}[internal] -% {\xeCJK_ULprepunctchar:n, \xeCJK_ULpostpunctchar:n, \xeCJK_ULroutines:} +% \begin{macro}[internal]{\xeCJK_hook_for_ulem:} +% \changes{v3.1.0}{2012/11/16}{简化对 \pkg{ulem} 宏包的兼容补丁。} +% 对 \pkg{ulem} 宏包打补丁,以支持 \pkg{CJKfntef} 宏包。目前的问题是,在下划线状态 +% 下,相邻两个标点之间的空白不能压缩。 % \begin{macrocode} -\cs_new_protected_nopar:Npn \xeCJK_ULprepunctchar:n #1 - { - { \makexeCJKinactive \CJKpunctsymbol {#1} \xeCJK_no_break: } - \tex_ignorespaces:D - } -\cs_new_protected_nopar:Npn \xeCJK_ULpostpunctchar:n #1 +\cs_new_protected_nopar:Npn \xeCJK_hook_for_ulem: { - { \makexeCJKinactive \CJKpunctsymbol {#1} } - \xeCJK_ignorespaces: + \bool_if:NF \l_@@_ulem_hook_used_bool + { + \bool_set_true:N \l_@@_ulem_hook_used_bool + \xeCJK_cs_clear:N \@@_CJK_FullLeft_glue: + \cs_set_protected_nopar:Npn \@@_FullLeft_ulem_hook: { { \CJKglue } } + \xeCJK_swap_cs:NN \CJKsymbol \@@_ulem_CJKsymbol:N + \xeCJK_swap_cs:NN \CJKpunctsymbol \@@_ulem_CJKpunctsymbol:N + } } -\cs_new_protected_nopar:Npn \xeCJK_ULroutines: +\bool_new:N \l_@@_ulem_hook_used_bool +\@@_after_preamble:n { - \@@_inter_class_toks:nnn { Default } { CJK } { \CJKecglue \CJKsymbol } - \@@_inter_class_toks:nnn { HalfLeft } { CJK } { \CJKsymbol } - \@@_inter_class_toks:nnn { HalfRight } { CJK } { \CJKecglue \CJKsymbol } - \@@_inter_class_toks:nnn { Boundary } { CJK } { \xeCJK_Boundary_and_CJK: } - \clist_map_inline:nn { Default, HalfLeft, HalfRight, Boundary } + \xeCJK_if_package_loaded:nT { ulem } { - \@@_inter_class_toks:nnn {##1} { FullLeft } { \xeCJK_ULprepunctchar:n } - \@@_inter_class_toks:nnn {##1} { FullRight } { \xeCJK_ULpostpunctchar:n } + \xeCJK_cs_gclear:N \@@_FullLeft_ulem_hook: + \xeCJK_pre_inter_class_toks:nnn { Boundary } { FullLeft } + { \@@_FullLeft_ulem_hook: } + \cs_if_exist:NTF \XeTeX@CJKfntef@hook + { + \xeCJK_cs_gclear:N \CJKf@global + \AtBeginEnvironment + { CJKfilltwosides } { \cs_set_eq:NN \CJKglue \tex_hfil:D } + \cs_set_protected_nopar:Npn \XeTeX@CJKfntef@hook + { \xeCJK_select_font: \makexeCJKinactive } + } + { \RequirePackage { CJKulem } } + \addto@hook \UL@hook { \xeCJK_hook_for_ulem: } } - \@@_UL_subclass_patch_tl } % \end{macrocode} % \end{macro} % -% 对 \pkg{ulem} 宏包打补丁,以支持 \pkg{CJKfntef} 宏包。 -% \begin{macrocode} -\@@_AfterPreamble:n +% \begin{macro}[internal]{\@@_ulem_CJKsymbol:N,\@@_ulem_CJKpunctsymbol:N} +% 这两个宏定义里面的分组记号都是必须的,否则会出现分组不匹配的情况。 +% \begin{macrocode} +\cs_new_protected_nopar:Npn \@@_ulem_CJKsymbol:N #1 { - \cs_if_exist:NT \UL@hook - { - \addto@hook \UL@hook - { - \cs_set_eq:NN \@@_UL_CJKsymbol \CJKsymbol - \cs_set_eq:NN \@@_UL_CJKpunctsymbol \CJKpunctsymbol - \cs_set_protected_nopar:Npn \CJKsymbol #1 - { - { \xeCJK_select_font: \@@_UL_CJKsymbol {#1} } - { \xeCJK_make_node:n { CJK } } \xeCJK_ignorespaces: - } - \cs_set_protected_nopar:Npn \CJKpunctsymbol #1 - { { \xeCJK_select_font: \@@_UL_CJKpunctsymbol {#1} } } - \xeCJK_ULroutines: - } - } - \cs_if_exist:NT \XeTeX@CJKfntef@hook - { - \cs_set_nopar:Npn \XeTeX@CJKfntef@hook - { \xeCJK_select_font: \makexeCJKinactive } - } + { \@@_ulem_CJKsymbol:N {#1} } + { \xeCJK_make_node:n { CJK } } \xeCJK_ignore_spaces:w } +\cs_new_protected_nopar:Npn \@@_ulem_CJKpunctsymbol:N #1 + { { \@@_ulem_CJKpunctsymbol:N {#1} } \tex_ignorespaces:D } % \end{macrocode} +% \end{macro} % -% 使用 \pkg{CJKnumb} 宏包。 +% 为使用 \pkg{CJKnumb} 宏包而作一些处理。另外 \pkg{CJKnumb} 使用的是传统汉字“萬” +% 和“億”,我们在这里把它们修正为简体字。 % \begin{macrocode} \bool_if:NT \g_@@_number_bool { \tl_set:Nn \CJK@UnicodeEnc { UTF8 } - \cs_set_protected_nopar:Npn \CJKaddEncHook #1#2 - { \cs_set_nopar:cpn { @@_enc_#1 } {#2} } + \cs_set_protected:Npn \CJKaddEncHook #1#2 + { \cs_set:cpn { @@_enc_#1_hook: } {#2} } \cs_set_protected_nopar:Npn \Unicode #1#2 - { \tex_char:D \int_eval:n { (#1) * \c_two_hundred_fifty_six + (#2) } } + { \tex_char:D \etex_numexpr:D (#1) * \c_two_hundred_fifty_six + (#2) \scan_stop: } \RequirePackage { CJKnumb } - \cs_if_exist_use:cT { @@_enc_\CJK@UnicodeEnc } { } - \tl_set:Nx \CJK@tenthousand { ^^^^4e07 } - \tl_set:Nx \CJK@hundredmillion { ^^^^4ebf } + \cs_if_exist_use:c { @@_enc_ \CJK@UnicodeEnc _hook: } + \tl_set:Nn \CJK@tenthousand { \Unicode { 78 } { 7 } } + \tl_set:Nn \CJK@hundredmillion { \Unicode { 78 } { 191 } } + } +% \end{macrocode} +% +% 最后引入本地配置文件。 +% \begin{macrocode} +\bool_if:NT \g_@@_config_bool + { + \tl_const:Nn \c_@@_config_ext_tl { cfg } + \@onefilewithoptions + { \g_@@_config_name_tl } [ ] [ ] { \c_@@_config_ext_tl } } % \end{macrocode} % @@ -4419,6 +5187,24 @@ $URL: https://ctex-kit.googlecode.com/svn/trunk/xeCJK/xeCJK.dtx $ %</package> % \end{macrocode} % +% \subsection{\pkg{xeCJK.cfg}} +% +% \begin{macrocode} +%<*config> +% \end{macrocode} +% +% 预设的配置文件 \file{xeCJK.cfg} 为一个空文件。可以在里面增加设置,然后保存到 +% 本地目录下面。 +% \begin{macrocode} + +% \end{macrocode} +% +% \begin{macrocode} +%</config> +% \end{macrocode} +% +% \iffalse +% % \makeatletter % \let\special@index\@gobble % \makeatother @@ -4431,7 +5217,7 @@ $URL: https://ctex-kit.googlecode.com/svn/trunk/xeCJK/xeCJK.dtx $ %<*ex-autofake> % \end{macrocode} % -% \begin{macrocode} +% \begin{macrocode} \documentclass{article} \usepackage[AutoFakeBold,AutoFakeSlant]{xeCJK} \setCJKmainfont[BoldFont=simhei.ttf, ItalicFont=simkai.ttf]{simsun.ttc} @@ -4492,7 +5278,7 @@ $URL: https://ctex-kit.googlecode.com/svn/trunk/xeCJK/xeCJK.dtx $ %<*ex-fallback> % \end{macrocode} % -% \begin{macrocode} +% \begin{macrocode} \documentclass{article} \usepackage[AutoFallBack]{xeCJK} \usepackage{CJKfntef} @@ -4544,7 +5330,7 @@ $URL: https://ctex-kit.googlecode.com/svn/trunk/xeCJK/xeCJK.dtx $ %<*ex-block> % \end{macrocode} % -% \begin{macrocode} +% \begin{macrocode} \documentclass{article} \usepackage{xeCJK} \usepackage{array} @@ -4606,7 +5392,6 @@ CJK統合漢字(シージェーケーとうごうかんじ、CJK Unified Ideog %</ex-block> % \end{macrocode} % -% \CJKfixedspacing % % \subsection{\pkg{xeCJK-example-CJKecglue.tex}} % @@ -4674,9 +5459,163 @@ x^2+y^2 %</ex-single> % \end{macrocode} % +% \subsection{\pkg{xeCJK-example-CJKfntef.tex}} +% +% \begin{macrocode} +%<*ex-fntef> +% \end{macrocode} +% +% \begin{macrocode} +\documentclass{article} +\usepackage{xeCJK} +\usepackage{xcolor} +\usepackage{CJKfntef} +\setCJKmainfont{SimSun} + +\begin{document} + +\CJKunderline{汉字}\CJKunderline{加下划线加下划线加下划线加下划线 +加下划线加下划线加下划线加下划线加下划线加下划线加下划线} + +\CJKunderwave{波浪线} + +\CJKunderanyline{0.5em}{\sixly \kern-.021em\char58 \kern-.021em}{自定义下划线} + +\CJKunderanyline{0.2em}{\kern-.03em\vtop{\kern.2ex\hrule width.2em\kern 0.11em + \hrule height 0.1em}\kern-.03em}{自定义下划线} + +\CJKunderanysymbol{0.5em}{$\cdot$}{汉字加点} + +\end{document} +% \end{macrocode} +% +% \begin{macrocode} +%</ex-fntef> +% \end{macrocode} +% +% \subsection{\pkg{xeCJK-example-punctstyle.tex}} +% +% \begin{macrocode} +%<*ex-punctstyle> +% \end{macrocode} +% +% \begin{macrocode} +\documentclass{article} +\usepackage{xeCJK} +\setCJKmainfont{SimSun} +\xeCJKDeclarePunctStyle { mine } + { + fixed-punct-ratio = 0 , + fixed-margin-width = 0 pt , + mixed-margin-width = \maxdimen , + mixed-margin-ratio = 0.5 , + middle-margin-width = \maxdimen , + middle-margin-ratio = 0.5 , + add-min-bound-to-margin = true , + min-bound-to-kerning = true , + kerning-margin-minimum = 0.1 em + } + +\begin{document} +\setlength\parindent{2em} +\newcommand\showexample[1]{% + \texttt{------ #1 ------}\par\xeCJKsetup{PunctStyle=#1}\showtexts\par} + +\newcommand\showtexts{% +列位看官:你道此书从何而来?说起根由,虽近荒唐,细按则深有趣味。待在下将此来历注明,方使阅者了然不惑。 + +原来女娲氏炼石补天之时,于大荒山无稽崖炼成高经十二丈、方经二十四丈顽石三万六千五百零一块。娲皇氏只用了三万六千五百块,只单单剩了一块未用,便弃在此山青埂峰下。谁知此石自经煆炼之后,灵性已通,因见众石俱得补天,独自己无材不堪入选,遂自怨自叹,日夜悲号惭愧。 + +一日,正当嗟悼之际,俄见一僧一道远远而来,生得骨格不凡,丰神迥别,说说笑笑,来至峰下,坐于石边,高谈快论:先是说些云山雾海、神仙玄幻之事,后便说到红尘中荣华富贵。此石听了,不觉打动凡心,也想要到人间去享一享这荣华富贵,但自恨粗蠢,不得已,便口吐人言,向那僧道说道:“大师,弟子蠢物,不能见礼了!适闻二位谈那人世间荣耀繁华,心切慕之。弟子质虽粗蠢,性却稍通,况见二师仙形道体,定非凡品,必有补天济世之材,利物济人之德。如蒙发一点慈心,携带弟子得入红尘,在那富贵场中,温柔乡里受享几年,自当永佩洪恩,万劫不忘也!”二仙师听毕,齐憨笑道:“善哉,善哉!那红尘中有却有些乐事,但不能永远依恃;况又有‘美中不足,好事多磨’八个字紧相连属,瞬息间则又乐极悲生,人非物换,究竟是到头一梦,万境归空,倒不如不去的好。”这石凡心已炽,那里听得进这话去,乃复苦求再四。二仙知不可强制,乃叹道:“此亦静极思动,无中生有之数也!既如此,我们便携你去受享受享,只是到不得意时,切莫后悔!”石道:“自然,自然。”那僧又道:“若说你性灵,却又如此质蠢,并更无奇贵之处。如此也只好踮脚而已。也罢!我如今大施佛法,助你助,待劫终之日,复还本质,以了此案。你道好否?”石头听了,感谢不尽。那僧便念咒书符,大展幻术,将一块大石登时变成一块鲜明莹洁的美玉,且又缩成扇坠大小的可佩可拿。那僧托于掌上,笑道:“形体倒也是个宝物了!还只没有实在的好处,须得再镌上数字,使人一见便知是奇物方妙。然后好携你到那昌明隆盛之邦、诗礼簪缨之族、花柳繁华地、温柔富贵乡去安身乐业。”石头听了,喜不能禁,乃问:“不知赐了弟子那哪几件奇处?又不知携了弟子到何地方?望乞明示,使弟子不惑。”那僧笑道:“你且莫问,日后自然明白的。”说着,便袖了这石,同那道人飘然而去,竟不知投奔何方何舍。 + +\hfill +——曹雪芹《红楼梦》} + + +\showexample{mine} +\showexample{quanjiao} +\showexample{banjiao} +\showexample{CCT} +\showexample{kaiming} +\showexample{hangmobanjiao} +\showexample{plain} + +\end{document} +% \end{macrocode} +% +% \begin{macrocode} +%</ex-punctstyle> +% \end{macrocode} +% +% \subsection{\pkg{xeCJK-example-verbatim.tex}} +% +% \begin{macrocode} +%<*ex-verb> +% \end{macrocode} +% +% \begin{macrocode} +\documentclass[a4paper]{article} +\usepackage{xeCJK} +\usepackage{fullpage} +\xeCJKDeclareSubCJKBlock{Hangul} + { "1100 -> "11FF, "3130 -> "318F, "A960 -> "A97F, "AC00 -> "D7AF } +\setCJKmainfont{Adobe Song Std} +\setCJKmainfont[Hangul]{Adobe Myungjo Std} +%%\setmonofont{Inconsolata} +%%\setmonofont{Source Code Pro} +%%\setCJKmonofont{Adobe Kaiti Std} +\setmonofont{TeX Gyre Cursor} +\setCJKmonofont{Adobe Fangsong Std} +\begin{document} + +\begin{verbatim} +************************************************************* +* * +* 精致甲版红楼梦 - 精致工作室特别奉献(2010年9月) * +* * +* GBK简体、GBK繁体、Big5繁体、PDF简体、PDF繁体 * +* * +* 为 GBK、Big5 特别度身订制,并经反复修订,方便纯文本阅读 * +* * +* 精致甲、乙版红楼梦下载专页 * +* http://www.speedy7.com/cn/stguru/gb2312/redmansions.htm * +* http://www.speedy7.com/cn/stguru/big5/redmansions.htm * +* * +* 此电子文件可随意传播、发布、下载。 * +* 传播时建议保留此版本说明供查阅与识别。 * +* 未经修订者同意,不得将此版本用于商业用途。 * +* 如您对红楼梦不具深入了解,请勿随便修改其中的内容。 * +* * +************************************************************* +\end{verbatim} + +\verb|a 汉 字 b| + +\verb*|a 汉 字 b| + +\begin{verbatim} +lang_set = { + ["English"] = lang.en, + ["Français"] = lang.fr, + ["Español"] = lang.es, + ["中文"] = lang.zh, + ["日本語"] = lang.ja, + ["한국어"] = lang.ko, +} +\end{verbatim} + +\end{document} +% \end{macrocode} +% +% \begin{macrocode} +%</ex-verb> +% \end{macrocode} +% +% \fi +% % \end{implementation} % -% \PrintIndex +% % \Finale % \endinput diff --git a/Master/texmf-dist/source/xelatex/xecjk/xeCJK.ins b/Master/texmf-dist/source/xelatex/xecjk/xeCJK.ins index ff9493f666f..d6dda519368 100644 --- a/Master/texmf-dist/source/xelatex/xecjk/xeCJK.ins +++ b/Master/texmf-dist/source/xelatex/xecjk/xeCJK.ins @@ -6,7 +6,7 @@ %% %% xeCJK.dtx (with options: `batchfile') %% -%% $Id: xeCJK.dtx 358 2012-10-27 11:52:01Z sobenlee $ +%% $Id: xeCJK.dtx 368 2012-11-23 04:55:23Z sobenlee $ %% $URL: https://ctex-kit.googlecode.com/svn/trunk/xeCJK/xeCJK.dtx $ %% ----------------------------------------------------------------- %% Author: @@ -35,7 +35,7 @@ \askforoverwritefalse \preamble -$Id: xeCJK.dtx 358 2012-10-27 11:52:01Z sobenlee $ +$Id: xeCJK.dtx 368 2012-11-23 04:55:23Z sobenlee $ $URL: https://ctex-kit.googlecode.com/svn/trunk/xeCJK/xeCJK.dtx $ ----------------------------------------------------------------- Author: @@ -64,34 +64,56 @@ $URL: https://ctex-kit.googlecode.com/svn/trunk/xeCJK/xeCJK.dtx $ This package consists of the file xeCJK.dtx and the derived files xeCJK.pdf, xeCJK.sty, + xeCJK.cfg, xeCJK.ins, xeCJK-example-autofake.tex, xeCJK-example-fallback.tex, xeCJK-example-subCJKblock.tex, xeCJK-example-CJKecglue.tex, - xeCJK-example-checksingle.tex and + xeCJK-example-checksingle.tex, + xeCJK-example-CJKfntef.tex, + xeCJK-example-punctstyle.tex, + xeCJK-example-verbatim.tex, and README.txt. \endpostamble +\declarepreamble\emptypreamble +\endpreamble +\declarepostamble\emptypostamble +\endpostamble \usedir{tex/xelatex/xecjk} \generate{\file{\jobname.sty}{\from{\jobname.dtx}{package}}} +\usedir{tex/xelatex/xecjk/config} +\generate{ + \usepreamble\emptypreamble + \usepostamble\emptypostamble + \file{\jobname.cfg}{\from{\jobname.dtx}{config}}} \usedir{doc/xelatex/xecjk/example} \generate{ + \usepreamble\emptypreamble + \usepostamble\emptypostamble \file{\jobname-example-autofake.tex}{\from{\jobname.dtx}{ex-autofake}} \file{\jobname-example-fallback.tex}{\from{\jobname.dtx}{ex-fallback}} \file{\jobname-example-subCJKblock.tex}{\from{\jobname.dtx}{ex-block}} \file{\jobname-example-CJKecglue.tex}{\from{\jobname.dtx}{ex-ecglue}} - \file{\jobname-example-checksingle.tex}{\from{\jobname.dtx}{ex-single}}} + \file{\jobname-example-checksingle.tex}{\from{\jobname.dtx}{ex-single}} + \file{\jobname-example-CJKfntef.tex}{\from{\jobname.dtx}{ex-fntef}} + \file{\jobname-example-punctstyle.tex}{\from{\jobname.dtx}{ex-punctstyle}} + \file{\jobname-example-verbatim.tex}{\from{\jobname.dtx}{ex-verb}}} \endbatchfile %% %% This package consists of the file xeCJK.dtx %% and the derived files xeCJK.pdf, %% xeCJK.sty, +%% xeCJK.cfg, %% xeCJK.ins, %% xeCJK-example-autofake.tex, %% xeCJK-example-fallback.tex, %% xeCJK-example-subCJKblock.tex, %% xeCJK-example-CJKecglue.tex, -%% xeCJK-example-checksingle.tex and +%% xeCJK-example-checksingle.tex, +%% xeCJK-example-CJKfntef.tex, +%% xeCJK-example-punctstyle.tex, +%% xeCJK-example-verbatim.tex, and %% README.txt. %% %% End of file `xeCJK.ins'. diff --git a/Master/texmf-dist/tex/xelatex/xecjk/config/xeCJK.cfg b/Master/texmf-dist/tex/xelatex/xecjk/config/xeCJK.cfg new file mode 100644 index 00000000000..cf9c3189a7f --- /dev/null +++ b/Master/texmf-dist/tex/xelatex/xecjk/config/xeCJK.cfg @@ -0,0 +1,18 @@ +%% +%% This is file `xeCJK.cfg', +%% generated with the docstrip utility. +%% +%% The original source files were: +%% +%% xeCJK.dtx (with options: `config') +%% +\NeedsTeXFormat{LaTeX2e} +\GetIdInfo$Id: xeCJK.dtx 368 2012-11-23 04:55:23Z sobenlee $ + {Configuration file for xeCJK package} +\ProvidesExplFile + {\ExplFileName.cfg} + {\ExplFileDate}{3.1.0}{\ExplFileDescription} + +%% +%% +%% End of file `xeCJK.cfg'. diff --git a/Master/texmf-dist/tex/xelatex/xecjk/xeCJK.sty b/Master/texmf-dist/tex/xelatex/xecjk/xeCJK.sty index c229af4412c..f6876df0358 100644 --- a/Master/texmf-dist/tex/xelatex/xecjk/xeCJK.sty +++ b/Master/texmf-dist/tex/xelatex/xecjk/xeCJK.sty @@ -6,7 +6,7 @@ %% %% xeCJK.dtx (with options: `package') %% -%% $Id: xeCJK.dtx 358 2012-10-27 11:52:01Z sobenlee $ +%% $Id: xeCJK.dtx 368 2012-11-23 04:55:23Z sobenlee $ %% $URL: https://ctex-kit.googlecode.com/svn/trunk/xeCJK/xeCJK.dtx $ %% ----------------------------------------------------------------- %% Author: @@ -31,11 +31,11 @@ %% \NeedsTeXFormat{LaTeX2e} \RequirePackage{expl3} -\GetIdInfo$Id: xeCJK.dtx 358 2012-10-27 11:52:01Z sobenlee $ - {package for typesetting CJK scripts with XeLaTeX} +\GetIdInfo$Id: xeCJK.dtx 368 2012-11-23 04:55:23Z sobenlee $ + {Typesetting CJK scripts with XeLaTeX} \ProvidesExplPackage {\ExplFileName} - {\ExplFileDate}{3.0.10}{\ExplFileDescription} + {\ExplFileDate}{3.1.0}{\ExplFileDescription} \msg_new:nnn { xeCJK } { Require-XeTeX } { The~xeCJK~package~requires~XeTeX~to~function.\\\\ @@ -46,106 +46,116 @@ \xetex_if_engine:F { \msg_critical:nn { xeCJK } { Require-XeTeX } } \msg_new:nnn { xeCJK } { l3-too-old } { - Support~package~'expl3'~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.\\ - Loading~xeCJK~will~abort! - } -\@ifpackagelater { expl3 } { 2012/09/10 } { } - { \msg_critical:nn { xeCJK } { l3-too-old } } -\RequirePackage{xparse} -\RequirePackage{l3keys2e} -\msg_new:nnn { xeCJK } { XeTeX-too-old } - { - \token_to_str:N \XeTeXglyphbounds \ is~not~defined.\\\\ - You~have~to~update~XeTeX~to~the~version~0.9995.0~or~later. - } -\cs_if_free:NT \XeTeXglyphbounds - { - \msg_error:nn { xeCJK } { XeTeX-too-old } - \AtEndOfPackage { \__xeCJK_AfterPreamble:n { \punctstyle { plain } } } - } + \str_if_eq:nnT {#1} { expl3 } { Loading~xeCJK~will~abort! } + } +\@ifpackagelater { expl3 } { 2012/11/10 } { } + { \msg_critical:nnn { xeCJK } { l3-too-old } { expl3 } } +\RequirePackage { xtemplate } +\@ifpackagelater { xtemplate } { 2012/11/10 } { } + { \msg_error:nnn { xeCJK } { l3-too-old } { xtemplate } } +\RequirePackage { xparse , l3keys2e } +\RequirePackage { xpatch } +\tl_new:N \l__xeCJK_tmpa_tl +\tl_new:N \l__xeCJK_tmpb_tl \int_new:N \l__xeCJK_tmpa_int \int_new:N \l__xeCJK_tmpb_int \int_new:N \l__xeCJK_tmpc_int -\dim_new:N \l__xeCJK_tmpa_dim -\dim_new:N \l__xeCJK_tmpb_dim -\dim_new:N \l__xeCJK_tmpc_dim -\tl_new:N \l__xeCJK_tmpa_tl -\tl_new:N \l__xeCJK_tmpb_tl +\box_new:N \l__xeCJK_tmp_box +\dim_new:N \l__xeCJK_tmp_dim +\skip_new:N \g__xeCJK_tmp_skip +\prop_new:N \l__xeCJK_tmp_prop \clist_new:N \l__xeCJK_tmpa_clist \clist_new:N \l__xeCJK_tmpb_clist -\clist_new:N \l__xeCJK_tmpc_clist +\cs_new_protected_nopar:Npn \__xeCJK_msg_new:nn { \msg_new:nnn { xeCJK } } +\cs_new_protected_nopar:Npn \__xeCJK_error:n { \msg_error:nn { xeCJK } } +\cs_new_protected_nopar:Npn \__xeCJK_error:nx { \msg_error:nnx { xeCJK } } +\cs_new_protected_nopar:Npn \__xeCJK_warning:n { \msg_warning:nn { xeCJK } } +\cs_new_protected_nopar:Npn \__xeCJK_warning:nx { \msg_warning:nnx { xeCJK } } +\cs_new_protected_nopar:Npn \__xeCJK_warning:nxx { \msg_warning:nnxx { xeCJK } } +\cs_new_protected_nopar:Npn \__xeCJK_info:nx { \msg_info:nnx { xeCJK } } +\cs_new_protected_nopar:Npn \__xeCJK_info:nxx { \msg_info:nnxx { xeCJK } } +\cs_new_protected_nopar:Npn \xeCJK_allow_break: { \tex_penalty:D \c_zero } \cs_new_protected_nopar:Npn \xeCJK_no_break: { \tex_penalty:D \c_ten_thousand } \tl_new:N \g__xeCJK_at_end_preamble_hook_tl \tl_new:N \g__xeCJK_after_preamble_hook_tl \tl_new:N \g__xeCJK_after_end_preamble_hook_tl -\cs_new_protected:Npn \__xeCJK_AtEndPreamble:n #1 +\cs_new_protected:Npn \__xeCJK_at_end_preamble:n #1 { \tl_gput_right:Nn \g__xeCJK_at_end_preamble_hook_tl {#1} } -\cs_new_protected:Npn \__xeCJK_AfterPreamble:n #1 +\cs_new_protected:Npn \__xeCJK_after_preamble:n #1 { \tl_gput_right:Nn \g__xeCJK_after_preamble_hook_tl {#1} } -\cs_new_protected:Npn \__xeCJK_AfterEndPreamble:n #1 +\cs_new_protected:Npn \__xeCJK_after_end_preamble:n #1 { \tl_gput_right:Nn \g__xeCJK_after_end_preamble_hook_tl {#1} } -\AtBeginDocument { \g__xeCJK_after_preamble_hook_tl } -\tl_put_left:Nn \document { \group_end: \g__xeCJK_at_end_preamble_hook_tl \group_begin: } -\tl_put_right:Nn \document { \g__xeCJK_after_end_preamble_hook_tl \tex_ignorespaces:D } -\group_begin: -\char_set_lccode:nn { `\Z } { `\t } -\char_set_lccode:nn { `\Y } { `\c } -\char_set_lccode:nn { `\; } { `\: } -\char_set_lccode:nn { `\/ } { `\\ } -\tl_map_inline:nn { \T \F \C \J \K } { \char_set_lccode:nn { `#1 } { `#1 } } -\tl_map_function:nN { \O \U \Z \E \R \M \A \Y \R \; \/ } \char_set_catcode_other:N -\tl_to_lowercase:n +\AtEndPreamble { \g__xeCJK_at_end_preamble_hook_tl } +\AfterPreamble { \g__xeCJK_after_preamble_hook_tl } +\AfterEndPreamble { \g__xeCJK_after_end_preamble_hook_tl } +\cs_new_nopar:Npn \xeCJK_reverse:nnn #1#2#3 + { \str_if_eq_x:nnTF {#1} {#2} {#3} {#2} } +\cs_new_protected_nopar:Npn \xeCJK_tl_remove_outer_braces:N #1 + { \tl_set:Nx #1 { \exp_args:NV \xeCJK_tl_remove_outer_braces:n #1 } } +\cs_new:Npn \xeCJK_tl_remove_outer_braces:n #1 + { \__xeCJK_tl_remove_outer_braces:w #1 \q_stop } +\cs_new:Npn \__xeCJK_tl_remove_outer_braces:w #1 \q_stop { - \group_end: - \prg_new_conditional:Npnn \xeCJK_if_outer_macro:c #1 { p , T , F , TF } + \bool_if:nTF { \tl_if_single_p:n {#1} && \tl_if_head_is_group_p:n {#1} } + { \__xeCJK_tl_remove_outer_braces:w #1 \q_stop } + { \tl_trim_spaces:n {#1} } + } +\cs_new_protected:Npn \xeCJK_cs_add:Nnn #1#2#3 + { + \tl_if_empty:nTF {#3} + { \tl_if_empty:nTF {#2} { \use_ii:nn } { \xpretocmd {#1} {#2} } } { - \exp_last_unbraced:Nf \__xeCJK_if_outer_macro_aux:w - { \cs_meaning:c {#1} } OUZER ~ MAYRO ; \q_stop + \tl_if_empty:nTF {#2} { \xapptocmd {#1} {#3} } + { \xpretocmd {#1} {#2} { \xapptocmd {#1} {#3} } { \use_ii:nn } } } - \cs_new_nopar:Npn \__xeCJK_if_outer_macro_aux:w #1 OUZER ~ MAYRO ; #2 \q_stop + { \__xeCJK_info:nxx { patch-cmd } { \token_to_str:N #1 } { succeeded } } + { \__xeCJK_warning:nxx { patch-cmd } { \token_to_str:N #1 } { failed } } + } +\cs_new_protected:Npn \xeCJK_cs_patch:Nnn #1#2#3 + { + \xpatchcmd {#1} {#2} {#3} + { \__xeCJK_info:nxx { patch-cmd } { \token_to_str:N #1 } { succeeded } } + { \__xeCJK_warning:nxx { patch-cmd } { \token_to_str:N #1 } { failed } } + } +\__xeCJK_msg_new:nn { patch-cmd } { Patching~'#1'~#2! } +\cs_new_eq:NN \xeCJK_cs_clear:N \tl_clear:N +\cs_new_eq:NN \xeCJK_cs_gclear:N \tl_gclear:N +\cs_new_protected:Npn \xeCJK_swap_cs:NN #1#2 + { + \cs_set_eq:NN \__xeCJK_swap_cs_aux:w #1 + \cs_set_eq:NN #1 #2 + \cs_set_eq:NN #2 \__xeCJK_swap_cs_aux:w + \cs_undefine:N \__xeCJK_swap_cs_aux:w + } +\cs_new_protected_nopar:Npn \xeCJK_font_gset_to_current:c #1 + { + \exp_after:wN \cs_gset_eq:NN + \cs:w #1 \exp_after:wN \cs_end: \tex_the:D \tex_font:D + } +\prg_new_conditional:Npnn \xeCJK_glyph_if_exist:N #1 { p , T , F , TF } + { + \etex_iffontchar:D \tex_font:D `#1 \exp_stop_f: + \prg_return_true: \else: \prg_return_false: \fi: + } +\tl_const:Nn \c_xeCJK_space_skip_tl + { + \skip_if_eq:nnTF \tex_spaceskip:D \c_zero_skip { - \if_cs_exist:w c__xeCJK_prefix_#1_aux_tl \cs_end: - \prg_return_true: \else: \prg_return_false: \fi: + \tex_fontdimen:D \c_two \tex_font:D + plus \tex_fontdimen:D \c_three \tex_font:D + minus \tex_fontdimen:D \c_four \tex_font:D } - \tl_new:c { c__xeCJK_prefix_/_aux_tl } - \tl_new:c { c__xeCJK_prefix_/long/_aux_tl } - \tl_new:c { c__xeCJK_prefix_/protected/_aux_tl } - \tl_new:c { c__xeCJK_prefix_/protected/long/_aux_tl } - } -\token_new:Nn \l__xeCJK_peek_search_token { ? } -\cs_new_protected:Npn \xeCJK_peek_catcode_ignore_spaces:NTF #1#2#3 - { - \cs_set_eq:NN \l__xeCJK_peek_search_token #1 \prg_do_nothing: - \tl_set:Nn \__xeCJK_peek_true:w { \group_align_safe_end: #2 } - \tl_set:Nn \__xeCJK_peek_false:w { \group_align_safe_end: #3 } - \group_align_safe_begin: - \peek_after:Nw \__xeCJK_peek_ignore_spaces_execute_branches: - } -\cs_new_protected:Npn \xeCJK_peek_catcode_ignore_spaces:NT #1#2 - { \xeCJK_peek_catcode_ignore_spaces:NTF #1 {#2} { } } -\cs_new_protected:Npn \xeCJK_peek_catcode_ignore_spaces:NF #1#2 - { \xeCJK_peek_catcode_ignore_spaces:NTF #1 { } {#2} } -\cs_new_nopar:Npn \__xeCJK_peek_ignore_spaces_execute_branches: - { - \if_meaning:w \l_peek_token \c_space_token - \tex_afterassignment:D \__xeCJK_peek_ignore_spaces_execute_branches_aux: - \exp_after:wN \cs_set_eq:NN \exp_after:wN \__xeCJK_peek_tmp:w - \else: - \exp_after:wN \__xeCJK_peek_execute_branches_catcode: - \fi: + { \tex_spaceskip:D } } -\cs_new_protected_nopar:Npn \__xeCJK_peek_ignore_spaces_execute_branches_aux: - { \peek_after:Nw \__xeCJK_peek_ignore_spaces_execute_branches: } -\cs_new_nopar:Npn \__xeCJK_peek_execute_branches_catcode: +\cs_new_protected_nopar:Npn \xeCJK_glue_to_skip:nN #1#2 { - \if_catcode:w \exp_not:N \l_peek_token \exp_not:N \l__xeCJK_peek_search_token - \exp_after:wN \__xeCJK_peek_true:w - \else: - \exp_after:wN \__xeCJK_peek_false:w - \fi: + \hbox_set:Nn \l__xeCJK_tmp_box + { #1 \skip_gset_eq:NN \g__xeCJK_tmp_skip \tex_lastskip:D } + \skip_set_eq:NN #2 \g__xeCJK_tmp_skip } \prg_new_conditional:Npnn \xeCJK_if_blank_x:n #1 { p , T , F , TF } { @@ -158,90 +168,158 @@ } \prg_new_conditional:Npnn \xeCJK_if_package_loaded:n #1 { p , T , F , TF } { - \tl_if_exist:cTF { ver@ #1 . \c__xeCJK_pkg_extension_tl } - { \prg_return_true: } { \prg_return_false: } + \tl_if_exist:cTF { ver@ #1 . \c__xeCJK_package_ext_tl } + { \prg_return_true: } + { \prg_return_false: } } -\tl_const:Nx \c__xeCJK_pkg_extension_tl { \@pkgextension } -\cs_new_nopar:Npn \__xeCJK_msg_new:nn { \msg_new:nnn { xeCJK } } -\cs_new_nopar:Npn \__xeCJK_error:n { \msg_error:nn { xeCJK } } -\cs_new_nopar:Npn \__xeCJK_error:nx { \msg_error:nnx { xeCJK } } -\cs_new_nopar:Npn \__xeCJK_warning:n { \msg_warning:nn { xeCJK } } -\cs_new_nopar:Npn \__xeCJK_warning:nx { \msg_warning:nnx { xeCJK } } -\cs_new_nopar:Npn \__xeCJK_warning:nxx { \msg_warning:nnxx { xeCJK } } -\cs_new_nopar:Npn \__xeCJK_info:nx { \msg_info:nnx { xeCJK } } -\cs_new_nopar:Npn \__xeCJK_info:nxx { \msg_info:nnxx { xeCJK } } +\tl_const:Nx \c__xeCJK_package_ext_tl { \@pkgextension } +\cs_new_protected:Npn \xeCJK_int_until_do:nn #1#2 + { \__xeCJK_int_until_do:wn \use_none:n { \reverse_if:N \if_int_compare:w #1#2 } } +\cs_new_protected:Npn \__xeCJK_int_until_do:wn \use_none:n #1 + { #1 \exp_after:wN \__xeCJK_int_until_do:wn \fi: \use_none:n {#1} } \keys_define:nn { xeCJK / options } { - xeCJKactive .choice:, + xeCJKactive .choice: , xeCJKactive / true .code:n = { \makexeCJKactive } , xeCJKactive / false .code:n = { \makexeCJKinactive } , - xeCJKactive .default:n = { true }, + xeCJKactive .default:n = { true } } \NewDocumentCommand \makexeCJKactive { } { \XeTeXinterchartokenstate = \c_one } \NewDocumentCommand \makexeCJKinactive { } { \XeTeXinterchartokenstate = \c_zero } \char_set_catcode_ignore:n { "FEFF } -\int_const:Nn \c__xeCJK_Default_class_int { 0 } -\int_const:Nn \c__xeCJK_CJK_class_int { 1 } -\int_const:Nn \c__xeCJK_FullLeft_class_int { 2 } -\int_const:Nn \c__xeCJK_FullRight_class_int { 3 } -\int_const:Nn \c__xeCJK_Boundary_class_int { 255 } -\cs_new_protected_nopar:Npn \__xeCJK_new_class:n #1 +\int_const:Nn \c__xeCJK_Default_class_int { \c_zero } +\int_const:Nn \c__xeCJK_CJK_class_int { \c_one } +\int_const:Nn \c__xeCJK_FullLeft_class_int { \c_two } +\int_const:Nn \c__xeCJK_FullRight_class_int { \c_three } +\int_const:Nn \c__xeCJK_Boundary_class_int { \c_two_hundred_fifty_five } +\cs_new_protected_nopar:Npn \xeCJK_new_class:n #1 { \exp_args:Nc \newXeTeXintercharclass { c__xeCJK_#1_class_int } \clist_gclear_new:c { g__xeCJK_#1_range_clist } \seq_gput_right:Nv \g__xeCJK_class_seq { c__xeCJK_#1_class_int } } \seq_new:N \g__xeCJK_class_seq -\__xeCJK_new_class:n { HalfLeft } -\__xeCJK_new_class:n { HalfRight } -\__xeCJK_new_class:n { NormalSpace } -\clist_set:Nn \g__xeCJK_base_class_clist - { - Default, CJK, FullLeft, FullRight, Boundary, - HalfLeft, HalfRight, NormalSpace - } -\clist_map_inline:Nn \g__xeCJK_base_class_clist +\xeCJK_new_class:n { HalfLeft } +\xeCJK_new_class:n { HalfRight } +\xeCJK_new_class:n { NormalSpace } +\clist_const:Nn \c__xeCJK_HalfLeft_chars_clist + { "28 , "2D , "5B , "60 , "7B } +\clist_const:Nn \c__xeCJK_HalfRight_chars_clist + { "21 , "22 , "25 , "27 , "29 , "2C , "2E , "3A , "3B , "3F , "5D , "7D } +\clist_const:Nn \c__xeCJK_NormalSpace_chars_clist { "2F } +\clist_const:Nn \c__xeCJK_FullLeft_chars_clist + { + "2018 , "201C , "2116 , "3008 , "300A , "300C , "300E , "3010 , "3012 , + "3014 , "3016 , "3018 , "301A , "301D , "3036 , "E76C , "FE59 , "FE5B , + "FE5D , "FE5F , "FE60 , "FE69 , "FE6B , "FF03 , "FF04 , "FF08 , "FF20 , + "FF3B , "FF5B , "FFE0 , "FFE1 , "FFE5 , "FFE6 + } +\clist_const:Nn \c__xeCJK_FullRight_chars_clist + { + "00B7 , "2019 , "201D , "2014 , "2015 , "2025 , "2026 , "2030 , "2500 , + "3001 , "3002 , "3005 , "3006 , "3009 , "300B , "300D , "300F , "3011 , + "3015 , "3017 , "3019 , "301B , "301E , "301F , "3041 , "3043 , "3045 , + "3047 , "3049 , "3063 , "3083 , "3085 , "3087 , "308E , "309B , "309C , + "309D , "309E , "30A1 , "30A3 , "30A5 , "30A7 , "30A9 , "30C3 , "30E3 , + "30E5 , "30E7 , "30EE , "30F5 , "30F6 , "30FB , "30FC , "30FD , "30FE , + "FE50 , "FE51 , "FE52 , "FE54 , "FE55 , "FE56 , "FE57 , "FE5A , "FE5C , + "FE5E , "FE6A , "FF01 , "FF05 , "FF09 , "FF0C , "FF0E , "FF1A , "FF1B , + "FF1F , "FF3D , "FF5D , "FF61 , "FF63 , "FF64 , "FF65 , "FF67 , "FF68 , + "FF69 , "FF6A , "FF6B , "FF6C , "FF6D , "FF6E , "FF6F , "FF70 , "FF9E , + "FF9F + } +\clist_const:Nn \c__xeCJK_CJK_chars_clist + { + "1100 -> "11FF , + "2E80 -> "2EFF , + "2F00 -> "2FDF , + "2FF0 -> "2FFF , + "3000 -> "303F , + "3040 -> "309F , + "30A0 -> "30FF , + "3100 -> "312F , + "3130 -> "318F , + "3190 -> "319F , + "31A0 -> "31BF , + "31C0 -> "31EF , + "31F0 -> "31FF , + "3200 -> "32FF , + "3300 -> "33FF , + "3400 -> "4DBF , + "4DC0 -> "4DFF , + "4E00 -> "9FFF , + "A000 -> "A48F , + "A490 -> "A4CF , + "A960 -> "A97F , + "AC00 -> "D7AF , + "B000 -> "B0FF , + "D7B0 -> "D7FF , + "F900 -> "FAFF , + "FE30 -> "FE4F , + "FF00 -> "FFEF , + "20000 -> "2A6DF , + "2A700 -> "2B73F , + "2B740 -> "2B81F , + "2F800 -> "2FA1F + } +\seq_new:N \g__xeCJK_base_class_seq +\seq_gset_split:Nnn \g__xeCJK_base_class_seq { , } + { + Default , CJK , FullLeft , FullRight , Boundary , + HalfLeft , HalfRight , NormalSpace + } +\seq_map_inline:Nn \g__xeCJK_base_class_seq { \clist_gclear_new:c { g__xeCJK_#1_range_clist } } -\clist_new:N \g__xeCJK_CJK_class_clist +\seq_new:N \g__xeCJK_CJK_class_seq \prop_new:N \g__xeCJK_CJK_class_prop \cs_new_protected_nopar:Npn \__xeCJK_save_CJK_class:n #1 { - \clist_gput_right:Nx \g__xeCJK_CJK_class_clist {#1} - \prop_gput:Nvx \g__xeCJK_CJK_class_prop { c__xeCJK_#1_class_int } {#1} + \seq_gput_right:Nn \g__xeCJK_CJK_class_seq {#1} + \prop_gput:Nvn \g__xeCJK_CJK_class_prop { c__xeCJK_#1_class_int } {#1} + } +\cs_generate_variant:Nn \prop_gput:Nnn { Nvn } +\clist_map_function:nN { CJK , FullLeft , FullRight } \__xeCJK_save_CJK_class:n +\cs_new_nopar:Npn \xeCJK_class_num:n #1 { \use:c { c__xeCJK_#1_class_int } } +\cs_new_nopar:Npn \xeCJK_value_class:n #1 + { \XeTeXcharclass \etex_numexpr:D #1 \scan_stop: } +\prg_new_conditional:Npnn \xeCJK_if_same_class:NN #1#2 { p , T , F , TF } + { + \if_int_compare:w \xeCJK_value_class:n {`#1} = \xeCJK_value_class:n {`#2} + \prg_return_true: \else: \prg_return_false: \fi: } -\cs_generate_variant:Nn \prop_gput:Nnn { Nvx } -\clist_map_function:nN { CJK, FullLeft, FullRight } \__xeCJK_save_CJK_class:n -\cs_new_nopar:Npn \__xeCJK_class_num:n #1 { \tl_use:c { c__xeCJK_#1_class_int } } \NewDocumentCommand \xeCJKDeclareCharClass { s > { \TrimSpaces } m m } { - \__xeCJK_declare_char_class:nn {#2} {#3} + \xeCJK_declare_char_class:nx {#2} {#3} \IfBooleanT {#1} { \xeCJKResetPunctClass } } -\cs_new_protected_nopar:Npn \__xeCJK_declare_char_class:nn #1#2 +\cs_new_protected_nopar:Npn \xeCJK_declare_char_class:nn #1#2 { - \clist_gput_right:cx { g__xeCJK_#1_range_clist } {#2} - \clist_map_inline:xn {#2} + \clist_set:Nn \l__xeCJK_tmpa_clist {#2} + \clist_gconcat:ccN + { g__xeCJK_#1_range_clist } { g__xeCJK_#1_range_clist } \l__xeCJK_tmpa_clist + \clist_map_inline:Nn \l__xeCJK_tmpa_clist { - \str_if_eq_x:nnF {##1} { -> } + \str_if_eq:nnF {##1} { -> } { - \__xeCJK_set_char_class_aux:Nn \__xeCJK_set_char_class:nnn {##1} - { \__xeCJK_class_num:n {#1} } + \__xeCJK_set_char_class_aux:Nnw \xeCJK_set_char_class:nnn {##1} + { \xeCJK_class_num:n {#1} } } } } -\NewDocumentCommand \__xeCJK_set_char_class_aux:Nn +\NewDocumentCommand \__xeCJK_set_char_class_aux:Nnw { m > { \SplitArgument { 1 } { -> } } m } { #1 #2 } -\cs_generate_variant:Nn \clist_map_inline:nn { x } +\cs_generate_variant:Nn \clist_gconcat:NNN { cc } +\cs_generate_variant:Nn \xeCJK_declare_char_class:nn { nx , nV } \NewDocumentCommand \xeCJKsetcharclass { s m m m } { - \__xeCJK_set_char_class:nnn {#2} {#3} {#4} + \xeCJK_set_char_class:nnn {#2} {#3} {#4} \IfBooleanF {#1} { \xeCJKResetPunctClass } } -\cs_new_protected_nopar:Npn \__xeCJK_set_char_class:nnn #1#2#3 +\cs_new_protected_nopar:Npn \xeCJK_set_char_class:nnn #1#2#3 { \__xeCJK_check_num_range:nnNN {#1} {#2} \l__xeCJK_tmpa_int \l__xeCJK_tmpb_int \int_set:Nn \l__xeCJK_tmpc_int {#3} - \prop_if_in:NVTF \g__xeCJK_CJK_class_prop \l__xeCJK_tmpc_int + \prop_get:NVNTF \g__xeCJK_CJK_class_prop \l__xeCJK_tmpc_int \l__xeCJK_tmpa_tl { \cs_set_eq:NN \__xeCJK_set_char_catcode:n \char_set_catcode_other:n } { \cs_set_eq:NN \__xeCJK_set_char_catcode:n \use_none:n } \xeCJK_int_until_do:nn { \l__xeCJK_tmpa_int > \l__xeCJK_tmpb_int } @@ -251,16 +329,6 @@ \int_incr:N \l__xeCJK_tmpa_int } } -\cs_new_protected:Npn \xeCJK_int_until_do:nn #1#2 - { - \__xeCJK_int_until_do_aux:wn \use_none:n - { \reverse_if:N \if_int_compare:w #1#2 } - } -\cs_new_protected:Npn \__xeCJK_int_until_do_aux:wn \use_none:n #1 - { - #1 \exp_after:wN \__xeCJK_int_until_do_aux:wn \fi: - \use_none:n {#1} - } \cs_new_protected_nopar:Npn \__xeCJK_check_num_range:nnNN #1#2#3#4 { \bool_if:nTF { \xeCJK_if_blank_x_p:n {#1} || \xeCJK_if_blank_x_p:n {#2} } @@ -273,532 +341,466 @@ \int_set:Nn #4 { \int_max:nn {#1} { \IfNoValueTF {#2} {#1} {#2} } } } } -\NewDocumentCommand \xeCJKResetPunctClass { } +\cs_new_protected_nopar:Npn \__xeCJK_set_char_class_eq:nn #1#2 { - \__xeCJK_declare_char_class:nn { HalfLeft } - { "28 , "2D , "5B , "60 , "7B } - \__xeCJK_declare_char_class:nn { HalfRight } - { "21 , "22 , "25 , "27 , "29 , "2C , "2E , "3A , "3B , "3F , "5D , "7D , } - \__xeCJK_declare_char_class:nn { FullLeft } - { - "2018 , "201C , "2116 , "3008 , "300A , "300C , "300E , "3010 , "3012 , - "3014 , "3016 , "3018 , "301A , "301D , "3036 , "E76C , "FE59 , "FE5B , - "FE5D , "FE5F , "FE60 , "FE69 , "FE6B , "FF03 , "FF04 , "FF08 , "FF20 , - "FF3B , "FF5B , "FFE0 , "FFE1 , "FFE5 , "FFE6 , - } - \__xeCJK_declare_char_class:nn { FullRight } - { - "00B7 , "2019 , "201D , "2014 , "2015 , "2025 , "2026 , "2030 , "2500 , - "3001 , "3002 , "3005 , "3006 , "3009 , "300B , "300D , "300F , "3011 , - "3015 , "3017 , "3019 , "301B , "301E , "301F , "3041 , "3043 , "3045 , - "3047 , "3049 , "3063 , "3083 , "3085 , "3087 , "308E , "309B , "309C , - "309D , "309E , "30A1 , "30A3 , "30A5 , "30A7 , "30A9 , "30C3 , "30E3 , - "30E5 , "30E7 , "30EE , "30F5 , "30F6 , "30FB , "30FC , "30FD , "30FE , - "FE50 , "FE51 , "FE52 , "FE54 , "FE55 , "FE56 , "FE57 , "FE5A , "FE5C , - "FE5E , "FE6A , "FF01 , "FF05 , "FF09 , "FF0C , "FF0E , "FF1A , "FF1B , - "FF1F , "FF3D , "FF5D , "FF61 , "FF63 , "FF64 , "FF65 , "FF67 , "FF68 , - "FF69 , "FF6A , "FF6B , "FF6C , "FF6D , "FF6E , "FF6F , "FF70 , "FF9E , - "FF9F , - } - } -\__xeCJK_declare_char_class:nn { CJK } - { - "1100 -> "11FF , - "2E80 -> "2EFF , - "2F00 -> "2FDF , - "2FF0 -> "2FFF , - "3000 -> "303F , - "3040 -> "309F , - "30A0 -> "30FF , - "3100 -> "312F , - "3130 -> "318F , - "3190 -> "319F , - "31A0 -> "31BF , - "31C0 -> "31EF , - "31F0 -> "31FF , - "3200 -> "32FF , - "3300 -> "33FF , - "3400 -> "4DBF , - "4DC0 -> "4DFF , - "4E00 -> "9FFF , - "A000 -> "A48F , - "A490 -> "A4CF , - "A960 -> "A97F , - "AC00 -> "D7AF , - "B000 -> "B0FF , - "D7B0 -> "D7FF , - "F900 -> "FAFF , - "FE30 -> "FE4F , - "FF00 -> "FFEF , - "20000 -> "2A6DF , - "2A700 -> "2B73F , - "2B740 -> "2B81F , - "2F800 -> "2FA1F , - } -\xeCJKResetPunctClass + \int_set:Nn \l__xeCJK_tmpa_int { \xeCJK_class_num:n {#1} } + \clist_map_inline:cn { c__xeCJK_#2_chars_clist } + { \XeTeXcharclass ##1 = \l__xeCJK_tmpa_int } + } \NewDocumentCommand \normalspacedchars { m } { - \tl_map_inline:nn {#1} - { \XeTeXcharclass `##1 = \__xeCJK_class_num:n { NormalSpace } } + \tl_map_inline:xn {#1} + { \XeTeXcharclass `##1 = \xeCJK_class_num:n { NormalSpace } } } -\normalspacedchars{/} -\cs_new_protected_nopar:Npn \__xeCJK_inter_class_toks:nnn #1#2#3 - { \XeTeXinterchartoks \__xeCJK_class_num:n {#1} \__xeCJK_class_num:n {#2} = {#3} } -\cs_generate_variant:Nn \__xeCJK_inter_class_toks:nnn { nnc , nnx } -\cs_new_nopar:Npn \__xeCJK_get_inter_class_toks:nn #1#2 - { \tex_the:D \XeTeXinterchartoks \__xeCJK_class_num:n {#1} \__xeCJK_class_num:n {#2} } -\cs_new_protected_nopar:Npn \__xeCJK_clear_inter_class_toks:nn #1#2 - { \__xeCJK_inter_class_toks:nnn {#1} {#2} { \c_empty_tl } } -\cs_new_protected_nopar:Npn \__xeCJK_pre_inter_class_toks:nnn #1#2#3 +\cs_generate_variant:Nn \tl_map_inline:nn { x } +\NewDocumentCommand \xeCJKResetPunctClass { } { - \__xeCJK_inter_class_toks:nnx {#1} {#2} - { \exp_not:n {#3} \__xeCJK_get_inter_class_toks:nn {#1} {#2} } + \xeCJK_declare_char_class:nV { HalfLeft } \c__xeCJK_HalfLeft_chars_clist + \xeCJK_declare_char_class:nV { HalfRight } \c__xeCJK_HalfRight_chars_clist + \xeCJK_declare_char_class:nV { FullLeft } \c__xeCJK_FullLeft_chars_clist + \xeCJK_declare_char_class:nV { FullRight } \c__xeCJK_FullRight_chars_clist } -\cs_new_protected_nopar:Npn \__xeCJK_app_inter_class_toks:nnn #1#2#3 +\NewDocumentCommand \xeCJKResetCharClass { } { - \__xeCJK_inter_class_toks:nnx {#1} {#2} - { \__xeCJK_get_inter_class_toks:nn {#1} {#2} \exp_not:n {#3} } + \xeCJK_declare_char_class:nV { CJK } \c__xeCJK_CJK_chars_clist + \xeCJK_declare_char_class:nV { NormalSpace } \c__xeCJK_NormalSpace_chars_clist + \xeCJKResetPunctClass } -\cs_generate_variant:Nn \__xeCJK_app_inter_class_toks:nnn { nnc } -\cs_new_protected_nopar:Npn \__xeCJK_copy_inter_class_toks:nnnn #1#2#3#4 +\xeCJKResetCharClass +\cs_new_protected_nopar:Npn \xeCJK_inter_class_toks:nnn #1#2#3 + { \XeTeXinterchartoks \xeCJK_class_num:n {#1} ~ \xeCJK_class_num:n {#2} = {#3} } +\cs_generate_variant:Nn \xeCJK_inter_class_toks:nnn { nnc , nnx } +\cs_new_nopar:Npn \xeCJK_get_inter_class_toks:nn #1#2 + { \tex_the:D \XeTeXinterchartoks \xeCJK_class_num:n {#1} ~ \xeCJK_class_num:n {#2} } +\cs_new_protected_nopar:Npn \xeCJK_clear_inter_class_toks:nn #1#2 + { \xeCJK_inter_class_toks:nnn {#1} {#2} { \prg_do_nothing: } } +\cs_new_protected_nopar:Npn \xeCJK_pre_inter_class_toks:nnn #1#2#3 { - \__xeCJK_inter_class_toks:nnx {#1} {#2} - { \__xeCJK_get_inter_class_toks:nn {#3} {#4} } + \xeCJK_inter_class_toks:nnx {#1} {#2} + { \exp_not:n {#3} \xeCJK_get_inter_class_toks:nn {#1} {#2} } } -\cs_new_protected_nopar:Npn \__xeCJK_clear_CJK_toks: +\cs_generate_variant:Nn \xeCJK_pre_inter_class_toks:nnn { nnx } +\cs_new_protected_nopar:Npn \xeCJK_app_inter_class_toks:nnn #1#2#3 { - \clist_map_inline:Nn \g__xeCJK_CJK_class_clist - { \__xeCJK_clear_inter_class_toks:nn { Boundary } {##1} } + \xeCJK_inter_class_toks:nnx {#1} {#2} + { \xeCJK_get_inter_class_toks:nn {#1} {#2} \exp_not:n {#3} } } -\clist_map_inline:nn { Default, HalfLeft, HalfRight, NormalSpace } +\cs_generate_variant:Nn \xeCJK_app_inter_class_toks:nnn { nnc , nnx } +\cs_new_protected_nopar:Npn \xeCJK_copy_inter_class_toks:nnnn #1#2#3#4 { - \clist_map_inline:nn { CJK, FullLeft, FullRight } + \xeCJK_inter_class_toks:nnx {#1} {#2} + { \xeCJK_get_inter_class_toks:nn {#3} {#4} } + } +\cs_new_protected_nopar:Npn \xeCJK_replace_inter_class_toks:nnnn #1#2#3#4 + { + \tl_set:Nx \l__xeCJK_tmpa_tl { \xeCJK_get_inter_class_toks:nn {#1} {#2} } + \tl_replace_all:Nnn \l__xeCJK_tmpa_tl {#3} {#4} + \xeCJK_inter_class_toks:nnx {#1} {#2} { \exp_not:V \l__xeCJK_tmpa_tl } + } +\cs_new_protected_nopar:Npn \xeCJK_clear_Boundary_and_CJK_toks: + { \seq_map_function:NN \g__xeCJK_CJK_class_seq \__xeCJK_clear_Boundary_and_CJK_toks:n } +\cs_new_protected_nopar:Npn \__xeCJK_clear_Boundary_and_CJK_toks:n #1 + { \xeCJK_clear_inter_class_toks:nn { Boundary } {#1} } +\cs_new_eq:NN \xeCJK_class_group_begin: \c_group_begin_token +\cs_new_eq:NN \xeCJK_class_group_end: \c_group_end_token +\clist_map_inline:nn { Default , HalfLeft , HalfRight , NormalSpace } + { + \clist_map_inline:nn { CJK , FullLeft , FullRight } { - \__xeCJK_inter_class_toks:nnn {#1} {##1} + \xeCJK_inter_class_toks:nnn {#1} {##1} { - \c_group_begin_token + \xeCJK_class_group_begin: \xeCJK_select_font: - \__xeCJK_clear_inter_class_toks:nn {#1} {##1} - \__xeCJK_clear_CJK_toks: + \xeCJK_clear_inter_class_toks:nn {#1} {##1} + \xeCJK_clear_Boundary_and_CJK_toks: } - \__xeCJK_inter_class_toks:nnn {##1} {#1} { \c_group_end_token } + \xeCJK_inter_class_toks:nnn {##1} {#1} { \xeCJK_class_group_end: } } - \__xeCJK_app_inter_class_toks:nnn {#1} { CJK } { \CJKsymbol } - \clist_map_inline:nn { FullLeft, FullRight } - { \__xeCJK_app_inter_class_toks:nnc {#1} {##1} { xeCJK_CJK_and_##1:N } } + \xeCJK_app_inter_class_toks:nnn {#1} { CJK } { \CJKsymbol } + \clist_map_inline:nn { FullLeft , FullRight } + { \xeCJK_app_inter_class_toks:nnc {#1} {##1} { xeCJK_CJK_and_##1:N } } } -\clist_map_inline:nn { Default, HalfLeft, NormalSpace } +\clist_map_inline:nn { Default , HalfLeft , NormalSpace } { - \__xeCJK_inter_class_toks:nnn { Boundary } {#1} + \xeCJK_inter_class_toks:nnn { Boundary } {#1} { \bool_if:nTF { \l__xeCJK_xecglue_bool && - \int_compare_p:nNn \etex_lastnodetype:D = \c_eleven && - \skip_if_eq_p:nn \tex_lastskip:D \l__xeCJK_space_glue_tl + \skip_if_eq_p:nn \tex_lastskip:D \c_xeCJK_space_skip_tl } { \tex_unskip:D \bool_if:nTF - { \xeCJK_if_last_node_p:n { CJK } || \xeCJK_if_last_node_p:n { CJK_space } } + { + \xeCJK_if_last_node_p:n { CJK } || + \xeCJK_if_last_node_p:n { CJK-space } + } { \CJKecglue } { \c_space_token } } { \xeCJK_if_last_node:nTF { CJK } { \CJKecglue } - { \xeCJK_if_last_node:nT { CJK_space } { \__xeCJK_space_or_xecglue: } } + { \xeCJK_if_last_node:nT { CJK-space } { \__xeCJK_space_or_xecglue: } } } } - \str_if_eq_x:nnF {#1} { NormalSpace } - { \__xeCJK_app_inter_class_toks:nnn { CJK } {#1} { \CJKecglue } } + \str_if_eq:nnF {#1} { NormalSpace } + { \xeCJK_app_inter_class_toks:nnn { CJK } {#1} { \CJKecglue } } } -\clist_map_inline:nn { Default, HalfRight, NormalSpace } +\clist_map_inline:nn { Default , HalfRight , NormalSpace } { - \__xeCJK_inter_class_toks:nnn {#1} { Boundary } + \xeCJK_inter_class_toks:nnn {#1} { Boundary } { - \peek_catcode:NTF \c_space_token - { { \xeCJK_make_node:n { default_space } } } - { { \xeCJK_make_node:n { default } } } + \peek_meaning_remove:NTF \/ + { \/ { \xeCJK_make_node:n { default } } } + { + \token_if_space:NTF \l_peek_token + { { \xeCJK_make_node:n { default-space } } } + { { \xeCJK_make_node:n { default } } } + } } - \str_if_eq_x:nnF {#1} { NormalSpace } - { \__xeCJK_pre_inter_class_toks:nnn {#1} { CJK } { \CJKecglue } } + \str_if_eq:nnF {#1} { NormalSpace } + { \xeCJK_pre_inter_class_toks:nnn {#1} { CJK } { \CJKecglue } } } -\__xeCJK_inter_class_toks:nnn { Boundary } { CJK } { \xeCJK_Boundary_and_CJK: } -\cs_new_protected_nopar:Npn \xeCJK_Boundary_and_CJK: +\xeCJK_inter_class_toks:nnn { Boundary } { CJK } { - { \__xeCJK_check_for_glue: } - \c_group_begin_token - \__xeCJK_clear_CJK_toks: + { \xeCJK_check_for_glue: } + \xeCJK_class_group_begin: + \xeCJK_clear_Boundary_and_CJK_toks: \xeCJK_select_font: \CJKsymbol } -\cs_new_protected_nopar:Npn \__xeCJK_check_for_glue: +\cs_new_protected_nopar:Npn \xeCJK_check_for_glue: { \bool_if:nTF - { \xeCJK_if_last_node_p:n { CJK } || \xeCJK_if_last_node_p:n { CJK_space } } + { \xeCJK_if_last_node_p:n { CJK } || \xeCJK_if_last_node_p:n { CJK-space } } { \CJKglue } { \bool_if:nTF { \xeCJK_if_last_node_p:n { default } || - \int_compare_p:nNn \etex_lastnodetype:D = \c_ten || - \xeCJK_if_last_node_p:n { default_itcorr } + \int_compare_p:nNn \etex_lastnodetype:D = \c_ten } { \CJKecglue } { \bool_if:nT { \l__xeCJK_xecglue_bool && - \int_compare_p:nNn \etex_lastnodetype:D = \c_eleven && - ( \skip_if_eq_p:nn \tex_lastskip:D \l__xeCJK_space_glue_tl || - \dim_compare_p:nNn \tex_lastskip:D = \l__xeCJK_ecglue_dim ) + ( \skip_if_eq_p:nn \tex_lastskip:D \c_xeCJK_space_skip_tl || + \skip_if_eq_p:nn \tex_lastskip:D \l__xeCJK_ecglue_skip ) } { \tex_unskip:D \bool_if:nTF { - \xeCJK_if_last_node_p:n { default_space } || + \xeCJK_if_last_node_p:n { default-space } || \int_compare_p:nNn \etex_lastnodetype:D = \c_ten || - \xeCJK_if_last_node_p:n { default } || - \xeCJK_if_last_node_p:n { default_itcorr } + \xeCJK_if_last_node_p:n { default } } { \CJKecglue } { \bool_if:nTF { \xeCJK_if_last_node_p:n { CJK } || - \xeCJK_if_last_node_p:n { CJK_space } + \xeCJK_if_last_node_p:n { CJK-space } } - { \bool_if:NTF \l__xeCJK_space_bool \c_space_token \CJKglue } + { \bool_if:NTF \l__xeCJK_reserve_space_bool \c_space_token \CJKglue } { \c_space_token } } } } } } -\tl_set:Nn \l__xeCJK_space_glue_tl + \prg_new_conditional:Npnn \xeCJK_if_last_node:n #1 { p , T , F , TF } + { + \if_dim:w \use:c { c__xeCJK_#1_node_dim } = \tex_lastkern:D + \prg_return_true: \else: \prg_return_false: \fi: + } +\cs_new_protected_nopar:Npn \xeCJK_def_node:nn #1#2 + { + \dim_if_exist:cTF { c__xeCJK_#1_node_dim } + { \dim_gset:cn } { \dim_const:cn } + { c__xeCJK_#1_node_dim } {#2} + } +\cs_new_protected_nopar:Npn \xeCJK_make_node:n #1 + { + \tex_kern:D - \use:c { c__xeCJK_#1_node_dim } + \tex_kern:D \use:c { c__xeCJK_#1_node_dim } + } +\xeCJK_def_node:nn { CJK } { 11 sp } +\xeCJK_def_node:nn { CJK-space } { 12 sp } +\xeCJK_def_node:nn { default } { 13 sp } +\xeCJK_def_node:nn { default-space } { 14 sp } +\keys_define:nn { xeCJK / options } + { CJKglue .code:n = { \cs_set_protected:Npn \CJKglue {#1} } } +\keys_define:nn { xeCJK / options } + { + CJKecglue .code:n = + { + \cs_set_protected:Npn \CJKecglue {#1} + \xeCJK_glue_to_skip:nN \CJKecglue \l__xeCJK_ecglue_skip + } , + xCJKecglue .choice: , + xCJKecglue / true .code:n = + { + \bool_set_true:N \l__xeCJK_xecglue_bool + \cs_set_eq:NN \__xeCJK_space_or_xecglue: \CJKecglue + } , + xCJKecglue / false .code:n = + { + \bool_set_false:N \l__xeCJK_xecglue_bool + \cs_set_eq:NN \__xeCJK_space_or_xecglue: \c_space_token + } , + xCJKecglue / unknown .code:n = + { + \bool_set_true:N \l__xeCJK_xecglue_bool + \cs_set_protected:Npn \CJKecglue {#1} + \xeCJK_glue_to_skip:nN \CJKecglue \l__xeCJK_ecglue_skip + \cs_set_eq:NN \__xeCJK_space_or_xecglue: \CJKecglue + } , + xCJKecglue .default:n = { true } + } +\skip_new:N \l__xeCJK_ecglue_skip +\bool_new:N \l__xeCJK_xecglue_bool +\keys_define:nn { xeCJK / options } { - \tex_fontdimen:D \c_two \tex_font:D - \@plus \tex_fontdimen:D \c_three \tex_font:D - \@minus \tex_fontdimen:D \c_four \tex_font:D + CJKspace .bool_set:N = \l__xeCJK_reserve_space_bool , + space .meta:n = { CJKspace = true } , + nospace .meta:n = { CJKspace = false } } -\__xeCJK_inter_class_toks:nnn { CJK } { Boundary } +\xeCJK_inter_class_toks:nnn { CJK } { Boundary } { - \c_group_end_token + \xeCJK_class_group_end: { \xeCJK_make_node:n { CJK } } - \xeCJK_ignorespaces: + \xeCJK_ignore_spaces:w + } +\cs_new_protected_nopar:Npn \xeCJK_ignore_spaces:w + { + \peek_catcode:NTF \c_space_token + { + \xeCJK_if_last_node:nT { CJK } + { \tex_unkern:D \tex_unkern:D { \xeCJK_make_node:n { CJK-space } } } + \peek_catcode_ignore_spaces:NTF \c_math_toggle_token + { \__xeCJK_space_or_xecglue: } + { + \bool_if:nT + { + \token_if_macro_p:N \l_peek_token || + ( \l__xeCJK_reserve_space_bool && + \token_if_other_p:N \l_peek_token ) + } + { \__xeCJK_space_or_xecglue: } + } + } + { + \token_if_math_toggle:NTF \l_peek_token + { \CJKecglue } + { \cs_if_exist:NF \l_peek_token \exp_not:N } + } } -\__xeCJK_inter_class_toks:nnn { CJK } { CJK } { \xeCJK_CJK_and_CJK:N } +\cs_new_eq:NN \xeCJK_ignorespaces: \xeCJK_ignore_spaces:w +\xeCJK_inter_class_toks:nnn { CJK } { CJK } { \xeCJK_CJK_and_CJK:N } \cs_new_protected_nopar:Npn \xeCJK_CJK_and_CJK:N #1 { \CJKglue \CJKsymbol {#1} } -\clist_map_inline:nn { FullLeft, FullRight } +\clist_map_inline:nn { FullLeft , FullRight } { - \__xeCJK_inter_class_toks:nnn { Boundary } {#1} + \xeCJK_inter_class_toks:nnn { Boundary } {#1} { - \c_group_begin_token - \__xeCJK_clear_CJK_toks: + \xeCJK_class_group_begin: + \xeCJK_clear_Boundary_and_CJK_toks: \xeCJK_select_font: \use:c { xeCJK_CJK_and_#1:N } } - \__xeCJK_inter_class_toks:nnn {#1} { CJK } { \CJKsymbol } - \__xeCJK_inter_class_toks:nnn {#1} { Boundary } { \c_group_end_token \tex_ignorespaces:D } } -\clist_map_inline:Nn \g__xeCJK_base_class_clist +\xeCJK_inter_class_toks:nnn { FullLeft } { Boundary } + { \xeCJK_class_group_end: \tex_ignorespaces:D } +\xeCJK_inter_class_toks:nnn { FullRight } { Boundary } + { \xeCJK_class_group_end: \CJKglue \tex_ignorespaces:D } +\xeCJK_inter_class_toks:nnn { FullLeft } { CJK } { \CJKsymbol } +\xeCJK_inter_class_toks:nnn { FullRight } { CJK } { \CJKglue \CJKsymbol } +\seq_map_inline:Nn \g__xeCJK_base_class_seq { \bool_if:nF - { \str_if_eq_x_p:nn {#1} { FullLeft } || \str_if_eq_x_p:nn {#1} { FullRight } } + { \str_if_eq_p:nn {#1} { FullLeft } || \str_if_eq_p:nn {#1} { FullRight } } { - \__xeCJK_pre_inter_class_toks:nnn { FullLeft } {#1} { \xeCJK_no_break: } - \__xeCJK_pre_inter_class_toks:nnn { FullRight } {#1} { \xeCJK_after_FullRight: } + \xeCJK_pre_inter_class_toks:nnn { FullLeft } {#1} { \xeCJK_after_FullLeft: } + \xeCJK_pre_inter_class_toks:nnn { FullRight } {#1} { \xeCJK_after_FullRight: } } } -\clist_map_inline:nn { CJK, FullLeft, FullRight } +\clist_map_inline:nn { CJK , FullLeft , FullRight } { - \clist_map_inline:nn { FullLeft, FullRight } - { \__xeCJK_inter_class_toks:nnc {#1} {##1} { xeCJK_#1_and_##1:N } } + \clist_map_inline:nn { FullLeft , FullRight } + { \xeCJK_inter_class_toks:nnc {#1} {##1} { xeCJK_#1_and_##1:N } } } -\cs_new_protected_nopar:Npn \__xeCJK_punct_rule:n #1 +\cs_new_protected_nopar:Npn \__xeCJK_punct_rule:NN #1#2 { \tex_vrule:D - \@width \dim_eval:c { \l__xeCJK_punct_coor_tl/rule/#1 } - \@depth \c_zero_dim - \@height \c_zero_dim \scan_stop: + width - \__xeCJK_use_punct_dim:nnn { bound } {#1} {#2} + depth \c_zero_dim + height \c_zero_dim \scan_stop: } -\cs_new_protected_nopar:Npn \__xeCJK_punct_glue:n #1 +\cs_new_protected_nopar:Npn \__xeCJK_punct_glue:NN #1#2 { \skip_horizontal:n { - \dim_eval:c { \l__xeCJK_punct_coor_tl/glue/#1 } - \@plus \dim_eval:n { ( \tl_use:c { \l__xeCJK_punct_coor_tl/glue/#1 } ) /4 } - \@minus \dim_eval:n { ( \tl_use:c { \l__xeCJK_punct_coor_tl/glue/#1 } ) /2 } + \__xeCJK_use_punct_dim:nnn { glue } {#1} {#2} + minus \dim_eval:n { ( \__xeCJK_use_punct_dim:nnn { glue } {#1} {#2} ) / \c_two } } } -\cs_new_protected_nopar:Npn \__xeCJK_punct_kern:n #1 - { \tex_kern:D \dim_eval:c { \l__xeCJK_punct_coor_tl/kern/#1 } } -\cs_generate_variant:Nn \dim_eval:n { c } -\cs_new_protected_nopar:Npn \xeCJK_before_FullLeft:N #1 +\cs_new_protected_nopar:Npn \__xeCJK_punct_kern:NN #1#2 + { \tex_kern:D \__xeCJK_use_punct_dim:nnn { kern } {#1} {#2} } +\tl_new:N \g__xeCJK_last_punct_tl +\cs_new_protected_nopar:Npn \xeCJK_after_FullLeft: { - \tl_set:Nx \l__xeCJK_lastpunct_tl {#1} - \__xeCJK_punct_rule:n { l/#1 } - \CJKpunctsymbol {#1} + \xeCJK_no_break: + \__xeCJK_punct_if_middle:NT \g__xeCJK_last_punct_tl + { + \xeCJK_get_punct_bounds:NN \c__xeCJK_left_tl \g__xeCJK_last_punct_tl + \__xeCJK_punct_glue:NN \c__xeCJK_left_tl \g__xeCJK_last_punct_tl + \__xeCJK_punct_rule:NN \c__xeCJK_right_tl \g__xeCJK_last_punct_tl + \xeCJK_no_break: + } } \cs_new_protected_nopar:Npn \xeCJK_after_FullRight: { - \xeCJK_get_punct_bounds:nV { r } \l__xeCJK_lastpunct_tl - \__xeCJK_punct_rule:n { r/\l__xeCJK_lastpunct_tl } - \__xeCJK_punct_glue:n { r/\l__xeCJK_lastpunct_tl } + \xeCJK_get_punct_bounds:NN \c__xeCJK_right_tl \g__xeCJK_last_punct_tl + \__xeCJK_punct_rule:NN \c__xeCJK_right_tl \g__xeCJK_last_punct_tl + \__xeCJK_punct_glue:NN \c__xeCJK_right_tl \g__xeCJK_last_punct_tl } \cs_new_protected_nopar:Npn \xeCJK_CJK_and_FullLeft:N #1 { - \xeCJK_get_punct_bounds:nN { l } {#1} + \xeCJK_get_punct_bounds:NN \c__xeCJK_left_tl {#1} \int_compare:nNnF \etex_lastnodetype:D = \c_one - { \__xeCJK_punct_glue:n { l/#1 } } - \xeCJK_before_FullLeft:N {#1} - \__xeCJK_punct_if_middle:NT {#1} - { - \__xeCJK_punct_rule:n { lr/#1 } - \__xeCJK_punct_glue:n { l/#1 } - } + { \__xeCJK_CJK_FullLeft_glue: \__xeCJK_punct_glue:NN \c__xeCJK_left_tl {#1} } + \tl_gset:Nx \g__xeCJK_last_punct_tl {#1} + \__xeCJK_punct_rule:NN \c__xeCJK_left_tl {#1} + \CJKpunctsymbol {#1} } +\cs_new_protected_nopar:Npn \__xeCJK_CJK_FullLeft_glue: { \CJKglue } \cs_new_protected_nopar:Npn \xeCJK_CJK_and_FullRight:N #1 { - \xeCJK_get_punct_bounds:nN { r } {#1} - \__xeCJK_punct_if_long:NTF {#1} \CJKglue + \xeCJK_get_punct_bounds:NN \c__xeCJK_right_tl {#1} + \__xeCJK_punct_if_long:NTF {#1} + { \CJKglue } { \xeCJK_no_break: \__xeCJK_punct_if_middle:NT {#1} { - \__xeCJK_punct_glue:n { r/#1 } - \__xeCJK_punct_rule:n { lr/#1 } + \__xeCJK_punct_glue:NN \c__xeCJK_right_tl {#1} + \__xeCJK_punct_rule:NN \c__xeCJK_left_tl {#1} } } - \tl_gset:Nx \l__xeCJK_lastpunct_tl {#1} + \tl_gset:Nx \g__xeCJK_last_punct_tl {#1} \CJKpunctsymbol {#1} } \cs_new_protected_nopar:Npn \xeCJK_FullLeft_and_FullLeft:N #1 { \xeCJK_no_break: - \xeCJK_get_punct_bounds:nN { l } {#1} - \xeCJK_calc_kern:VN \l__xeCJK_lastpunct_tl {#1} - \__xeCJK_punct_kern:n { \l__xeCJK_lastpunct_tl - #1 } - \xeCJK_before_FullLeft:N {#1} + \xeCJK_get_punct_bounds:NN \c__xeCJK_left_tl {#1} + \xeCJK_get_punct_kerning:oN \g__xeCJK_last_punct_tl {#1} + \__xeCJK_punct_kern:NN \g__xeCJK_last_punct_tl {#1} + \tl_gset:Nx \g__xeCJK_last_punct_tl {#1} + \CJKpunctsymbol {#1} } \cs_new_protected_nopar:Npn \xeCJK_FullLeft_and_FullRight:N #1 { \xeCJK_no_break: - \xeCJK_get_punct_bounds:nN { r } {#1} - \xeCJK_calc_kern:VN \l__xeCJK_lastpunct_tl {#1} - \__xeCJK_punct_kern:n { \l__xeCJK_lastpunct_tl - #1 } + \xeCJK_get_punct_bounds:NN \c__xeCJK_right_tl {#1} + \xeCJK_get_punct_kerning:oN \g__xeCJK_last_punct_tl {#1} + \__xeCJK_punct_kern:NN \g__xeCJK_last_punct_tl {#1} + \tl_gset:Nx \g__xeCJK_last_punct_tl {#1} \xeCJK_no_break: - \tl_set:Nx \l__xeCJK_lastpunct_tl {#1} \CJKpunctsymbol {#1} } \cs_new_protected_nopar:Npn \xeCJK_FullRight_and_FullLeft:N #1 { - \__xeCJK_punct_rule:n { r/\l__xeCJK_lastpunct_tl } - \xeCJK_get_punct_bounds:nN { l } {#1} - \xeCJK_calc_kern:VN \l__xeCJK_lastpunct_tl {#1} - \__xeCJK_punct_kern:n { \l__xeCJK_lastpunct_tl - #1 } - \__xeCJK_punct_nobreak: - \xeCJK_before_FullLeft:N {#1} - } + \xeCJK_get_punct_bounds:NN \c__xeCJK_left_tl {#1} + \xeCJK_get_punct_kerning:oN \g__xeCJK_last_punct_tl {#1} + \__xeCJK_punct_kern:NN \g__xeCJK_last_punct_tl {#1} + \tl_gset:Nx \g__xeCJK_last_punct_tl {#1} + \__xeCJK_punct_break: + \CJKpunctsymbol {#1} + } \cs_new_protected_nopar:Npn \xeCJK_FullRight_and_FullRight:N #1 { - \__xeCJK_punct_rule:n { r/\l__xeCJK_lastpunct_tl } - \xeCJK_get_punct_bounds:nN { r } {#1} - \xeCJK_calc_kern:VN \l__xeCJK_lastpunct_tl {#1} - \__xeCJK_punct_kern:n { \l__xeCJK_lastpunct_tl - #1 } + \xeCJK_get_punct_bounds:NN \c__xeCJK_right_tl {#1} + \xeCJK_get_punct_kerning:oN \g__xeCJK_last_punct_tl {#1} + \__xeCJK_punct_kern:NN \g__xeCJK_last_punct_tl {#1} + \tl_gset:Nx \g__xeCJK_last_punct_tl {#1} \xeCJK_no_break: - \tl_set:Nx \l__xeCJK_lastpunct_tl {#1} \CJKpunctsymbol {#1} } - \prg_new_conditional:Npnn \xeCJK_if_last_node:n #1 { p , T , F , TF } - { - \if_dim:w \dim_use:c { c__xeCJK_#1_node_dim } = \tex_lastkern:D - \prg_return_true: \else: \prg_return_false: \fi: - } -\cs_new_protected_nopar:Npn \xeCJK_def_node:nn #1#2 - { - \dim_if_exist:cTF { c__xeCJK_#1_node_dim } - { \dim_gset:cn } { \dim_const:cn } - { c__xeCJK_#1_node_dim } {#2} - } -\cs_new_protected_nopar:Npn \xeCJK_make_node:n #1 - { - \tex_kern:D - \dim_use:c { c__xeCJK_#1_node_dim } - \tex_kern:D \dim_use:c { c__xeCJK_#1_node_dim } - } -\xeCJK_def_node:nn { CJK } { 11 sp } -\xeCJK_def_node:nn { CJK_space } { 12 sp } -\xeCJK_def_node:nn { default } { 13 sp } -\xeCJK_def_node:nn { default_space } { 14 sp } -\xeCJK_def_node:nn { default_itcorr } { 15 sp } -\keys_define:nn { xeCJK / options } - { CJKglue .code:n = { \cs_set_protected:Npn \CJKglue {#1} } } \keys_define:nn { xeCJK / options } { - CJKecglue .code:n = - { - \cs_set_protected:Npn \CJKecglue {#1} - \settowidth \l__xeCJK_ecglue_dim \CJKecglue - }, - xCJKecglue .choice:, - xCJKecglue / true .code:n = - { - \bool_set_true:N \l__xeCJK_xecglue_bool - \cs_set_eq:NN \__xeCJK_space_or_xecglue: \CJKecglue - }, - xCJKecglue / false .code:n = - { - \bool_set_false:N \l__xeCJK_xecglue_bool - \cs_set_eq:NN \__xeCJK_space_or_xecglue: \c_space_token - }, - xCJKecglue / unknown .code:n = - { - \bool_set_true:N \l__xeCJK_xecglue_bool - \cs_set_protected:Npn \CJKecglue {#1} - \settowidth \l__xeCJK_ecglue_dim \CJKecglue - \cs_set_eq:NN \__xeCJK_space_or_xecglue: \CJKecglue - }, - xCJKecglue .default:n = { true } , - } -\dim_new:N \l__xeCJK_ecglue_dim -\bool_new:N \l__xeCJK_xecglue_bool -\keys_define:nn { xeCJK / options } - { - CJKspace .choice:, - CJKspace / true .code:n = { \CJKspace }, - CJKspace / false .code:n = { \CJKnospace }, - CJKspace .default:n = { true }, - space .meta:n = { CJKspace = true }, - nospace .meta:n = { CJKspace = false }, - } -\NewDocumentCommand \CJKspace { } - { - \bool_set_true:N \l__xeCJK_space_bool - \cs_set_eq:NN \xeCJK_ignorespaces: \__xeCJK_peek_math: - } -\NewDocumentCommand \CJKnospace { } - { - \bool_set_false:N \l__xeCJK_space_bool - \cs_set_eq:NN \xeCJK_ignorespaces: \__xeCJK_ignore_spaces: - } -\cs_new_protected_nopar:Npn \__xeCJK_ignore_spaces: - { - \peek_catcode:NTF \c_space_token - { - \xeCJK_if_last_node:nT { CJK } - { \tex_unkern:D \tex_unkern:D { \xeCJK_make_node:n { CJK_space } } } - \xeCJK_peek_catcode_ignore_spaces:NTF \c_math_toggle_token - { \__xeCJK_space_or_xecglue: } - { - \bool_if:nT - { - \xeCJK_if_outer_macro_p:c { l_peek_token } || - \token_if_cs_p:c { l_peek_token } - } - { \__xeCJK_space_or_xecglue: } - } - } - { - \xeCJK_if_outer_macro:cF { l_peek_token } - { - \token_if_math_toggle:cTF { l_peek_token } \CJKecglue - { \cs_if_exist:cF { l_peek_token } \exp_not:N } - } - } - } -\cs_new_protected_nopar:Npn \__xeCJK_peek_math: - { - \peek_catcode:NTF \c_space_token - { - \xeCJK_if_last_node:nT { CJK } - { \tex_unkern:D \tex_unkern:D { \xeCJK_make_node:n { CJK_space } } } - \xeCJK_peek_catcode_ignore_spaces:NF \c_space_token - { \__xeCJK_space_or_xecglue: } - } - { - \xeCJK_if_outer_macro:cF { l_peek_token } - { - \token_if_math_toggle:cTF { l_peek_token } \CJKecglue - { \cs_if_exist:cF { l_peek_token } \exp_not:N } - } - } - } -\keys_define:nn { xeCJK / options } - { - CheckSingle .choice:, - CheckSingle / true .code:n = { \xeCJKenablechecksingle }, - CheckSingle / false .code:n = { \xeCJKdisablechecksingle }, - CheckSingle .default:n = { true }, - CJKchecksingle .meta:n = { CheckSingle = true } , + CheckSingle .choice: , + CheckSingle / true .code:n = { \xeCJKenablechecksingle } , + CheckSingle / false .code:n = { \xeCJKdisablechecksingle } , + CheckSingle .default:n = { true } , + CJKchecksingle .meta:n = { CheckSingle = true } } -\bool_new:N \l__xeCJK_checksingle_bool +\bool_new:N \l__xeCJK_check_single_bool \NewDocumentCommand \xeCJKenablechecksingle { } { - \bool_if:NF \l__xeCJK_checksingle_bool + \bool_if:NF \l__xeCJK_check_single_bool { - \bool_set_true:N \l__xeCJK_checksingle_bool - \cs_set_eq:NN \__xeCJK_checksingle_save_CJKsymbol:N \xeCJK_CJK_and_CJK:N - \cs_set_eq:NN \xeCJK_CJK_and_CJK:N \xeCJK_checksingle:N + \bool_set_true:N \l__xeCJK_check_single_bool + \cs_set_eq:NN \__xeCJK_check_single_save:N \xeCJK_CJK_and_CJK:N + \cs_set_eq:NN \xeCJK_CJK_and_CJK:N \xeCJK_check_single:Nw } } \NewDocumentCommand \xeCJKdisablechecksingle { } { - \bool_if:NT \l__xeCJK_checksingle_bool + \bool_if:NT \l__xeCJK_check_single_bool { - \bool_set_false:N \l__xeCJK_checksingle_bool - \cs_set_eq:NN \xeCJK_CJK_and_CJK:N \__xeCJK_checksingle_save_CJKsymbol:N + \bool_set_false:N \l__xeCJK_check_single_bool + \cs_set_eq:NN \xeCJK_CJK_and_CJK:N \__xeCJK_check_single_save:N } } -\cs_new_protected_nopar:Npn \xeCJK_checksingle:N #1 +\cs_new_protected_nopar:Npn \xeCJK_check_single:Nw #1 { \peek_catcode:NTF \c_catcode_other_token - { \xeCJK_checksingle:NN {#1} } + { \xeCJK_check_single:NNw {#1} } { \bool_if:nTF { - ! ( \xeCJK_if_outer_macro_p:c { l_peek_token } ) && - \xeCJK_if_blank_x_p:n { \token_get_arg_spec:c { l_peek_token } } && - \exp_args:NNc \exp_args:No \tl_if_single_token_p:n { l_peek_token } && - \exp_args:NNc \exp_after:wN \token_if_other_p:N { l_peek_token } + \xeCJK_if_blank_x_p:n { \token_get_arg_spec:N \l_peek_token } && + \exp_args:No \tl_if_single_token_p:n \l_peek_token && + \exp_after:wN \token_if_other_p:N \l_peek_token } - { \xeCJK_checksingle:NN {#1} } - { \__xeCJK_checksingle_save_CJKsymbol:N {#1} } + { \xeCJK_check_single:NNw {#1} } + { \__xeCJK_check_single_save:N {#1} } } } -\cs_new_protected_nopar:Npn \xeCJK_checksingle:NN #1#2 +\cs_new_protected_nopar:Npn \xeCJK_check_single:NNw #1#2 { \peek_catcode:NTF \c_catcode_other_token - { \__xeCJK_checksingle_save_CJKsymbol:N {#1} #2 } + { \__xeCJK_check_single_save:N {#1} #2 } { \bool_if:nTF { - ! ( \xeCJK_if_outer_macro_p:c { l_peek_token } ) && - ( \token_if_space_p:c { l_peek_token } || - \token_if_math_toggle_p:c { l_peek_token } || - \token_if_cs_p:c { l_peek_token } ) + \token_if_space_p:N \l_peek_token || + \token_if_math_toggle_p:N \l_peek_token || + \token_if_cs_p:N \l_peek_token } { - \bool_if:nTF { \token_if_space_p:c { l_peek_token } } + \bool_if:nTF { \token_if_space_p:N \l_peek_token } { - \xeCJK_peek_catcode_ignore_spaces:NTF \c_catcode_other_token - { \__xeCJK_checksingle_save_CJKsymbol:N {#1} #2 \c_space_token } + \peek_catcode_ignore_spaces:NTF \c_catcode_other_token + { \__xeCJK_check_single_save:N {#1} #2 \c_space_token } { \bool_if:nTF { - ! ( \xeCJK_if_outer_macro_p:c { l_peek_token } ) && - ( \token_if_math_toggle_p:c { l_peek_token } || - \token_if_cs_p:c { l_peek_token } ) + \token_if_math_toggle_p:N \l_peek_token || + \token_if_cs_p:N \l_peek_token } - { \xeCJK_checksingle:NNN {#1} {#2} \c_space_token } - { \__xeCJK_checksingle_save_CJKsymbol:N {#1} #2 \c_space_token } + { \xeCJK_check_single:NNNw {#1} {#2} \c_space_token } + { \__xeCJK_check_single_save:N {#1} #2 \c_space_token } } } - { \xeCJK_checksingle:NNN {#1} {#2} { } } + { \xeCJK_check_single:NNNw {#1} {#2} { } } } - { \__xeCJK_checksingle_save_CJKsymbol:N {#1} #2 } + { \__xeCJK_check_single_save:N {#1} #2 } } } -\cs_new_protected_nopar:Npn \xeCJK_checksingle:NNN #1#2#3 +\cs_new_protected_nopar:Npn \xeCJK_check_single:NNNw #1#2#3 { \bool_if:nTF { @@ -806,30 +808,30 @@ \token_if_eq_meaning_p:NN \l_peek_token \[ % \] } { \CJKsymbol {#1} \xeCJK_no_break: #2 } - { \xeCJK_checksingle_env:NNN {#1} {#2} {#3} } + { \xeCJK_check_single_env:NNNw {#1} {#2} {#3} } } -\cs_new_protected_nopar:Npn \xeCJK_checksingle_env:NNN #1#2#3 +\cs_new_protected_nopar:Npn \xeCJK_check_single_env:NNNw #1#2#3 { \peek_catcode_remove:NTF \c_math_toggle_token { \peek_catcode:NTF \c_math_toggle_token { \CJKsymbol {#1} \xeCJK_no_break: #2 \c_math_toggle_token } - { \__xeCJK_checksingle_save_CJKsymbol:N {#1} #2#3 \c_math_toggle_token } + { \__xeCJK_check_single_save:N {#1} #2#3 \c_math_toggle_token } } { \peek_meaning_remove:NTF \begin - { \xeCJK_checksingle_env:NNNNn {#1} {#2} {#3} \begin } + { \xeCJK_check_single_env:NNNNn {#1} {#2} {#3} \begin } { \peek_meaning_remove:NTF \end - { \xeCJK_checksingle_env:NNNNn {#1} {#2} {#3} \end } - { \__xeCJK_checksingle_save_CJKsymbol:N {#1} #2#3 } + { \xeCJK_check_single_env:NNNNn {#1} {#2} {#3} \end } + { \__xeCJK_check_single_save:N {#1} #2#3 } } } } -\cs_new_protected_nopar:Npn \xeCJK_checksingle_env:NNNNn #1#2#3#4#5 +\cs_new_protected_nopar:Npn \xeCJK_check_single_env:NNNNn #1#2#3#4#5 { \clist_if_in:NnTF \g__xeCJK_inline_env_clist {#5} - { \__xeCJK_checksingle_save_CJKsymbol:N {#1} #2#3 } + { \__xeCJK_check_single_save:N {#1} #2#3 } { \CJKsymbol {#1} \xeCJK_no_break: #2 } \scan_stop: #4 {#5} } @@ -840,33 +842,19 @@ { \clist_gput_right:Nx \g__xeCJK_inline_env_clist {#1} \clist_gremove_duplicates:N \g__xeCJK_inline_env_clist - }, + } , InlineEnv- .code:n = { \clist_map_inline:xn {#1} { \clist_gremove_all:Nn \g__xeCJK_inline_env_clist {##1} } - }, - } -\cs_generate_variant:Nn \token_if_cs_p:N { c } -\cs_generate_variant:Nn \token_if_space_p:N { c } -\cs_generate_variant:Nn \token_get_arg_spec:N { c } -\cs_generate_variant:Nn \token_if_math_toggle_p:N { c } -\cs_generate_variant:Nn \token_if_math_toggle:NTF { c } -\tl_new:N \__xeCJK_UL_subclass_patch_tl -\clist_new:N \g__xeCJK_CJK_subclass_clist -\cs_new_protected_nopar:Npn \__xeCJK_erase_CJKsymbol: - { - \cs_gset_eq:NN \CJKsymbol_Block \CJKsymbol - \cs_gset_eq:NN \CJKsymbol \prg_do_nothing: - } -\cs_new_protected_nopar:Npn \__xeCJK_restore_CJKsymbol: - { - \cs_gset_eq:NN \CJKsymbol \CJKsymbol_Block - \CJKsymbol + } } -\NewDocumentCommand \xeCJKDeclareSubCJKBlock { s m m } +\cs_generate_variant:Nn \clist_map_inline:nn { x } +\seq_new:N \g__xeCJK_CJK_sub_class_seq +\NewDocumentCommand \xeCJKDeclareSubCJKBlock + { s > { \TrimSpaces } m > { \TrimSpaces } m } { - \xeCJKDeclareSubCharClass { CJK } {#2} {#3} + \xeCJK_declare_sub_char_class:nxx { CJK } {#2} {#3} \IfBooleanT {#1} { \xeCJKResetPunctClass } } \@onlypreamble \xeCJKDeclareSubCJKBlock @@ -876,7 +864,7 @@ \bool_if:NF \l__xeCJK_sub_cancel_bool { \bool_set_true:N \l__xeCJK_sub_cancel_bool - \__xeCJK_sub_restore_or_cancel:n {#2} + \__xeCJK_sub_restore_or_cancel:x {#2} \IfBooleanT {#1} { \xeCJKResetPunctClass } } } @@ -885,482 +873,620 @@ \bool_if:NT \l__xeCJK_sub_cancel_bool { \bool_set_false:N \l__xeCJK_sub_cancel_bool - \__xeCJK_sub_restore_or_cancel:n {#2} + \__xeCJK_sub_restore_or_cancel:x {#2} \IfBooleanT {#1} { \xeCJKResetPunctClass } } } \cs_new_protected_nopar:Npn \__xeCJK_sub_restore_or_cancel:n #1 { - \clist_map_inline:xn {#1} + \clist_map_inline:nn {#1} { \int_if_exist:cTF { c__xeCJK_ CJK/##1 _class_int } { - \__xeCJK_declare_char_class:nn + \xeCJK_declare_char_class:nx { CJK \bool_if:NF \l__xeCJK_sub_cancel_bool { /##1 } } { \tl_use:c { g__xeCJK_CJK/##1_range_clist } } } { \__xeCJK_error:nx { SubBlock-undefined } {##1} } } } +\cs_generate_variant:Nn \__xeCJK_sub_restore_or_cancel:n { x } \__xeCJK_msg_new:nn { SubBlock-undefined } { The~CJK~sub~block~'#1'~is~undefined.\\\\ Try~to~use~\token_to_str:N \xeCJKDeclareSubCJKBlock \ to~declare~it. } -\NewDocumentCommand \xeCJKDeclareSubCharClass - { > { \TrimSpaces } m > { \TrimSpaces } m m } +\cs_new_protected_nopar:Npn \xeCJK_declare_sub_char_class:nnn #1#2#3 { \int_if_exist:cF { c__xeCJK_ #1/#2 _class_int } { - \__xeCJK_new_class:n { #1/#2 } + \xeCJK_new_class:n { #1/#2 } \__xeCJK_set_sub_class_toks:nn {#1} {#2} \__xeCJK_new_sub_key:n {#2} - \__xeCJK_UL_subclass_patch:nn {#1} {#2} } - \__xeCJK_declare_char_class:nn { #1/#2 } {#3} + \xeCJK_declare_char_class:nn { #1/#2 } {#3} } -\@onlypreamble \xeCJKDeclareSubCharClass +\cs_generate_variant:Nn \xeCJK_declare_sub_char_class:nnn { nxx } \cs_new_protected_nopar:Npn \__xeCJK_set_sub_class_toks:nn #1#2 { - \clist_map_inline:Nn \g__xeCJK_base_class_clist + \seq_map_inline:Nn \g__xeCJK_base_class_seq { - \__xeCJK_copy_inter_class_toks:nnnn { #1/#2 } {##1} {#1} {##1} - \__xeCJK_copy_inter_class_toks:nnnn {##1} { #1/#2 } {##1} {#1} - \str_if_eq_x:nnTF {##1} { CJK } + \xeCJK_copy_inter_class_toks:nnnn { #1/#2 } {##1} {#1} {##1} + \xeCJK_copy_inter_class_toks:nnnn {##1} { #1/#2 } {##1} {#1} + \str_if_eq:nnTF {##1} { CJK } { - \__xeCJK_pre_inter_class_toks:nnn {##1} { #1/#2 } + \xeCJK_pre_inter_class_toks:nnn {##1} { #1/#2 } { \__xeCJK_switch_font:nn {#1} {#2} } } { - \__xeCJK_pre_inter_class_toks:nnn {##1} { #1/#2 } - { \__xeCJK_erase_CJKsymbol: } - \__xeCJK_app_inter_class_toks:nnn {##1} { #1/#2 } - { \__xeCJK_switch_font:nn {#1} {#2} \__xeCJK_restore_CJKsymbol: } + \xeCJK_replace_inter_class_toks:nnnn {##1} { #1/#2 } + { \CJKsymbol } + { \__xeCJK_switch_font:nn {#1} {#2} \CJKsymbol } } } - \__xeCJK_copy_inter_class_toks:nnnn { #1/#2 } { #1/#2 } {#1} {#1} - \clist_if_empty:NF \g__xeCJK_CJK_subclass_clist + \xeCJK_copy_inter_class_toks:nnnn { #1/#2 } { #1/#2 } {#1} {#1} + \seq_map_inline:Nn \g__xeCJK_CJK_sub_class_seq { - \clist_map_inline:Nn \g__xeCJK_CJK_subclass_clist - { - \__xeCJK_copy_inter_class_toks:nnnn { #1/#2 } { #1/##1 } {#1} {#1} - \__xeCJK_copy_inter_class_toks:nnnn { #1/##1 } { #1/#2 } {#1} {#1} - \__xeCJK_pre_inter_class_toks:nnn { #1/#2 } { #1/##1 } - { \__xeCJK_switch_font:nn {#2} {##1} } - \__xeCJK_pre_inter_class_toks:nnn { #1/##1 } { #1/#2 } - { \__xeCJK_switch_font:nn {##1} {#2} } - } + \xeCJK_copy_inter_class_toks:nnnn { #1/#2 } { #1/##1 } {#1} {#1} + \xeCJK_copy_inter_class_toks:nnnn { #1/##1 } { #1/#2 } {#1} {#1} + \xeCJK_pre_inter_class_toks:nnn { #1/#2 } { #1/##1 } + { \__xeCJK_switch_font:nn {#2} {##1} } + \xeCJK_pre_inter_class_toks:nnn { #1/##1 } { #1/#2 } + { \__xeCJK_switch_font:nn {##1} {#2} } } - \clist_gput_right:Nn \g__xeCJK_CJK_subclass_clist {#2} + \seq_gput_right:Nn \g__xeCJK_CJK_sub_class_seq {#2} \__xeCJK_save_CJK_class:n { #1/#2 } - \clist_map_inline:nn { CJK, FullLeft, FullRight } + \clist_map_inline:nn { CJK , FullLeft , FullRight } { - \__xeCJK_pre_inter_class_toks:nnn { #1/#2 } {##1} + \xeCJK_pre_inter_class_toks:nnn { #1/#2 } {##1} { \__xeCJK_switch_font:nn {#2} {#1} } } } -\cs_new_protected_nopar:Npn \__xeCJK_UL_subclass_patch:nn #1#2 +\__xeCJK_msg_new:nn { XeTeX-too-old } { - \tl_put_right:Nn \__xeCJK_UL_subclass_patch_tl - { - \clist_map_inline:nn { Default, HalfLeft, HalfRight } - { - \str_if_eq_x:nnTF {##1} { HalfLeft } - { \__xeCJK_inter_class_toks:nnn {#1} { #1/#2 } { \CJKecglue \CJKsymbol } } - { \__xeCJK_inter_class_toks:nnn {#1} { #1/#2 } { \CJKsymbol } } - \__xeCJK_inter_class_toks:nnn { Boundary } { #1/#2 } - { - \__xeCJK_erase_CJKsymbol: - \xeCJK_Boundary_and_CJK: - \__xeCJK_switch_font:nn {#1} {#2} - \__xeCJK_restore_CJKsymbol: - } - } - } - } -\clist_new:N \g__xeCJK_punctstyle_clist -\clist_set:Nn \g__xeCJK_punctstyle_clist - { CCT , halfwidth , fullwidth , marginkerning , mixedwidth , plain } -\clist_map_inline:Nn \g__xeCJK_punctstyle_clist - { \tl_const:cn { c__xeCJK_ps_#1_tl } {#1} } -\cs_generate_variant:Nn \keys_define:nn { nx } -\keys_define:nn { xeCJK / options } - { - PunctStyle .choice_code:n = - { - \tl_set:Nx \l_xeCJK_punctstyle_tl { \l_keys_choice_tl } - \tl_if_eq:NNT \l_xeCJK_punctstyle_tl \c__xeCJK_ps_plain_tl - { \xeCJKallowbreakbetweenpuncts } - }, - } -\keys_define:nx { xeCJK / options } - { PunctStyle .generate_choices:n = { \exp_not:V \g__xeCJK_punctstyle_clist } } -\keys_define:nn { xeCJK / options } - { - PunctStyle / banjiao .meta:n = { PunctStyle = halfwidth }, - PunctStyle / quanjiao .meta:n = { PunctStyle = fullwidth }, - PunctStyle / kaiming .meta:n = { PunctStyle = mixedwidth }, - PunctStyle / hangmobanjiao .meta:n = { PunctStyle = marginkerning }, - PunctStyle / unknown .code:n = - { \__xeCJK_error:nx { PunctStyle-undefined } \l_keys_value_tl }, + \token_to_str:N \XeTeXglyphbounds \ is~not~defined.\\ + CJK~punctuation~kerning~will~not~be~available.\\\\ + You~have~to~update~XeTeX~to~the~version~0.9995.0~or~later. } -\__xeCJK_msg_new:nn { PunctStyle-undefined } +\cs_if_exist:NF \XeTeXglyphbounds { - Punctstyle~"#1"~is~not~available. \\\\ - You~can~only~use~one~of\\\\ - "\g__xeCJK_punctstyle_clist".\\ + \__xeCJK_error:n { XeTeX-too-old } + \__xeCJK_after_end_preamble:n { \xeCJKsetup { PunctStyle = plain } } } +\NewDocumentCommand \xeCJKsetwidth { m m } + { \tl_map_inline:xn {#1} { \tl_gset:cn { g__xeCJK_punct_width/##1/tl } {#2} } } +\NewDocumentCommand \xeCJKsetkern { m m m } + { \tl_gset:cn { g__xeCJK_punct/kern/#1/#2/tl } {#3} } +\tl_const:Nn \c__xeCJK_left_tl { left } +\tl_const:Nn \c__xeCJK_right_tl { right } \keys_define:nn { xeCJK / options } { - AllowBreakBetweenPuncts .choice:, - AllowBreakBetweenPuncts / true .code:n = { \xeCJKallowbreakbetweenpuncts }, - AllowBreakBetweenPuncts / false .code:n = { \xeCJKnobreakbetweenpuncts }, - AllowBreakBetweenPuncts .default:n = { true }, - KaiMingPunct .code:n = { \__xeCJK_set_special_punct:nn { mixedwidth } {#1} }, - KaiMingPunct+ .code:n = { \__xeCJK_add_special_punct:nn { mixedwidth } {#1} }, - KaiMingPunct- .code:n = { \__xeCJK_sub_special_punct:nn { mixedwidth } {#1} }, - LongPunct .code:n = { \__xeCJK_set_special_punct:nn { long } {#1} }, - LongPunct+ .code:n = { \__xeCJK_add_special_punct:nn { long } {#1} }, - LongPunct- .code:n = { \__xeCJK_sub_special_punct:nn { long } {#1} }, - MiddlePunct+ .code:n = { \__xeCJK_add_special_punct:nn { middle } {#1} }, - MiddlePunct .code:n = { \__xeCJK_set_special_punct:nn { middle } {#1} }, - MiddlePunct- .code:n = { \__xeCJK_sub_special_punct:nn { middle } {#1} }, - PunctWidth .tl_gset:N = \g__xeCJK_punct_width_tl , - } -\NewDocumentCommand \xeCJKallowbreakbetweenpuncts { } - { \cs_set_eq:NN \__xeCJK_punct_nobreak: \__xeCJK_zero_glue: } -\NewDocumentCommand \xeCJKnobreakbetweenpuncts { } - { \cs_set_eq:NN \__xeCJK_punct_nobreak: \xeCJK_no_break: } -\cs_new_protected_nopar:Npn \__xeCJK_zero_glue: { \skip_horizontal:N \c_zero_skip } -\clist_set:Nn \g__xeCJK_special_ps_clist { mixedwidth , long , middle } -\clist_map_inline:Nn \g__xeCJK_special_ps_clist - { - \tl_new:c { l__xeCJK_#1_punct_tl } - \prop_new:c { l__xeCJK_#1_punct_prop } - } + AllowBreakBetweenPuncts .choice: , + AllowBreakBetweenPuncts / true .code:n = + { \cs_set_eq:NN \__xeCJK_punct_break: \xeCJK_allow_break: } , + AllowBreakBetweenPuncts / false .code:n = + { \cs_set_eq:NN \__xeCJK_punct_break: \xeCJK_no_break: } , + AllowBreakBetweenPuncts .default:n = { true } , + KaiMingPunct .code:n = { \__xeCJK_set_special_punct:nn { mixed_width } {#1} } , + KaiMingPunct+ .code:n = { \__xeCJK_add_special_punct:nn { mixed_width } {#1} } , + KaiMingPunct- .code:n = { \__xeCJK_sub_special_punct:nn { mixed_width } {#1} } , + LongPunct .code:n = { \__xeCJK_set_special_punct:nn { long } {#1} } , + LongPunct+ .code:n = { \__xeCJK_add_special_punct:nn { long } {#1} } , + LongPunct- .code:n = { \__xeCJK_sub_special_punct:nn { long } {#1} } , + MiddlePunct .code:n = { \__xeCJK_set_special_punct:nn { middle } {#1} } , + MiddlePunct+ .code:n = { \__xeCJK_add_special_punct:nn { middle } {#1} } , + MiddlePunct- .code:n = { \__xeCJK_sub_special_punct:nn { middle } {#1} } , + PunctWidth .tl_gset:N = \g__xeCJK_punct_width_tl + } +\clist_new:N \g__xeCJK_special_punct_clist +\clist_gset:Nn \g__xeCJK_special_punct_clist { mixed_width , long , middle } +\cs_new_nopar:Npn \__xeCJK_special_punct_seq:n #1 { g__xeCJK_special_punct_#1_seq } +\cs_new_nopar:Npn \__xeCJK_special_punct_tl:nN #1#2 { g__xeCJK_special_punct_#1_#2_tl } +\clist_map_inline:Nn \g__xeCJK_special_punct_clist + { \seq_new:c { \__xeCJK_special_punct_seq:n {#1} } } \cs_new_protected_nopar:Npn \__xeCJK_set_special_punct:nn #1#2 { - \tl_set:cx { l__xeCJK_#1_punct_tl } {#2} - \prop_clear:c { l__xeCJK_#1_punct_prop } - \tl_map_inline:cn { l__xeCJK_#1_punct_tl } - { \prop_put:cnn { l__xeCJK_#1_punct_prop } {##1} { } } + \seq_map_inline:cn { \__xeCJK_special_punct_seq:n {#1} } + { \cs_undefine:c { \__xeCJK_special_punct_tl:nN {#1} {##1} } } + \seq_gclear:c { \__xeCJK_special_punct_seq:n {#1} } + \tl_map_inline:xn {#2} + { + \tl_new:c { \__xeCJK_special_punct_tl:nN {#1} {##1} } + \seq_gput_right:cn { \__xeCJK_special_punct_seq:n {#1} } {##1} + } } \cs_new_protected_nopar:Npn \__xeCJK_add_special_punct:nn #1#2 { - \tl_put_right:cx { l__xeCJK_#1_punct_tl } {#2} - \tl_map_inline:cn { l__xeCJK_#1_punct_tl } - { \prop_put:cnn { l__xeCJK_#1_punct_prop } {##1} { } } + \tl_map_inline:xn {#2} + { + \seq_if_in:cnF { \__xeCJK_special_punct_seq:n {#1} } {##1} + { + \tl_new:c { \__xeCJK_special_punct_tl:nN {#1} {##1} } + \seq_gput_right:cn { \__xeCJK_special_punct_seq:n {#1} } {##1} + } + } } \cs_new_protected_nopar:Npn \__xeCJK_sub_special_punct:nn #1#2 { \tl_map_inline:xn {#2} { - \tl_remove_all:cn { l__xeCJK_#1_punct_tl } {##1} - \prop_remove:cn { l__xeCJK_#1_punct_prop } {##1} + \cs_undefine:c { \__xeCJK_special_punct_tl:nN {#1} {##1} } + \seq_gremove_all:cn { \__xeCJK_special_punct_seq:n {#1} } {##1} } } -\cs_generate_variant:Nn \tl_map_inline:nn { x } -\cs_generate_variant:Nn \dim_set:Nn { Nc } -\cs_generate_variant:Nn \dim_add:Nn { Nc } -\cs_generate_variant:Nn \dim_min:nn { cc } -\cs_new_protected_nopar:Npn \xeCJK_dim_set_max:Nn #1#2 - { \dim_set:Nn #1 { \dim_max:nn {#1} {#2} } } -\cs_new_protected_nopar:Npn \xeCJK_dim_set_min:Nn #1#2 - { \dim_set:Nn #1 { \dim_min:nn {#1} {#2} } } -\tl_set:Nn \l__xeCJK_punct_coor_tl { \l_xeCJK_font_coor_tl/\l_xeCJK_punctstyle_tl } -\cs_new_protected_nopar:Npn \xeCJK_get_punct_bounds:nN #1#2 - { - \tl_if_exist:cF { \l__xeCJK_punct_coor_tl/rule/#1/#2 } - { - \tl_if_eq:NNTF \l_xeCJK_punctstyle_tl \c__xeCJK_ps_plain_tl +\prg_new_conditional:Npnn \__xeCJK_punct_if_right:N #1 { p , T , F , TF } + { + \if_int_compare:w \xeCJK_value_class:n {`#1} = \xeCJK_class_num:n { FullRight } + \prg_return_true: \else: \prg_return_false: \fi: + } +\cs_generate_variant:Nn \prg_new_conditional:Npnn { c } +\clist_map_inline:Nn \g__xeCJK_special_punct_clist + { + \prg_new_conditional:cpnn { __xeCJK_punct_if_#1:N } ##1 { p , T , F , TF } + { + \if_cs_exist:w \__xeCJK_special_punct_tl:nN {#1} {##1} \cs_end: + \prg_return_true: \else: \prg_return_false: \fi: + } + } +\cs_new_nopar:Npn \__xeCJK_punct_dim_csname:nn #1#2 + { g__\l_xeCJK_current_font_tl/\l_xeCJK_punct_style_tl/#1/#2/tl } +\cs_new_nopar:Npn \__xeCJK_punct_dim_csname:nnn + { \__xeCJK_punct_dim_csname:nnnn { \l_xeCJK_punct_style_tl } } +\cs_new_nopar:Npn \__xeCJK_punct_dim_csname:nnnn #1#2#3#4 + { g__\l_xeCJK_current_font_tl/#1/#2/#3/#4/tl } +\cs_new_nopar:Npn \__xeCJK_use_punct_dim:nn #1#2 + { \tl_use:c { \__xeCJK_punct_dim_csname:nn {#1} {#2} } } +\cs_new_nopar:Npn \__xeCJK_use_punct_dim:nnn #1#2#3 + { \tl_use:c { \__xeCJK_punct_dim_csname:nnn {#1} {#2} {#3} } } +\cs_new_protected_nopar:Npn \__xeCJK_gset_punct_dim:nnx #1#2#3 + { \tl_gset:cx { \__xeCJK_punct_dim_csname:nn {#1} {#2} } {#3} } +\cs_new_protected_nopar:Npn \__xeCJK_gset_punct_dim:nnnx #1#2#3#4 + { \tl_gset:cx { \__xeCJK_punct_dim_csname:nnn {#1} {#2} {#3} } {#4} } +\cs_new_protected_nopar:Npn \__xeCJK_gset_punct_dim:nnnnx #1#2#3#4#5 + { \tl_gset:cx { \__xeCJK_punct_dim_csname:nnnn {#1} {#2} {#3} {#4} } {#5} } +\DeclareObjectType { xeCJK / punctuation } { 3 } +\DeclareTemplateInterface { xeCJK / punctuation } { basic } { 3 } + { + enabled-global-setting : boolean = true , + fixed-punct-width : length = \c_max_dim , + fixed-punct-ratio : real = \c_one_fp , + mixed-punct-width : length = \KeyValue { fixed-punct-width } , + mixed-punct-ratio : real = \KeyValue { fixed-punct-ratio } , + middle-punct-width : length = \KeyValue { fixed-punct-width } , + middle-punct-ratio : real = \KeyValue { fixed-punct-ratio } , + fixed-margin-width : length = \c_max_dim , + fixed-margin-ratio : real = \c_one_fp , + mixed-margin-width : length = \KeyValue { fixed-margin-width } , + mixed-margin-ratio : real = \KeyValue { fixed-margin-ratio } , + middle-margin-width : length = \KeyValue { fixed-margin-width } , + middle-margin-ratio : real = \KeyValue { fixed-margin-ratio } , + add-min-bound-to-margin : boolean = false , + optimize-margin : boolean = false , + margin-minimum : length = \c_zero_dim , + enabled-kerning : boolean = true , + min-bound-to-kerning : boolean = false , + kerning-total-width : length = \c_max_dim , + kerning-total-ratio : real = 0.75 , + optimize-kerning : boolean = false , + same-align-margin : length = \c_max_dim , + same-align-ratio : real = \c_zero_fp , + different-align-margin : length = \c_max_dim , + different-align-ratio : real = \c_zero_fp , + kerning-margin-width : length = \c_max_dim , + kerning-margin-ratio : real = \c_one_fp , + kerning-margin-minimum : length = \c_zero_dim + } +\DeclareTemplateCode { xeCJK / punctuation } { basic } { 3 } + { + enabled-global-setting = \l__xeCJK_enabled_global_setting_bool , + fixed-punct-width = \l__xeCJK_fixed_punct_width_dim , + fixed-punct-ratio = \l__xeCJK_fixed_punct_ratio_fp , + mixed-punct-width = \l__xeCJK_mixed_punct_width_dim , + mixed-punct-ratio = \l__xeCJK_mixed_punct_ratio_fp , + middle-punct-width = \l__xeCJK_middle_punct_width_dim , + middle-punct-ratio = \l__xeCJK_middle_punct_ratio_fp , + fixed-margin-width = \l__xeCJK_fixed_margin_width_dim , + fixed-margin-ratio = \l__xeCJK_fixed_margin_ratio_fp , + mixed-margin-width = \l__xeCJK_mixed_margin_width_dim , + mixed-margin-ratio = \l__xeCJK_mixed_margin_ratio_fp , + middle-margin-width = \l__xeCJK_middle_margin_width_dim , + middle-margin-ratio = \l__xeCJK_middle_margin_ratio_fp , + add-min-bound-to-margin = \l__xeCJK_add_min_bound_to_margin_bool , + optimize-margin = \l__xeCJK_optimize_margin_bool , + margin-minimum = \l__xeCJK_margin_minimum_dim , + enabled-kerning = \l__xeCJK_enabled_kerning_bool , + min-bound-to-kerning = \l__xeCJK_min_bound_to_kerning_bool , + kerning-total-width = \l__xeCJK_kerning_total_width_dim , + kerning-total-ratio = \l__xeCJK_kerning_total_ratio_fp , + optimize-kerning = \l__xeCJK_optimize_kerning_bool , + same-align-margin = \l__xeCJK_same_align_margin_dim , + same-align-ratio = \l__xeCJK_same_align_ratio_fp , + different-align-margin = \l__xeCJK_different_align_margin_dim , + different-align-ratio = \l__xeCJK_different_align_ratio_fp , + kerning-margin-width = \l__xeCJK_kerning_margin_width_dim , + kerning-margin-ratio = \l__xeCJK_kerning_margin_ratio_fp , + kerning-margin-minimum = \l__xeCJK_kerning_margin_minimum_dim + } + { + \AssignTemplateKeys + \tl_if_blank:nTF {#3} + { \xeCJK_punct_margin_process:NN {#1} {#2} } + { \xeCJK_punct_kerning_process:NN {#2} {#3} } + } +\cs_new_protected_nopar:Npn \xeCJK_punct_margin_process:NN #1#2 + { + \tl_set:Nx \l__xeCJK_tmpa_tl { \__xeCJK_use_punct_dim:nnn { bound } {#1} {#2} } + \tl_set:Nx \l__xeCJK_tmpb_tl + { + \__xeCJK_use_punct_dim:nnn { bound } + { \xeCJK_reverse:nnn {#1} \c__xeCJK_left_tl \c__xeCJK_right_tl } {#2} + } + \dim_set:Nn \l__xeCJK_tmp_dim + { + \bool_if:NTF \l__xeCJK_enabled_global_setting_bool { - \tl_set:NV \l__xeCJK_tmpa_tl \c_zero_dim - \tl_gset_eq:cN { \l__xeCJK_punct_coor_tl/glue/#1/#2 } \l__xeCJK_tmpa_tl - \tl_gset_eq:cN { \l__xeCJK_punct_coor_tl/rule/#1/#2 } \l__xeCJK_tmpa_tl - \tl_gset_eq:cN { \l__xeCJK_punct_coor_tl/rule/lr/#2 } \l__xeCJK_tmpa_tl - \tl_gset_eq:cN { \l__xeCJK_punct_coor_tl/bound/#1/#2 } \l__xeCJK_tmpa_tl - \tl_gset_eq:cN { \l__xeCJK_punct_coor_tl/bound/lr/#2 } \l__xeCJK_tmpa_tl + \cs_if_exist_use:cTF { g__xeCJK_punct_width/#2/tl } + { \use_none:n } + { + \xeCJK_if_blank_x:nTF \g__xeCJK_punct_width_tl + { \use:n } + { \g__xeCJK_punct_width_tl \use_none:n } + } } + { \use:n } { - \tl_if_exist:cF { \l__xeCJK_punct_coor_tl/bound/#1/#2 } - { { \xeCJK_select_font: \xeCJK_calc_punct_dimen:N {#2} } } - \__xeCJK_punct_if_long:NTF {#2} + \__xeCJK_punct_if_middle:NTF {#2} + { \__xeCJK_punct_width_or_ratio:nN { middle } {#2} } { - \dim_zero:N \l__xeCJK_tmpa_dim - \dim_zero:N \l__xeCJK_tmpb_dim - \dim_zero:N \l__xeCJK_tmpc_dim + \__xeCJK_punct_if_mixed_width:NTF {#2} + { \__xeCJK_punct_width_or_ratio:nN { mixed } {#2} } + { \__xeCJK_punct_width_or_ratio:nN { fixed } {#2} } } + } + } + \__xeCJK_gset_punct_dim:nnnx { glue } {#1} {#2} + { + \dim_max:nn + { \l__xeCJK_margin_minimum_dim } + { + \dim_compare:nNnTF \l__xeCJK_tmp_dim < \c_max_dim { - \dim_set:Nc \l__xeCJK_tmpa_dim { \l__xeCJK_punct_coor_tl/bound/#1/#2 } - \dim_set:Nc \l__xeCJK_tmpb_dim - { \l__xeCJK_punct_coor_tl/bound/\str_if_eq_x:nnTF {#1} lrl/#2 } - \dim_set:Nn \l__xeCJK_tmpc_dim + \__xeCJK_punct_if_middle:NTF {#2} { - \cs_if_exist_use:cF { g__xeCJK_punct_width/#2 } - { - \xeCJK_if_blank_x:nTF \g__xeCJK_punct_width_tl - { \c_zero_dim } { \g__xeCJK_punct_width_tl } - } + ( + \l__xeCJK_tmp_dim - ( \__xeCJK_use_punct_dim:nn { dimen } {#2} ) + ) / \c_two } - \__xeCJK_punct_if_middle:NTF {#2} { - \dim_set:Nn \l__xeCJK_tmpc_dim + \bool_if:NTF \l__xeCJK_optimize_margin_bool + { \dim_max:nn { \dim_min:nn \l__xeCJK_tmpa_tl \l__xeCJK_tmpb_tl } } + { \use:n } { - \dim_compare:nNnTF \l__xeCJK_tmpc_dim > \c_zero_dim - { \l__xeCJK_tmpc_dim } - { - \tl_case:Nnn \l_xeCJK_punctstyle_tl - { - \c__xeCJK_ps_halfwidth_tl { .5 em } - \c__xeCJK_ps_mixedwidth_tl { .5 em } - \c__xeCJK_ps_CCT_tl { .7 em } - \c__xeCJK_ps_fullwidth_tl { 1 em } - } - { 1 em } - } - - ( \tl_use:c { \l__xeCJK_punct_coor_tl/dimen/#2 } ) - } - \dim_compare:nNnTF \l__xeCJK_tmpc_dim > \c_zero_dim - { \dim_set:Nn \l__xeCJK_tmpc_dim { .5 \l__xeCJK_tmpc_dim } } - { - \dim_set:Nn \l__xeCJK_tmpc_dim - { \dim_min:nn \l__xeCJK_tmpa_dim \l__xeCJK_tmpb_dim } + \l__xeCJK_tmp_dim - ( \l__xeCJK_tmpb_tl ) + - ( \__xeCJK_use_punct_dim:nn { dimen } {#2} ) } } + } + { + \bool_if:NTF \l__xeCJK_optimize_margin_bool + { \dim_min:nn { \l__xeCJK_tmpa_tl } } + { \use:n } { - \dim_compare:nNnTF \l__xeCJK_tmpc_dim > \c_zero_dim + \__xeCJK_punct_if_middle:NTF {#2} { - \dim_set:Nn \l__xeCJK_tmpc_dim + \dim_compare:nNnTF \l__xeCJK_middle_margin_width_dim < \c_max_dim + { \l__xeCJK_middle_margin_width_dim } { - \l__xeCJK_tmpc_dim - \l__xeCJK_tmpb_dim - - ( \tl_use:c { \l__xeCJK_punct_coor_tl/dimen/#2 } ) + \fp_use:N \l__xeCJK_middle_margin_ratio_fp + \etex_dimexpr:D + ( \l__xeCJK_tmpa_tl + \l__xeCJK_tmpb_tl ) / \c_two + \scan_stop: } } { - \dim_set:Nn \l__xeCJK_tmpc_dim - { \dim_min:nn \l__xeCJK_tmpa_dim \l__xeCJK_tmpb_dim } - \tl_case:Nnn \l_xeCJK_punctstyle_tl - { - \c__xeCJK_ps_halfwidth_tl { \prg_do_nothing: } - \c__xeCJK_ps_mixedwidth_tl - { - \__xeCJK_punct_if_mixedwidth:NT {#2} - { - \dim_add:Nn \l__xeCJK_tmpc_dim { .5 \l__xeCJK_tmpa_dim } - \xeCJK_dim_set_min:Nn \l__xeCJK_tmpc_dim \l__xeCJK_tmpa_dim - } - } - \c__xeCJK_ps_CCT_tl - { - \__xeCJK_punct_if_mixedwidth:NTF {#2} - { \dim_add:Nn \l__xeCJK_tmpc_dim { .5 \l__xeCJK_tmpa_dim } } - { \dim_add:Nn \l__xeCJK_tmpc_dim { .3 \l__xeCJK_tmpa_dim } } - \xeCJK_dim_set_min:Nn \l__xeCJK_tmpc_dim \l__xeCJK_tmpa_dim - } - } - { \dim_set_eq:NN \l__xeCJK_tmpc_dim \l__xeCJK_tmpa_dim } + \__xeCJK_punct_if_mixed_width:NTF {#2} + { \__xeCJK_margin_width_or_ratio:n { mixed } } + { \__xeCJK_margin_width_or_ratio:n { fixed } } } } - \xeCJK_dim_set_max:Nn \l__xeCJK_tmpc_dim \c_zero_dim } - \tl_gset:cx { \l__xeCJK_punct_coor_tl/rule/#1/#2 } - { - \dim_use:N \l__xeCJK_tmpa_dim } - \tl_gset:cx { \l__xeCJK_punct_coor_tl/rule/lr/#2 } - { - \dim_use:N \l__xeCJK_tmpb_dim } - \tl_gset:cV { \l__xeCJK_punct_coor_tl/glue/#1/#2 } \l__xeCJK_tmpc_dim } } } -\cs_generate_variant:Nn \xeCJK_get_punct_bounds:nN { nV } -\NewDocumentCommand \xeCJKsetwidth { m m } - { \tl_map_inline:xn {#1} { \tl_gset:cn { g__xeCJK_punct_width/##1 } {#2} } } -\prg_new_conditional:Npnn \__xeCJK_punct_if_right:N #1 { p , T , F , TF } - { - \tl_if_exist:cTF { \l__xeCJK_punct_coor_tl/glue/r/#1 } - \prg_return_true: \prg_return_false: - } -\prg_new_conditional:Npnn \__xeCJK_punct_if_both_left_right:NN #1#2 { p , T , F , TF } +\cs_new_nopar:Npn \__xeCJK_punct_width_or_ratio:nN #1#2 { - \bool_if:nTF + \dim_compare:nNnTF { \use:c { l__xeCJK_#1_punct_width_dim } } < \c_max_dim + { \use:c { l__xeCJK_#1_punct_width_dim } } { - ( \tl_if_exist_p:c { \l__xeCJK_punct_coor_tl/glue/r/#1 } && - \tl_if_exist_p:c { \l__xeCJK_punct_coor_tl/glue/r/#2 } ) || - ( \tl_if_exist_p:c { \l__xeCJK_punct_coor_tl/glue/l/#1 } && - \tl_if_exist_p:c { \l__xeCJK_punct_coor_tl/glue/l/#2 } ) + \fp_compare:nNnTF { \use:c { l__xeCJK_#1_punct_ratio_fp } } = \c_zero_fp + { \c_max_dim } + { + \fp_use:c { l__xeCJK_#1_punct_ratio_fp } + \etex_dimexpr:D \__xeCJK_use_punct_dim:nn { width } {#2} \scan_stop: + } } - \prg_return_true: \prg_return_false: } -\cs_generate_variant:Nn \prg_new_conditional:Npnn { c } -\clist_map_inline:Nn \g__xeCJK_special_ps_clist +\cs_new_nopar:Npn \__xeCJK_margin_width_or_ratio:n #1 { - \prg_new_conditional:cpnn { __xeCJK_punct_if_#1:N } ##1 { p , T , F , TF } + \dim_compare:nNnTF { \use:c { l__xeCJK_#1_margin_width_dim } } < \c_max_dim + { \use:c { l__xeCJK_#1_margin_width_dim } } { - \prop_if_in:cnTF { l__xeCJK_#1_punct_prop } {##1} - \prg_return_true: \prg_return_false: + \fp_use:c { l__xeCJK_#1_margin_ratio_fp } + \etex_dimexpr:D \l__xeCJK_tmpa_tl \scan_stop: } + \bool_if:NT \l__xeCJK_add_min_bound_to_margin_bool + { + \dim_min:nn \l__xeCJK_tmpa_tl \l__xeCJK_tmpb_tl } } -\cs_new_protected_nopar:Npn \xeCJK_calc_kern:NN #1#2 +\cs_new_protected_nopar:Npn \xeCJK_punct_kerning_process:NN #1#2 { - \tl_if_exist:cF { \l__xeCJK_punct_coor_tl/kern/#1-#2 } + \__xeCJK_gset_punct_dim:nnnx { kern } {#1} {#2} { - \dim_zero:N \l__xeCJK_tmpa_dim - \tl_if_eq:NNF \l_xeCJK_punctstyle_tl \c__xeCJK_ps_plain_tl + \dim_eval:n { - \tl_if_exist:cTF { g__xeCJK_punct/kern/#1-#2 } - { \dim_set:Nc \l__xeCJK_tmpa_dim { g__xeCJK_punct/kern/#1-#2 } } - { \__xeCJK_calc_kern:NNN \l__xeCJK_tmpa_dim {#1} {#2} } + \bool_if:nTF + { + \l__xeCJK_enabled_global_setting_bool && + \tl_if_exist_p:c { g__xeCJK_punct/kern/#1/#2/tl } + } + { \tl_use:c { g__xeCJK_punct/kern/#1/#2/tl } } + { + \bool_if:NTF \l__xeCJK_enabled_kerning_bool + { \__xeCJK_calc_kerning_margin:NN {#1} {#2} } + { \__xeCJK_original_kerning_margin:NN {#1} {#2} } + } + - ( \__xeCJK_use_punct_dim:nnn { bound } \c__xeCJK_right_tl {#1} ) + - ( \__xeCJK_use_punct_dim:nnn { bound } \c__xeCJK_left_tl {#2} ) } - \tl_gset:cV { \l__xeCJK_punct_coor_tl/kern/#1-#2 } \l__xeCJK_tmpa_dim } } -\cs_new_protected_nopar:Npn \__xeCJK_calc_kern:NNN #1#2#3 +\cs_new_nopar:Npn \__xeCJK_original_kerning_margin:NN #1#2 { - \tl_if_eq:NNTF \l_xeCJK_punctstyle_tl \c__xeCJK_ps_marginkerning_tl + \dim_eval:n { - \dim_zero:N #1 - \__xeCJK_punct_if_right:NT {#2} - { \dim_add:Nc #1 { \l__xeCJK_punct_coor_tl/bound/r/#2 } } - \__xeCJK_punct_if_right:NF {#3} - { \dim_add:Nc #1 { \l__xeCJK_punct_coor_tl/bound/l/#3 } } + \__xeCJK_use_punct_dim:nnn + { \__xeCJK_punct_if_right:NTF {#1} { glue } { bound } } + { \c__xeCJK_right_tl } {#1} + + \__xeCJK_use_punct_dim:nnn + { \__xeCJK_punct_if_right:NTF {#2} { bound } { glue } } + { \c__xeCJK_left_tl } {#2} } + } +\cs_new_nopar:Npn \__xeCJK_calc_kerning_margin:NN #1#2 + { + \dim_max:nn + { \l__xeCJK_kerning_margin_minimum_dim } { - \tl_if_eq:NNTF \l_xeCJK_punctstyle_tl \c__xeCJK_ps_fullwidth_tl - { \dim_set:Nn #1 { \xeCJK_calc_kern:nNN { 1.5 em } {#2} {#3} } } + \bool_if:NTF \l__xeCJK_min_bound_to_kerning_bool + { \__xeCJK_punct_min_bound:NN {#1} {#2} } { - \__xeCJK_punct_if_both_left_right:NNTF {#2} {#3} - { - \__xeCJK_punct_if_mixedwidth:NT {#2} - { - \dim_set:Nn #1 { \xeCJK_calc_kern:nNN { 1 em } {#2} {#3} } - \dim_compare:nNnT #1 < { .1 em } - { \dim_set:Nc #1 { \l__xeCJK_punct_coor_tl/bound/l/#2 } } - } - } + \bool_if:NTF \l__xeCJK_optimize_kerning_bool + { \dim_max:nn { \__xeCJK_punct_min_bound:NN {#1} {#2} } } + { \use:n } { - \bool_if:nTF - { - \__xeCJK_punct_if_mixedwidth_p:N {#2} && - ! ( \tl_if_eq_p:NN \l_xeCJK_punctstyle_tl \c__xeCJK_ps_halfwidth_tl ) - } - { - \dim_set:Nn #1 { \tl_use:c { \l__xeCJK_punct_coor_tl/glue/r/#2 } } - \dim_set:Nn #1 { .7 #1 } - } + \dim_compare:nNnTF \l__xeCJK_kerning_total_width_dim < \c_max_dim + { \__xeCJK_calc_kerning_margin:nNN \l__xeCJK_kerning_total_width_dim } { - \dim_set:Nn #1 { \xeCJK_calc_kern:nNN { 1 em } {#2} {#3} } - \dim_compare:nNnT #1 < { .1 em } + \fp_compare:nNnTF \l__xeCJK_kerning_total_ratio_fp = \c_zero_fp + { + \xeCJK_if_same_class:NNTF {#1} {#2} + { \__xeCJK_kerning_width_or_ratio:nNN { same } } + { \__xeCJK_kerning_width_or_ratio:nNN { different } } + } { - \dim_set:Nn #1 + \__xeCJK_calc_kerning_margin:nNN { - \dim_max:nn - { - \dim_min:cc - { \l__xeCJK_punct_coor_tl/bound/l/#2 } - { \l__xeCJK_punct_coor_tl/bound/r/#2 } - } - { - \dim_min:cc - { \l__xeCJK_punct_coor_tl/bound/l/#3 } - { \l__xeCJK_punct_coor_tl/bound/r/#3 } - } + \fp_use:N \l__xeCJK_kerning_total_ratio_fp + \etex_dimexpr:D + \__xeCJK_use_punct_dim:nn { width } {#1} + + \__xeCJK_use_punct_dim:nn { width } {#2} + \scan_stop: } } } + {#1} {#2} } } - \bool_if:nT - { \__xeCJK_punct_if_long_p:N {#2} || \__xeCJK_punct_if_long_p:N {#3} } - { \xeCJK_dim_set_max:Nn #1 { .1 em } } } - \xeCJK_dim_set_max:Nn #1 \c_zero_dim } -\cs_generate_variant:Nn \xeCJK_calc_kern:NN { V } -\cs_new_protected_nopar:Npn \xeCJK_calc_kern:nNN #1#2#3 +\cs_new_nopar:Npn \__xeCJK_kerning_width_or_ratio:nNN #1#2#3 + { + \dim_compare:nNnTF { \use:c { l__xeCJK_#1_align_margin_dim } } < \c_max_dim + { \use:c { l__xeCJK_#1_align_margin_dim } \use_none:nn } + { + \fp_compare:nNnTF { \use:c { l__xeCJK_#1_align_ratio_fp } } = \c_zero_fp + { \use:n } + { \fp_use:c { l__xeCJK_#1_align_ratio_fp } \use_ii:nn } + } + { + \dim_compare:nNnTF \l__xeCJK_kerning_margin_width_dim < \c_max_dim + { \l__xeCJK_kerning_margin_width_dim \use_none:n } + { \fp_use:N \l__xeCJK_kerning_margin_ratio_fp \use:n } + } + { \etex_dimexpr:D \__xeCJK_original_kerning_margin:NN {#2} {#3} \scan_stop: } + } +\cs_new_nopar:Npn \__xeCJK_punct_min_bound:NN #1#2 + { + \dim_max:nn + { + \dim_min:nn + { \__xeCJK_use_punct_dim:nnn { bound } \c__xeCJK_left_tl {#1} } + { \__xeCJK_use_punct_dim:nnn { bound } \c__xeCJK_right_tl {#1} } + } + { + \dim_min:nn + { \__xeCJK_use_punct_dim:nnn { bound } \c__xeCJK_left_tl {#2} } + { \__xeCJK_use_punct_dim:nnn { bound } \c__xeCJK_right_tl {#2} } + } + } +\cs_new_nopar:Npn \__xeCJK_calc_kerning_margin:nNN #1#2#3 { \dim_eval:n { - #1 - - \tl_use:c { \l__xeCJK_punct_coor_tl/ - \__xeCJK_punct_if_right:NTF {#2} { bound } { glue } /l/#2 } - - \tl_use:c { \l__xeCJK_punct_coor_tl/ - \__xeCJK_punct_if_right:NTF {#3} { glue } { bound } /r/#3 } - - \tl_use:c { \l__xeCJK_punct_coor_tl/dimen/#2 } - - \tl_use:c { \l__xeCJK_punct_coor_tl/dimen/#3 } - \__xeCJK_punct_if_both_left_right:NNT {#2} {#3} - { + \tl_use:c { \l__xeCJK_punct_coor_tl/rule/lr/#3 } } + (#1) + - ( \__xeCJK_use_punct_dim:nnn + { \__xeCJK_punct_if_right:NTF {#2} { bound } { glue } } + { \c__xeCJK_left_tl } {#2} ) + - ( \__xeCJK_use_punct_dim:nnn + { \__xeCJK_punct_if_right:NTF {#3} { glue } { bound } } + { \c__xeCJK_right_tl } {#3} ) + - ( \__xeCJK_use_punct_dim:nn { dimen } {#2} ) + - ( \__xeCJK_use_punct_dim:nn { dimen } {#3} ) } } -\cs_new_protected_nopar:Npn \xeCJK_calc_punct_dimen:N #1 +\cs_new_protected_nopar:Npn \xeCJK_get_punct_bounds:NN #1#2 { - \tl_gset:cx { \l__xeCJK_punct_coor_tl/bound/l/#1 } - { \xeCJK_glyph_bounds:nN { left } {#1} } - \tl_gset:cx { \l__xeCJK_punct_coor_tl/bound/r/#1 } - { \xeCJK_glyph_bounds:nN { right } {#1} } - \tl_gset:cx { \l__xeCJK_punct_coor_tl/bound/lr/#1 } + \tl_if_exist:cF { \__xeCJK_punct_dim_csname:nnn { glue } {#1} {#2} } { - \dim_eval:n + \tl_if_eq:NNTF \l_xeCJK_punct_style_tl \c__xeCJK_punct_style_plain_tl { - ( \tl_use:c { \l__xeCJK_punct_coor_tl/bound/l/#1 } ) + - ( \tl_use:c { \l__xeCJK_punct_coor_tl/bound/r/#1 } ) + \__xeCJK_gset_punct_dim:nnnx { glue } {#1} {#2} { \c_zero_dim } + \__xeCJK_gset_punct_dim:nnnx { bound } \c__xeCJK_left_tl {#2} { \c_zero_dim } + \__xeCJK_gset_punct_dim:nnnx { bound } \c__xeCJK_right_tl {#2} { \c_zero_dim } } - } - \tl_gset:cx { \l__xeCJK_punct_coor_tl/dimen/#1 } - { - \dim_eval:n { - ( \etex_fontcharwd:D \tex_font:D `#1 ) - - ( \tl_use:c { \l__xeCJK_punct_coor_tl/bound/lr/#1 } ) + { \xeCJK_select_font: \xeCJK_calc_punct_dimen:f {#2} } + \__xeCJK_punct_if_long:NTF {#2} + { \__xeCJK_gset_punct_dim:nnnx { glue } {#1} {#2} { \c_zero_dim } } + { + \UseInstance { xeCJK / punctuation } + { \l_xeCJK_punct_style_tl } {#1} {#2} { } + } } } - \bool_if:nT + } +\cs_new_protected_nopar:Npn \xeCJK_calc_punct_dimen:N #1 + { + \__xeCJK_gset_punct_dim:nnnx { bound } \c__xeCJK_left_tl {#1} + { \xeCJK_glyph_bounds:NN \c_one {#1} } + \__xeCJK_gset_punct_dim:nnnx { bound } \c__xeCJK_right_tl {#1} + { \xeCJK_glyph_bounds:NN \c_three {#1} } + \dim_set:Nn \l__xeCJK_tmp_dim { - \__xeCJK_punct_if_long_p:N {#1} && - ! ( \str_if_eq_x_p:nn {#1} { ^^^^2025 } || \str_if_eq_x_p:nn {#1} { ^^^^2026 } ) + ( \__xeCJK_use_punct_dim:nnn { bound } \c__xeCJK_left_tl {#1} ) + + ( \__xeCJK_use_punct_dim:nnn { bound } \c__xeCJK_right_tl {#1} ) } + \__xeCJK_gset_punct_dim:nnx { width } {#1} + { \dim_use:N \etex_fontcharwd:D \tex_font:D `#1 } + \__xeCJK_gset_punct_dim:nnx { dimen } {#1} + { \dim_eval:n { \__xeCJK_use_punct_dim:nn { width } {#1} - \l__xeCJK_tmp_dim } } + \__xeCJK_punct_if_long:NT {#1} { - \clist_map_inline:Nn \g__xeCJK_punctstyle_clist + \seq_map_inline:Nn \g__xeCJK_punct_style_seq { - \str_if_eq_x:nnF \c__xeCJK_ps_plain_tl {##1} + \__xeCJK_gset_punct_dim:nnnnx {##1} { kern } {#1} {#1} { - \tl_gset:cx { \l_xeCJK_font_coor_tl/##1/kern/#1-#1 } - { - \tl_use:c { \l__xeCJK_punct_coor_tl/bound/lr/#1 } } + \bool_if:nTF + { + \str_if_eq_p:nn {#1} { ^^^^2025 } || + \str_if_eq_p:nn {#1} { ^^^^2026 } + } + { \c_zero_dim } + { - \dim_use:N \l__xeCJK_tmp_dim } } } } } -\cs_new_protected_nopar:Npn \xeCJK_glyph_bounds:nN #1#2 +\cs_generate_variant:Nn \xeCJK_calc_punct_dimen:N { f } +\cs_new_nopar:Npn \xeCJK_glyph_bounds:NN #1#2 + { \dim_use:N \XeTeXglyphbounds #1 ~ \XeTeXcharglyph `#2 \exp_stop_f: } +\cs_new_protected_nopar:Npn \xeCJK_get_punct_kerning:NN #1#2 { - \dim_eval:n + \tl_if_exist:cF { \__xeCJK_punct_dim_csname:nnn { kern } {#1} {#2} } + { + \tl_if_eq:NNTF \l_xeCJK_punct_style_tl \c__xeCJK_punct_style_plain_tl + { \__xeCJK_gset_punct_dim:nnnx { kern } {#1} {#2} { \c_zero_dim } } + { + \UseInstance { xeCJK / punctuation } + { \l_xeCJK_punct_style_tl } { } {#1} {#2} + } + } + } +\cs_generate_variant:Nn \xeCJK_get_punct_kerning:NN { o } +\keys_define:nn { xeCJK / options } + { + PunctStyle .choice: , + PunctStyle .default:n = { quanjiao } , + PunctStyle / halfwidth .meta:n = { PunctStyle = banjiao } , + PunctStyle / fullwidth .meta:n = { PunctStyle = quanjiao } , + PunctStyle / mixedwidth .meta:n = { PunctStyle = kaiming } , + PunctStyle / marginkerning .meta:n = { PunctStyle = hangmobanjiao } , + PunctStyle / plain .code:n = + { \tl_set_eq:NN \l_xeCJK_punct_style_tl \c__xeCJK_punct_style_plain_tl } , + PunctStyle / unknown .code:n = { - \XeTeXglyphbounds - \str_case_x:nnn {#1} - { - { left } { \c_one } { top } { \c_two } - { right } { \c_three } { bottom } { \c_four } - } - { \c_three } - \int_eval:n { \XeTeXcharglyph `#2 } + \IfInstanceExistTF { xeCJK / punctuation } { \l_keys_value_tl } + { \tl_set:Nx \l_xeCJK_punct_style_tl { \l_keys_value_tl } } + { \__xeCJK_error:nx { punct-style-unknown } { \l_keys_value_tl } } } } -\NewDocumentCommand \xeCJKsetkern { m m m } - { \tl_gset:cn { g__xeCJK_punct/kern/#1-#2 } {#3} } +\tl_const:Nn \c__xeCJK_punct_style_plain_tl { plain } +\__xeCJK_msg_new:nn { punct-style-unknown } + { + Punctuation~style~"#1"~is~unknown. \\\\ + The~available~styles~are~listed~as~follow.\\\\ + "plain,~\seq_use:Nnnn \g__xeCJK_punct_style_seq { ~and~ } { ,~ } { ,~and~ }".\\ + } +\NewDocumentCommand \xeCJKDeclarePunctStyle { > { \TrimSpaces } m m } + { + \IfInstanceExistTF { xeCJK / punctuation } {#1} + { \__xeCJK_warning:nx { punct-style-already-defined } {#1} } + { \seq_gput_right:Nn \g__xeCJK_punct_style_seq {#1} } + \DeclareInstance { xeCJK / punctuation } {#1} { basic } {#2} + } +\seq_new:N \g__xeCJK_punct_style_seq +\__xeCJK_msg_new:nn { punct-style-already-defined } + { + Punctuation~style~"#1"~is~already~defined!. \\\\ + The~existing~style~of~"#1"~will~be~overwritten.\\ + } +\@onlypreamble \xeCJKDeclarePunctStyle +\NewDocumentCommand \xeCJKEditPunctStyle { > { \TrimSpaces } m m } + { + \IfInstanceExistTF { xeCJK / punctuation } {#1} + { \EditInstance { xeCJK / punctuation } {#1} {#2} } + { \__xeCJK_error:nx { punct-style-unknown } {#1} } + } +\@onlypreamble \xeCJKEditPunctStyle +\xeCJKDeclarePunctStyle { quanjiao } { } +\xeCJKDeclarePunctStyle { hangmobanjiao } { enabled-kerning = false } +\xeCJKDeclarePunctStyle { banjiao } + { + fixed-punct-ratio = 0.5 , + optimize-margin = true , + kerning-total-ratio = 0.5 , + optimize-kerning = true + } +\xeCJKDeclarePunctStyle { kaiming } + { + fixed-punct-ratio = 0.5 , + mixed-punct-ratio = 0.8 , + optimize-margin = true , + kerning-total-ratio = 0.5 , + optimize-kerning = true + } +\xeCJKDeclarePunctStyle { CCT } + { + fixed-punct-ratio = 0.7 , + optimize-margin = true , + kerning-total-ratio = 0.6 , + optimize-kerning = true + } \keys_define:nn { xeCJK / options } { - AutoFallBack .choice:, - AutoFallBack / true .code:n = { \xeCJKenablefallback }, - AutoFallBack / false .code:n = { \xeCJKdisablefallback }, - AutoFallBack .default:n = { true }, - fallback .meta:n = { AutoFallBack = true }, + AutoFallBack .choice: , + AutoFallBack / true .code:n = { \xeCJKenablefallback } , + AutoFallBack / false .code:n = { \xeCJKdisablefallback } , + AutoFallBack .default:n = { true } , + fallback .meta:n = { AutoFallBack = true } } -\bool_new:N \l__xeCJK_fallback_bool \NewDocumentCommand \xeCJKenablefallback { } { \bool_if:NF \l__xeCJK_fallback_bool { \bool_set_true:N \l__xeCJK_fallback_bool \cs_set_eq:NN \__xeCJK_fallback_save_CJKsymbol:N \CJKsymbol - \cs_set_eq:NN \CJKsymbol \xeCJK_fallback_testsymbol:N + \cs_set_eq:NN \CJKsymbol \xeCJK_fallback_test_glyph:N } } \NewDocumentCommand \xeCJKdisablefallback { } @@ -1371,105 +1497,107 @@ \cs_set_eq:NN \CJKsymbol \__xeCJK_fallback_save_CJKsymbol:N } } -\cs_new_protected_nopar:Npn \xeCJK_fallback_testsymbol:N #1 +\bool_new:N \l__xeCJK_fallback_bool +\cs_new_protected_nopar:Npn \xeCJK_fallback_test_glyph:N #1 { - \font_glyph_if_exist:NnTF \tex_font:D {`#1} + \xeCJK_glyph_if_exist:NTF {#1} { \__xeCJK_fallback_save_CJKsymbol:N {#1} } + { { \xeCJK_fallback_loop:Nn {#1} { \l_xeCJK_family_tl/FallBack } } } + } +\cs_new_protected_nopar:Npn \xeCJK_fallback_loop:Nn #1#2 + { + \xeCJK_family_if_exist:xTF {#2} { - \xeCJK_family_if_exist:xTF { \l_xeCJK_family_tl/FallBack } - { { - \tl_put_right:Nn \l_xeCJK_family_tl { /FallBack } - \xeCJK_select_font: - \xeCJK_fallback_testsymbol:N {#1} - } } - { - \__xeCJK_warning:nx { fallback } {#1} - \__xeCJK_fallback_save_CJKsymbol:N {#1} - } + \xeCJK_select_font:x {#2} + \xeCJK_glyph_if_exist:NTF {#1} + { \__xeCJK_fallback_save_CJKsymbol:N {#1} } + { \xeCJK_fallback_loop:Nn {#1} { #2/FallBack } } + } + { + \__xeCJK_warning:nxx { fallback } {#1} {#2} + \__xeCJK_fallback_save_CJKsymbol:N {#1} } } \__xeCJK_msg_new:nn { fallback } { - CJKfamily~'\l_xeCJK_family_tl'~ - ( \prop_get:NV \g__xeCJK_family_prop \l_xeCJK_family_tl )~ + CJKfamily~'#2'~ + ( \prop_get:No \g__xeCJK_family_font_name_prop {#2} )~ does~not~contain~glyph~'#1'~(U+\int_to_hexadecimal:n {`#1}).\\ } +\cs_generate_variant:Nn \prop_get:Nn { No } \NewDocumentCommand \setCJKfallbackfamilyfont { m O{} m } { - \exp_args:Nx \tl_if_in:nnTF {#3} { , } - { \xeCJK_set_family_fallback:xnn {#1} {#2} {#3} } - { \xeCJK_set_family:xnn { #1/FallBack } {#2} {#3} } + \clist_set:Nx \l__xeCJK_tmpa_clist {#3} + \int_compare:nNnTF { \clist_count:N \l__xeCJK_tmpa_clist } > \c_one + { \xeCJK_set_family_fallback:xxN {#1} {#2} \l__xeCJK_tmpa_clist } + { \xeCJK_set_family:xxx { #1/FallBack } {#2} {#3} } } -\cs_new_protected_nopar:Npn \xeCJK_set_family_fallback:xnn #1#2#3 +\cs_new_protected_nopar:Npn \xeCJK_set_family_fallback:nnN #1#2#3 { \group_begin: - \tl_set:Nx \l__xeCJK_family_fb_tl {#1} - \prop_get:NVNF \g__xeCJK_family_prop \l__xeCJK_family_fb_tl \l__xeCJK_fontname_tl - { \tl_clear:N \l__xeCJK_fontname_tl } - \clist_map_inline:xn {#3} - { - \tl_put_right:Nn \l__xeCJK_family_fb_tl { /FallBack } - \__xeCJK_get_sub_features:nn \l__xeCJK_family_fb_tl {##1} - \clist_put_left:cx { l__xeCJK_ \l__xeCJK_family_fb_tl _fontfeat_clist } {#2} - \xeCJK_set_family:xcc \l__xeCJK_family_fb_tl - { l__xeCJK_ \l__xeCJK_family_fb_tl _fontfeat_clist } - { l__xeCJK_ \l__xeCJK_family_fb_tl _fontname_tl } + \tl_set:Nn \l__xeCJK_fallback_family_tl {#1} + \prop_get:NVNF \g__xeCJK_family_font_name_prop + \l__xeCJK_fallback_family_tl \l__xeCJK_font_name_tl + { \tl_clear:N \l__xeCJK_font_name_tl } + \clist_map_inline:Nn #3 + { + \tl_put_right:Nn \l__xeCJK_fallback_family_tl { /FallBack } + \__xeCJK_get_sub_features:Vn \l__xeCJK_fallback_family_tl {##1} + \clist_put_left:cn + { l__xeCJK_ \l__xeCJK_fallback_family_tl _font_options_clist } {#2} + \xeCJK_set_family:Vvv \l__xeCJK_fallback_family_tl + { l__xeCJK_ \l__xeCJK_fallback_family_tl _font_options_clist } + { l__xeCJK_ \l__xeCJK_fallback_family_tl _font_name_tl } } \group_end: } -\bool_new:N \g__xeCJK_AutoFakeBold_bool -\bool_new:N \g__xeCJK_AutoFakeSlant_bool -\fp_new:N \g__xeCJK_EmboldenFactor_fp -\fp_new:N \g__xeCJK_SlantFactor_fp +\cs_generate_variant:Nn \xeCJK_set_family_fallback:nnN { xx } +\bool_new:N \g__xeCJK_auto_fake_bold_bool +\bool_new:N \g__xeCJK_auto_fake_slant_bool +\fp_new:N \g__xeCJK_embolden_factor_fp +\fp_new:N \g__xeCJK_slant_factor_fp \keys_define:nn { xeCJK / options } { - AutoFakeBold .choice:, - AutoFakeBold / true .code:n = - { \bool_set_true:N \g__xeCJK_AutoFakeBold_bool }, - AutoFakeBold / false .code:n = - { \bool_set_false:N \g__xeCJK_AutoFakeBold_bool }, + AutoFakeBold .choices:nn = { true , false } + { \use:c { bool_gset_ \l_keys_choice_tl :N } \g__xeCJK_auto_fake_bold_bool } , AutoFakeBold / unknown .code:n = { - \bool_set_true:N \g__xeCJK_AutoFakeBold_bool - \fp_set:Nn \g__xeCJK_EmboldenFactor_fp { \l_keys_value_tl } - }, - AutoFakeBold .default:n = { true }, - AutoFakeSlant .choice:, - AutoFakeSlant / true .code:n = - { \bool_set_true:N \g__xeCJK_AutoFakeSlant_bool }, - AutoFakeSlant / false .code:n = - { \bool_set_false:N \g__xeCJK_AutoFakeSlant_bool }, + \bool_gset_true:N \g__xeCJK_auto_fake_bold_bool + \fp_gset:Nn \g__xeCJK_embolden_factor_fp { \l_keys_value_tl } + } , + AutoFakeBold .default:n = { true } , + AutoFakeSlant .choices:nn = { true , false } + { \use:c { bool_gset_ \l_keys_choice_tl :N } \g__xeCJK_auto_fake_slant_bool } , AutoFakeSlant / unknown .code:n = { - \bool_set_true:N \g__xeCJK_AutoFakeSlant_bool - \fp_set:Nn \g__xeCJK_SlantFactor_fp { \l_keys_value_tl } - }, - AutoFakeSlant .default:n = { true }, - EmboldenFactor .fp_set:N = \g__xeCJK_EmboldenFactor_fp, - SlantFactor .fp_set:N = \g__xeCJK_SlantFactor_fp, - BoldFont .meta:n = { AutoFakeBold = true }, - boldfont .meta:n = { AutoFakeBold = true }, - SlantFont .meta:n = { AutoFakeSlant = true }, - slantfont .meta:n = { AutoFakeSlant = true }, - } -\cs_generate_variant:Nn \keys_set_known:nnN { nx } -\clist_new:N \g__xeCJK_sub_key_clist + \bool_gset_true:N \g__xeCJK_auto_fake_slant_bool + \fp_gset:Nn \g__xeCJK_slant_factor_fp { \l_keys_value_tl } + } , + AutoFakeSlant .default:n = { true } , + EmboldenFactor .fp_gset:N = \g__xeCJK_embolden_factor_fp , + SlantFactor .fp_gset:N = \g__xeCJK_slant_factor_fp , + BoldFont .meta:n = { AutoFakeBold = true } , + boldfont .meta:n = { AutoFakeBold = true } , + SlantFont .meta:n = { AutoFakeSlant = true } , + slantfont .meta:n = { AutoFakeSlant = true } + } +\seq_new:N \g__xeCJK_sub_key_seq \cs_new_protected_nopar:Npn \__xeCJK_new_sub_key:n #1 { - \clist_gput_right:Nx \g__xeCJK_sub_key_clist {#1} + \seq_gput_right:Nn \g__xeCJK_sub_key_seq {#1} \keys_define:nn { xeCJK / features } { #1 .code:n = { - \xeCJK_if_blank_x:nTF {##1} + \tl_if_blank:nTF {##1} { \bool_set_false:c { l__xeCJK_copy_#1_bool } \bool_set_false:c { l__xeCJK_add_#1_bool } - \tl_put_right:Nx \l__xeCJK_family_aux_tl { /#1 } + \tl_put_right:Nn \l__xeCJK_family_name_tl { /#1 } } { - \clist_put_right:Nx \l__xeCJK_sub_key_clist {#1} - \str_if_eq_x:nnTF {##1} * + \seq_put_right:Nn \l__xeCJK_sub_key_seq {#1} + \str_if_eq:nnTF {##1} { * } { \bool_set_true:c { l__xeCJK_copy_#1_bool } \bool_set_false:c { l__xeCJK_add_#1_bool } @@ -1480,48 +1608,42 @@ \__xeCJK_get_sub_features:nn {#1} {##1} } } - }, - #1 .default:n = \c_empty_tl, + } , + #1 .default:n = { } } } \cs_generate_variant:Nn \__xeCJK_new_sub_key:n { x } \cs_new_protected_nopar:Npn \__xeCJK_get_sub_features:nn #1#2 { - \tl_set:Nx \l__xeCJK_tmpa_tl {#2} - \clist_clear:N \l__xeCJK_sub_fontfeat_clist - \__xeCJK_gobble_brace:N \l__xeCJK_tmpa_tl - \exp_args:No \tl_if_head_eq_charcode:nNTF \l__xeCJK_tmpa_tl [ % ] + \tl_set:Nx \l__xeCJK_tmpa_tl { \xeCJK_tl_remove_outer_braces:n {#2} } + \clist_clear:N \l__xeCJK_sub_font_options_clist + \tl_if_head_eq_meaning:VNTF \l__xeCJK_tmpa_tl [ % ] { - \exp_after:wN \__xeCJK_get_sub_features_aux:n \l__xeCJK_tmpa_tl \c_empty_tl - \xeCJK_if_blank_x:nT \l__xeCJK_sub_fontname_tl + \exp_after:wN \__xeCJK_get_sub_features:wn \l__xeCJK_tmpa_tl \c_empty_tl + \tl_if_blank:VT \l__xeCJK_sub_font_name_tl { - \tl_set:Nx \l__xeCJK_sub_fontname_tl \l__xeCJK_tmpa_tl - \clist_clear:N \l__xeCJK_sub_fontfeat_clist + \tl_set_eq:NN \l__xeCJK_sub_font_name_tl \l__xeCJK_tmpa_tl + \clist_clear:N \l__xeCJK_sub_font_options_clist } } - { \tl_set:Nx \l__xeCJK_sub_fontname_tl \l__xeCJK_tmpa_tl } - \xeCJK_if_blank_x:nTF \l__xeCJK_sub_fontname_tl - { \tl_set:Nx \l__xeCJK_sub_fontname_tl \l__xeCJK_fontname_tl } - { \tl_replace_all:Nnx \l__xeCJK_sub_fontname_tl * \l__xeCJK_fontname_tl } - \clist_set:cx { l__xeCJK_#1_fontfeat_clist } \l__xeCJK_sub_fontfeat_clist - \tl_set:cx { l__xeCJK_#1_fontname_tl } \l__xeCJK_sub_fontname_tl - } -\cs_new_protected_nopar:Npn \__xeCJK_gobble_brace:N #1 - { - \exp_args:No \tl_if_head_is_group:nT #1 - { - \exp_last_unbraced:NNo \tl_set:Nn #1 #1 - \__xeCJK_gobble_brace:N #1 - } + { \tl_set_eq:NN \l__xeCJK_sub_font_name_tl \l__xeCJK_tmpa_tl } + \tl_if_blank:VTF \l__xeCJK_sub_font_name_tl + { \tl_set_eq:NN \l__xeCJK_sub_font_name_tl \l__xeCJK_font_name_tl } + { \tl_replace_all:NnV \l__xeCJK_sub_font_name_tl { * } \l__xeCJK_font_name_tl } + \clist_set_eq:cN { l__xeCJK_#1_font_options_clist } \l__xeCJK_sub_font_options_clist + \tl_set_eq:cN { l__xeCJK_#1_font_name_tl } \l__xeCJK_sub_font_name_tl } -\cs_new_protected_nopar:Npn \__xeCJK_get_sub_features_aux:n [#1] #2 +\cs_new_protected_nopar:Npn \__xeCJK_get_sub_features:wn [#1] #2 { - \clist_set:Nx \l__xeCJK_sub_fontfeat_clist {#1} - \tl_set:Nx \l__xeCJK_sub_fontname_tl {#2} + \clist_set:Nn \l__xeCJK_sub_font_options_clist {#1} + \str_if_eq:nnTF {#2} { \c_empty_tl } + { \tl_set_eq:NN \l__xeCJK_sub_font_name_tl \c_empty_tl } + { \tl_set:Nn \l__xeCJK_sub_font_name_tl {#2} } } +\cs_generate_variant:Nn \__xeCJK_get_sub_features:nn { V } +\cs_generate_variant:Nn \tl_if_head_eq_meaning:nNTF { V } +\cs_generate_variant:Nn \tl_replace_all:Nnn { NnV } \__xeCJK_new_sub_key:n { FallBack } -\cs_new_nopar:Npn \__xeCJK_map_features_id:n #1 - { \prop_get:Nn \g__xeCJK_features_id_prop {#1} } \prop_new:N \g__xeCJK_features_id_prop \prop_put:Nnn \g__xeCJK_features_id_prop { bf } { Bold } \prop_put:Nnn \g__xeCJK_features_id_prop { it } { Italic } @@ -1532,282 +1654,278 @@ { \keys_define:nn { xeCJK / features } { - #2Font .tl_set_x:c = { l__xeCJK_fontname_#1_tl }, - #2Features .tl_set_x:c = { l__xeCJK_fontfeat_#1_clist } , + #2Font .tl_set:c = { l__xeCJK_font_name_#1_tl } , + #2Features .clist_set:c = { l__xeCJK_font_feat_#1_clist } } } \keys_define:nn { xeCJK / features } { - AutoFakeBold .choice:, + AutoFakeBold .choice: , AutoFakeBold / false .code:n = - { \bool_set_false:N \l__xeCJK_AutoFakeBold_bool }, + { \bool_set_false:N \l__xeCJK_auto_fake_bold_bool } , AutoFakeBold / unknown .code:n = { - \bool_set_true:N \l__xeCJK_AutoFakeBold_bool - \fp_set:Nn \l__xeCJK_EmboldenFactor_fp { \l_keys_value_tl } - }, - AutoFakeBold .default:n = { \g__xeCJK_EmboldenFactor_fp }, - AutoFakeSlant .choice:, + \bool_set_true:N \l__xeCJK_auto_fake_bold_bool + \fp_set:Nn \l__xeCJK_embolden_factor_fp { \l_keys_value_tl } + } , + AutoFakeBold .default:n = { \g__xeCJK_embolden_factor_fp } , + AutoFakeSlant .choice: , AutoFakeSlant / false .code:n = - { \bool_set_false:N \l__xeCJK_AutoFakeSlant_bool }, + { \bool_set_false:N \l__xeCJK_auto_fake_slant_bool } , AutoFakeSlant / unknown .code:n = { - \bool_set_true:N \l__xeCJK_AutoFakeSlant_bool - \fp_set:Nn \l__xeCJK_SlantFactor_fp { \l_keys_value_tl } - }, - AutoFakeSlant .default:n = { \g__xeCJK_SlantFactor_fp }, - Mono .choice:, - Mono / Exspace .code:n = - { - \xeCJK_set_monoexspace: - \tl_clear:N \l__xeCJK_monoscale_tl - }, - Mono / Scale .code:n = - { - \xeCJK_set_monoscale: - \tl_set:Nx \l__xeCJK_monoscale_tl { Scale = { \fp_use:N \g__xeCJK_monoscale_fp } } - } + \bool_set_true:N \l__xeCJK_auto_fake_slant_bool + \fp_set:Nn \l__xeCJK_slant_factor_fp { \l_keys_value_tl } + } , + AutoFakeSlant .default:n = { \g__xeCJK_slant_factor_fp } } -\cs_new_protected_nopar:Npn \__xeCJK_set_init: +\cs_new_protected_nopar:Npn \__xeCJK_set_family_initial: { - \cs_set_eq:NN \CJKfamily \use_none:n - \tl_clear:N \l__xeCJK_monoscale_tl - \int_gincr:N \g__xeCJK_fontspec_int + \__xeCJK_gobble_CJKfamily: + \int_gincr:N \g__xeCJK_family_int \prop_clear:N \l__xeCJK_add_font_prop \prop_map_inline:Nn \g__xeCJK_features_id_prop { - \tl_clear:c { l__xeCJK_fontname_##1_tl } - \clist_clear:c { l__xeCJK_fontfeat_##1_clist } + \tl_clear:c { l__xeCJK_font_name_##1_tl } + \clist_clear:c { l__xeCJK_font_feat_##1_clist } } - \clist_clear:N \l__xeCJK_pass_features_clist - \clist_clear:N \l__xeCJK_sub_key_clist - \clist_map_inline:Nn \g__xeCJK_sub_key_clist + \clist_clear:N \l__xeCJK_fontspec_options_clist + \seq_clear:N \l__xeCJK_sub_key_seq + \seq_map_inline:Nn \g__xeCJK_sub_key_seq { \bool_set_false:c { l__xeCJK_copy_##1_bool } \bool_set_false:c { l__xeCJK_add_##1_bool } } - \bool_set_eq:NN \l__xeCJK_AutoFakeBold_bool \g__xeCJK_AutoFakeBold_bool - \bool_set_eq:NN \l__xeCJK_AutoFakeSlant_bool \g__xeCJK_AutoFakeSlant_bool - \fp_set_eq:NN \l__xeCJK_EmboldenFactor_fp \g__xeCJK_EmboldenFactor_fp - \fp_set_eq:NN \l__xeCJK_SlantFactor_fp \g__xeCJK_SlantFactor_fp + \bool_set_eq:NN \l__xeCJK_auto_fake_bold_bool \g__xeCJK_auto_fake_bold_bool + \bool_set_eq:NN \l__xeCJK_auto_fake_slant_bool \g__xeCJK_auto_fake_slant_bool + \fp_set_eq:NN \l__xeCJK_embolden_factor_fp \g__xeCJK_embolden_factor_fp + \fp_set_eq:NN \l__xeCJK_slant_factor_fp \g__xeCJK_slant_factor_fp } -\cs_new_protected_nopar:Npn \xeCJK_set_family:xnn #1#2#3 +\int_new:N \g__xeCJK_family_int +\cs_new_protected_nopar:Npn \xeCJK_set_family:nnn #1#2#3 { \group_begin: - \__xeCJK_set_init: - \tl_set:Nx \l__xeCJK_family_aux_tl {#1} - \clist_set:Nx \l__xeCJK_fontoptions_clist {#2} - \tl_set:Nx \l__xeCJK_fontname_tl {#3} - \keys_set_known:nxN { xeCJK / features } - { \g__xeCJK_default_features_clist, #2 } \l__xeCJK_pass_features_clist + \__xeCJK_set_family_initial: + \tl_set:Nn \l__xeCJK_family_name_tl {#1} + \clist_set:Nn \l__xeCJK_font_options_clist {#2} + \tl_set:Nn \l__xeCJK_font_name_tl {#3} + \clist_concat:NNN \l__xeCJK_font_features_clist + \g__xeCJK_default_features_clist \l__xeCJK_font_options_clist + \__xeCJK_remove_duplicate_keys:N \l__xeCJK_font_features_clist + \keys_set_known:nVN { xeCJK / features } + \l__xeCJK_font_features_clist \l__xeCJK_fontspec_options_clist \__xeCJK_parse_features: \__xeCJK_pass_features: - \__xeCJK_check_family:V \l__xeCJK_family_aux_tl - \cs_gset_protected_nopar:cpx { __xeCJK/family/\l__xeCJK_family_aux_tl } + \__xeCJK_check_family:V \l__xeCJK_family_name_tl + \__xeCJK_gset_family_cs:x { \l__xeCJK_family_name_tl } + \__xeCJK_save_family_info: + \__xeCJK_set_sub_block_family: + \group_end: + } +\cs_generate_variant:Nn \xeCJK_set_family:nnn { Vnn , xxx , Vvv } +\cs_new_protected_nopar:Npn \__xeCJK_remove_duplicate_keys:N #1 + { + \prop_clear:N \l__xeCJK_tmp_prop + \keyval_parse:NNV \__xeCJK_prop_put_aux:n \__xeCJK_prop_put_aux:nn #1 + \clist_clear:N #1 + \prop_map_inline:Nn \l__xeCJK_tmp_prop + { + \tl_if_blank:nTF {##2} + { \clist_put_right:Nn #1 {##1} } + { \clist_put_right:Nn #1 { ##1 = {##2} } } + } + } +\cs_generate_variant:Nn \keyval_parse:NNn { NNV } +\cs_new_protected_nopar:Npn \__xeCJK_prop_put_aux:n #1 + { \prop_put:Nnn \l__xeCJK_tmp_prop {#1} { } } +\cs_new_protected_nopar:Npn \__xeCJK_prop_put_aux:nn #1#2 + { \prop_put:Nnn \l__xeCJK_tmp_prop {#1} {#2} } +\cs_new_protected_nopar:Npn \__xeCJK_gset_family_cs:x #1 + { + \cs_gset_protected_nopar:cpx { \__xeCJK_family_csname:n {#1} } { \group_begin: - \exp_not:n { \cs_set_eq:NN \CJKfamily \use_none:n } + \__xeCJK_gobble_CJKfamily: \exp_not:n { \fontspec_set_family:Nnn \l__xeCJK_fontspec_family_tl } - { \l__xeCJK_pass_features_clist } { \l__xeCJK_fontname_tl } - \prop_gput:NnV \exp_not:N \g__xeCJK_family_name_prop - { \l__xeCJK_family_aux_tl } \exp_not:N \l__xeCJK_fontspec_family_tl - \cs_gset_protected_nopar:cpx { __xeCJK/family/\l__xeCJK_family_aux_tl } - \exp_not:n - { { - \exp_not:N \fontencoding { \c__xeCJK_encoding_tl } - \exp_not:N \fontfamily { \l__xeCJK_fontspec_family_tl } - \exp_not:N \selectfont - } } + { \exp_not:V \l__xeCJK_fontspec_options_clist } + { \exp_not:V \l__xeCJK_font_name_tl } + \__xeCJK_gset_family_nfss_cs:xx {#1} { \exp_not:N \l__xeCJK_fontspec_family_tl } \group_end: } - \__xeCJK_save_family_info: - \__xeCJK_add_sub_block: - \group_end: } -\cs_generate_variant:Nn \xeCJK_set_family:xnn { xcc } \cs_new_protected_nopar:Npn \__xeCJK_check_family:n #1 { - \prop_get:NnNT \g__xeCJK_family_prop {#1} \l__xeCJK_tmpa_tl + \prop_get:NnNT \g__xeCJK_family_font_name_prop {#1} \l__xeCJK_tmpa_tl { - \prop_gpop:NnNT \g__xeCJK_family_name_prop {#1} \l__xeCJK_tmpa_tl { } - \__xeCJK_warning:nxx { CJKfamily-redef } {#1} \l__xeCJK_tmpa_tl + \prop_gpop:NnNT \g__xeCJK_family_name_prop {#1} \l__xeCJK_tmpa_tl + { \cs_undefine:c { \__xeCJK_family_nfss_csname:n {#1} } } + \__xeCJK_warning:nxx { CJKfamily-redef } {#1} { \l__xeCJK_tmpa_tl } } } \cs_generate_variant:Nn \__xeCJK_check_family:n { V } -\__xeCJK_msg_new:nn { CJKfamily-redef } { Redefining~CJKfamily~`#1'~(#2). } +\__xeCJK_msg_new:nn { CJKfamily-redef } + { Redefining~CJKfamily~`\__xeCJK_msg_family_map:n {#1}'~(#2). } \cs_new_protected_nopar:Npn \__xeCJK_add_font:nn #1#2 - { - \prop_put:Nxx \l__xeCJK_add_font_prop - { \__xeCJK_map_features_id:n {#1} Font } {#2} - } + { \prop_put:Nnn \l__xeCJK_add_font_prop { #1 Font } {#2} } \cs_new_protected_nopar:Npn \__xeCJK_add_font_if_new:nn #1#2 - { - \prop_put_if_new:Nxx \l__xeCJK_add_font_prop - { \__xeCJK_map_features_id:n {#1} Font } {#2} - } -\cs_generate_variant:Nn \__xeCJK_add_font:nn { nx, nc, nV, nv } -\cs_generate_variant:Nn \__xeCJK_add_font_if_new:nn { nx, nc, nV, nv } -\cs_generate_variant:Nn \prop_put:Nnn { Nxx } -\cs_generate_variant:Nn \prop_get:Nn { NV } -\cs_generate_variant:Nn \prop_get:NnNF { Nx } -\cs_generate_variant:Nn \prop_if_in:NnF { Nx } -\cs_generate_variant:Nn \prop_put_if_new:Nnn { Nxx } + { \prop_put_if_new:Nnn \l__xeCJK_add_font_prop { #1 Font } {#2} } +\cs_generate_variant:Nn \__xeCJK_add_font:nn { nx , nV , nv } +\cs_generate_variant:Nn \__xeCJK_add_font_if_new:nn { nx , nV , nv } \cs_new_protected_nopar:Npn \__xeCJK_add_fake_bold:n #1 { - \clist_put_left:cx { l__xeCJK_fontfeat_#1_clist } - { FakeBold = { \fp_use:N \l__xeCJK_EmboldenFactor_fp } } + \clist_put_left:cx { l__xeCJK_font_feat_#1_clist } + { FakeBold = { \fp_use:N \l__xeCJK_embolden_factor_fp } } } \cs_new_protected_nopar:Npn \__xeCJK_add_fake_slant:n #1 { - \clist_put_left:cx { l__xeCJK_fontfeat_#1_clist } - { FakeSlant = { \fp_use:N \l__xeCJK_SlantFactor_fp } } + \clist_put_left:cx { l__xeCJK_font_feat_#1_clist } + { FakeSlant = { \fp_use:N \l__xeCJK_slant_factor_fp } } } \cs_new_protected_nopar:Npn \__xeCJK_parse_features: - { \prop_map_inline:Nn \g__xeCJK_features_id_prop { \__xeCJK_parse_features:n {##1} } } -\cs_new_protected_nopar:Npn \__xeCJK_parse_features:n #1 + { \prop_map_function:NN \g__xeCJK_features_id_prop \__xeCJK_parse_features:nn } +\cs_new_protected_nopar:Npn \__xeCJK_parse_features:nn #1#2 { \__xeCJK_if_font_select:nTF {#1} { - \__xeCJK_add_font:nv {#1} { l__xeCJK_fontname_#1_tl } + \__xeCJK_add_font:nv {#2} { l__xeCJK_font_name_#1_tl } \__xeCJK_if_it_or_sl:nTF {#1} { - \__xeCJK_if_font_select:nF {bf#1} - { \__xeCJK_add_font_if_new:nv {bf#1} { l__xeCJK_fontname_#1_tl } } + \__xeCJK_if_font_select:nF { bf #1 } + { \__xeCJK_add_font_if_new:nv {#2} { l__xeCJK_font_name_#1_tl } } } { - \str_if_eq_x:nnT {#1} {bf} + \str_if_eq:nnT {#1} { bf } { - \clist_map_inline:nn { it , sl } - { - \__xeCJK_if_font_select:nF {bf##1} - { \__xeCJK_add_font:nV {bf##1} \l__xeCJK_fontname_bf_tl } - } + \__xeCJK_if_font_select:nF { bfit } + { \__xeCJK_add_font:nV { BoldItalic } \l__xeCJK_font_name_bf_tl } + \__xeCJK_if_font_select:nF { bfsl } + { \__xeCJK_add_font:nV { BoldSlanted } \l__xeCJK_font_name_bf_tl } } } } - { \__xeCJK_set_fake:n {#1} } + { \__xeCJK_set_fake_font:nn {#1} {#2} } } -\prg_new_conditional:Npnn \__xeCJK_if_font_select:n #1 { p, T, F, TF } +\prg_new_conditional:Npnn \__xeCJK_if_font_select:n #1 { p , T , F , TF } { - \exp_args:Nc \xeCJK_if_blank_x:nTF { l__xeCJK_fontname_#1_tl } - \prg_return_false: \prg_return_true: + \tl_if_blank:vTF { l__xeCJK_font_name_#1_tl } + { \prg_return_false: } { \prg_return_true: } } -\prg_new_conditional:Npnn \__xeCJK_if_it_or_sl:n #1 { p, T, F, TF } +\prg_new_conditional:Npnn \__xeCJK_if_it_or_sl:n #1 { p , T , F , TF } { - \bool_if:nTF { \str_if_eq_x_p:nn { it } {#1} || \str_if_eq_x_p:nn { sl } {#1} } - \prg_return_true: \prg_return_false: + \if_predicate:w + \bool_if_p:n { \str_if_eq_p:nn { it } {#1} || \str_if_eq_p:nn { sl } {#1} } + \prg_return_true: \else: \prg_return_false: \fi: } -\cs_new_protected_nopar:Npn \__xeCJK_set_fake:n #1 +\cs_generate_variant:Nn \tl_if_blank:nTF { v } +\cs_new_protected_nopar:Npn \__xeCJK_set_fake_font:nn #1#2 { - \str_if_eq_x:nnTF {#1} { bf } - { \bool_if:NT \l__xeCJK_AutoFakeBold_bool { \__xeCJK_add_fake_bold:n {#1} } } + \str_if_eq:nnTF {#1} { bf } + { \bool_if:NT \l__xeCJK_auto_fake_bold_bool { \__xeCJK_add_fake_bold:n {#1} } } { - \bool_if:NTF \l__xeCJK_AutoFakeSlant_bool + \bool_if:NTF \l__xeCJK_auto_fake_slant_bool { \bool_if:nT - { \__xeCJK_if_it_or_sl_p:n {#1} || - ( \str_if_eq_x_p:nn {#1} {bfit} && ! ( \__xeCJK_if_font_select_p:n {it} ) ) || - ( \str_if_eq_x_p:nn {#1} {bfsl} && ! ( \__xeCJK_if_font_select_p:n {sl} ) ) + { \__xeCJK_if_it_or_sl_p:n {#1} + || ( \str_if_eq_p:nn {#1} { bfit } + && ! ( \__xeCJK_if_font_select_p:n { it } ) ) + || ( \str_if_eq_p:nn {#1} { bfsl } + && ! ( \__xeCJK_if_font_select_p:n { sl } ) ) } { \__xeCJK_add_fake_slant:n {#1} } } - { \__xeCJK_if_it_or_sl:nT {#1} { \__xeCJK_map_it_sl:n {#1} } } + { \__xeCJK_if_it_or_sl:nT {#1} { \__xeCJK_map_it_sl:nn {#1} {#2} } } \bool_if:nT - { \l__xeCJK_AutoFakeBold_bool + { \l__xeCJK_auto_fake_bold_bool && ! ( \__xeCJK_if_it_or_sl_p:n {#1} ) - && ! ( \__xeCJK_if_font_select_p:n {bf} ) + && ! ( \__xeCJK_if_font_select_p:n { bf } ) } { \__xeCJK_add_fake_bold:n {#1} } } - \__xeCJK_add_font_if_new:nn {#1} * + \__xeCJK_add_font_if_new:nn {#2} { * } } -\cs_new_protected_nopar:Npn \__xeCJK_map_it_sl:n #1 +\cs_new_protected_nopar:Npn \__xeCJK_map_it_sl:nn #1#2 { \__xeCJK_if_map_font_select:nT {#1} { - \__xeCJK_add_font:nx {#1} { \__xeCJK_get_map_font:n {#1} } - \__xeCJK_if_font_select:nF {bf#1} - { \__xeCJK_add_font_if_new:nx {bf#1} { \__xeCJK_get_map_font:n {#1} } } + \__xeCJK_add_font:nx {#2} { \__xeCJK_get_map_font:n {#1} } + \__xeCJK_if_font_select:nF { bf #1 } + { \__xeCJK_add_font_if_new:nx { Bold #2 } { \__xeCJK_get_map_font:n {#1} } } } } \cs_new_nopar:Npn \__xeCJK_get_map_font:n #1 - { \tl_use:c { l__xeCJK_fontname_\str_if_eq_x:nnTF {#1} {it} {sl} {it} _tl } } -\prg_new_conditional:Npnn \__xeCJK_if_map_font_select:n #1 { p, T, F, TF } + { \exp_not:v { l__xeCJK_font_name_ \xeCJK_reverse:nnn {#1} { it } { sl } _tl } } +\prg_new_conditional:Npnn \__xeCJK_if_map_font_select:n #1 { p , T , F , TF } { \xeCJK_if_blank_x:nTF { \__xeCJK_get_map_font:n {#1} } - \prg_return_false: \prg_return_true: + { \prg_return_false: } { \prg_return_true: } } \cs_new_protected_nopar:Npn \__xeCJK_pass_features: { \prop_map_inline:Nn \g__xeCJK_features_id_prop { - \clist_if_empty:cF { l__xeCJK_fontfeat_##1_clist } + \clist_if_empty:cF { l__xeCJK_font_feat_##1_clist } { - \clist_put_right:Nx \l__xeCJK_pass_features_clist - { ##2Features = { \tl_use:c { l__xeCJK_fontfeat_##1_clist } } } + \clist_put_right:Nx \l__xeCJK_fontspec_options_clist + { ##2Features = { \exp_not:v { l__xeCJK_font_feat_##1_clist } } } } } \prop_map_inline:Nn \l__xeCJK_add_font_prop - { \clist_put_right:Nx \l__xeCJK_pass_features_clist { ##1 = { ##2 } } } - \xeCJK_if_blank_x:nF \l__xeCJK_monoscale_tl - { \clist_put_left:Nx \l__xeCJK_pass_features_clist \l__xeCJK_monoscale_tl } + { \clist_put_right:Nn \l__xeCJK_fontspec_options_clist { ##1 = { ##2 } } } } -\prop_new:N \g__xeCJK_family_prop \prop_new:N \g__xeCJK_family_name_prop -\prop_new:N \g__xeCJK_family_options_prop +\prop_new:N \g__xeCJK_family_font_name_prop +\prop_new:N \g__xeCJK_family_font_options_prop \cs_new_protected_nopar:Npn \__xeCJK_save_family_info: { \group_begin: - \clist_map_inline:Nn \g__xeCJK_CJK_subclass_clist + \seq_map_inline:Nn \g__xeCJK_CJK_sub_class_seq + { \clist_remove_all:Nn \l__xeCJK_font_options_clist {##1} } + \prop_gput:NVV \g__xeCJK_family_font_name_prop + \l__xeCJK_family_name_tl \l__xeCJK_font_name_tl + \prop_gput:NVV \g__xeCJK_family_font_options_prop + \l__xeCJK_family_name_tl \l__xeCJK_font_options_clist + \group_end: + } +\cs_new_protected_nopar:Npn \__xeCJK_set_sub_block_family: + { + \seq_map_inline:Nn \l__xeCJK_sub_key_seq { - \clist_remove_all:Nn \l__xeCJK_fontoptions_clist {##1} - \clist_remove_all:Nn \l__xeCJK_fontoptions_clist { ##1 = } + \tl_set:Nx \l__xeCJK_sub_family_tl { \l__xeCJK_family_name_tl/##1 } + \bool_if:cT { l__xeCJK_copy_##1_bool } { \__xeCJK_copy_sub_family:n {##1} } + \bool_if:cT { l__xeCJK_add_##1_bool } + { + \xeCJK_set_family:Vvv \l__xeCJK_sub_family_tl + { l__xeCJK_##1_font_options_clist } { l__xeCJK_##1_font_name_tl } + } } - \prop_gput:NVV \g__xeCJK_family_prop \l__xeCJK_family_aux_tl \l__xeCJK_fontname_tl - \prop_gput:NVV \g__xeCJK_family_options_prop \l__xeCJK_family_aux_tl \l__xeCJK_fontoptions_clist - \group_end: } -\cs_new_protected_nopar:Npn \__xeCJK_add_sub_block: +\cs_new_protected_nopar:Npn \__xeCJK_copy_sub_family:n #1 { - \clist_remove_duplicates:N \l__xeCJK_sub_key_clist - \clist_map_inline:Nn \l__xeCJK_sub_key_clist + \__xeCJK_check_family:V \l__xeCJK_sub_family_tl + \prop_get:NVNT \g__xeCJK_family_font_name_prop + \l__xeCJK_family_name_tl \l__xeCJK_tmpa_tl { - \tl_set:Nx \l__xeCJK_sub_family_tl { \l__xeCJK_family_aux_tl/##1 } - \bool_if:cT { l__xeCJK_copy_##1_bool } + \prop_gput:NVV \g__xeCJK_family_font_name_prop + \l__xeCJK_sub_family_tl \l__xeCJK_tmpa_tl + } + \prop_get:NVNT \g__xeCJK_family_font_options_prop + \l__xeCJK_family_name_tl \l__xeCJK_tmpa_clist + { + \clist_remove_all:Nn \l__xeCJK_tmpa_clist { #1 = * } + \prop_gput:NVV \g__xeCJK_family_font_options_prop + \l__xeCJK_sub_family_tl \l__xeCJK_tmpa_clist + } + \cs_gset_protected_nopar:cpx { \__xeCJK_family_csname:n { \l__xeCJK_sub_family_tl } } + { + \xeCJK_family_if_exist:xT { \l__xeCJK_family_name_tl } { - \__xeCJK_check_family:V \l__xeCJK_sub_family_tl - \prop_get:NVNT \g__xeCJK_family_prop \l__xeCJK_family_aux_tl \l__xeCJK_tmpa_tl - { \prop_gput:NVV \g__xeCJK_family_prop \l__xeCJK_sub_family_tl \l__xeCJK_tmpa_tl } - \prop_get:NVNT \g__xeCJK_family_options_prop \l__xeCJK_family_aux_tl \l__xeCJK_tmpa_clist - { - \clist_remove_all:Nn \l__xeCJK_tmpa_clist { ##1 = * } - \prop_gput:NVV \g__xeCJK_family_options_prop \l__xeCJK_sub_family_tl \l__xeCJK_tmpa_clist - } - \cs_gset_protected_nopar:cpx { __xeCJK/family/\l__xeCJK_sub_family_tl } + \prop_get:NnNT \exp_not:N \g__xeCJK_family_name_prop + { \l__xeCJK_family_name_tl } \exp_not:N \l__xeCJK_tmpa_tl { - \xeCJK_family_if_exist:xT { \l__xeCJK_family_aux_tl } - { - \prop_get:NnNT \exp_not:N \g__xeCJK_family_name_prop - { \l__xeCJK_family_aux_tl } \exp_not:N \l__xeCJK_tmpa_tl - { - \prop_gput:NnV \exp_not:N \g__xeCJK_family_name_prop - { \l__xeCJK_sub_family_tl } \exp_not:N \l__xeCJK_tmpa_tl - \cs_gset_protected_nopar:cpx { __xeCJK/family/\l__xeCJK_sub_family_tl } - \exp_not:n - { { - \exp_not:N \fontencoding { \c__xeCJK_encoding_tl } - \exp_not:N \fontfamily { \l__xeCJK_tmpa_tl } - \exp_not:N \selectfont - } } - } - } + \__xeCJK_gset_family_nfss_cs:xx + { \l__xeCJK_sub_family_tl } { \exp_not:N \l__xeCJK_tmpa_tl } } } - \bool_if:cT { l__xeCJK_add_##1_bool } - { - \xeCJK_set_family:xcc \l__xeCJK_sub_family_tl - { l__xeCJK_##1_fontfeat_clist } { l__xeCJK_##1_fontname_tl } - } } } \cs_new_protected_nopar:Npn \__xeCJK_copy_family:nn #1#2 @@ -1815,55 +1933,93 @@ \xeCJK_family_if_exist:xT {#2} { \tl_map_inline:nn - { \g__xeCJK_family_prop \g__xeCJK_family_options_prop \g__xeCJK_family_name_prop } - { \prop_get:NnNT ##1 {#2} \l__xeCJK_tmpa_tl { \prop_gput:NnV ##1 {#1} \l__xeCJK_tmpa_tl } } - \cs_gset_eq:cc { __xeCJK/family/#1 } { __xeCJK/family/#2 } + { + \g__xeCJK_family_name_prop + \g__xeCJK_family_font_name_prop + \g__xeCJK_family_font_options_prop + } + { + \prop_get:NnNT ##1 {#2} \l__xeCJK_tmpa_tl + { \prop_gput:NnV ##1 {#1} \l__xeCJK_tmpa_tl } + } + \cs_gset_eq:cc + { \__xeCJK_family_nfss_csname:n {#1} } + { \__xeCJK_family_nfss_csname:n {#2} } } } \cs_generate_variant:Nn \__xeCJK_copy_family:nn { xx } -\tl_set:Nn \l_xeCJK_font_coor_tl { __xeCJK/\l_xeCJK_family_tl/\f@series/\f@shape/\f@size } +\tl_new:N \l_xeCJK_current_font_tl +\tl_set:Nn \l_xeCJK_current_font_tl { \__xeCJK_font_csname:n { \l_xeCJK_family_tl } } +\cs_new_nopar:Npn \__xeCJK_font_csname:n #1 { xeCJK/#1/\f@series/\f@shape/\f@size } \cs_new_protected_nopar:Npn \xeCJK_select_font: { - \cs_if_exist_use:cF { \l_xeCJK_font_coor_tl } + \cs_if_exist_use:cF { \l_xeCJK_current_font_tl } + { + \tl_set:Nx \l__xeCJK_current_coor_tl { \l_xeCJK_current_font_tl } + \__xeCJK_family_use:x { \l_xeCJK_family_tl } + \xeCJK_font_gset_to_current:c { \l__xeCJK_current_coor_tl } + } + } +\cs_new_protected_nopar:Npn \xeCJK_select_font:x #1 + { + \cs_if_exist_use:cF { \__xeCJK_font_csname:n {#1} } { - \tl_set:Nx \l__xeCJK_current_coor_tl \l_xeCJK_font_coor_tl - \cs_if_exist_use:cT { __xeCJK/family/\l_xeCJK_family_tl } - { \exp_last_unbraced:NNV \cs_gset_eq:cN \l__xeCJK_current_coor_tl \tex_font:D } + \tl_set:Nx \l__xeCJK_current_coor_tl { \__xeCJK_font_csname:n {#1} } + \__xeCJK_family_use:x {#1} + \xeCJK_font_gset_to_current:c { \l__xeCJK_current_coor_tl } } } \cs_new_eq:NN \xeCJK@setfont \xeCJK_select_font: \cs_new_protected_nopar:Npn \__xeCJK_switch_font:nn #1#2 { - \str_if_eq_x:nnF {#1} {#2} + \str_if_eq:nnF {#1} {#2} { \__xeCJK_info:nxx { CJK-block } {#1} {#2} - \tl_remove_all:Nn \l_xeCJK_family_tl { /#1 } - \str_if_eq_x:nnF {#2} { CJK } + \str_if_eq:nnTF {#2} { CJK } + { \xeCJK_select_font: } + { \__xeCJK_block_select_font:n {#2} } + } + } +\__xeCJK_msg_new:nn { CJK-block } { Switch~from~block~'#1'~to~'#2'. } +\cs_new_protected_nopar:Npn \__xeCJK_block_select_font:n #1 + { + \cs_if_exist_use:cF { \__xeCJK_font_csname:n { \l_xeCJK_family_tl/#1 } } + { + \tl_set:Nx \l__xeCJK_current_coor_tl + { \__xeCJK_font_csname:n { \l_xeCJK_family_tl/#1 } } + \xeCJK_family_if_exist:xF { \l_xeCJK_family_tl/#1 } { - \tl_set:Nx \l__xeCJK_tmpa_tl \l_xeCJK_family_tl - \tl_put_right:Nx \l_xeCJK_family_tl { /#2 } - \xeCJK_family_if_exist:xF \l_xeCJK_family_tl + \__xeCJK_copy_family:xx { \l_xeCJK_family_tl/#1 } { - \xeCJK_family_if_exist:xTF { \CJKfamilydefault/#2 } - { \__xeCJK_copy_family:xx \l_xeCJK_family_tl { \CJKfamilydefault/#2 } } - { \__xeCJK_copy_family:xx \l_xeCJK_family_tl \l__xeCJK_tmpa_tl } + \cs_if_exist:cTF { \__xeCJK_family_csname:n { \CJKfamilydefault/#1 } } + { \CJKfamilydefault/#1 } { \l_xeCJK_family_tl } } } + \__xeCJK_family_use:x { \l_xeCJK_family_tl/#1 } + \xeCJK_font_gset_to_current:c { \l__xeCJK_current_coor_tl } } - \xeCJK_select_font: } -\__xeCJK_msg_new:nn { CJK-block } { Switch~from~block~'#1'~to~'#2'. } -\prg_new_protected_conditional:Npnn \xeCJK_family_if_exist:x #1 { T, F, TF } +\cs_new_nopar:Npn \__xeCJK_family_csname:n #1 { xeCJK/family/#1 } +\cs_new_nopar:Npn \__xeCJK_family_nfss_csname:n #1 { xeCJK/family/nfss/#1 } +\cs_new_nopar:Npn \__xeCJK_family_use:x #1 { \use:c { \__xeCJK_family_nfss_csname:n {#1} } } +\cs_new_protected_nopar:Npn \__xeCJK_gset_family_nfss_cs:xx #1#2 { - \cs_if_free:cTF { __xeCJK/family/#1 } - { \prg_return_false: } + \prop_gput:Nxx \g__xeCJK_family_name_prop {#1} {#2} + \cs_gset_protected_nopar:cpx { \__xeCJK_family_nfss_csname:n {#1} } { - \prop_get:NxNF \g__xeCJK_family_name_prop {#1} \l__xeCJK_family_name_tl - { \use:c { __xeCJK/family/#1 } } - \prg_return_true: + \exp_not:N \fontencoding { \c__xeCJK_encoding_tl } + \exp_not:N \fontfamily {#2} + \exp_not:N \selectfont } } -\cs_generate_variant:Nn \prop_get:NnNTF { Nx } +\cs_generate_variant:Nn \prop_gput:Nnn { Nxx } +\prg_new_protected_conditional:Npnn \xeCJK_family_if_exist:x #1 { T , F , TF } + { + \cs_if_exist:cTF { \__xeCJK_family_nfss_csname:n {#1} } + { \use_i:nn } + { \cs_if_exist_use:cTF { \__xeCJK_family_csname:n {#1} } } + { \prg_return_true: } { \prg_return_false: } + } \NewDocumentCommand \CJKfamily { t+ t- m } { \xeCJK_if_blank_x:nTF {#3} @@ -1878,39 +2034,37 @@ { \tl_set:Nx \l_xeCJK_family_tl {#3} \tl_set_eq:NN \xeCJK@family \l_xeCJK_family_tl - \IfBooleanT {#1} { \use:c { __xeCJK/family/#3 } } + \IfBooleanT {#1} { \__xeCJK_family_use:x {#3} } } { \__xeCJK_family_unknown_warning:x {#3} } } } \tex_ignorespaces:D } +\tl_new:N \l_xeCJK_family_tl +\tl_set:Nn \l_xeCJK_family_tl { \CJKfamilydefault } +\cs_new_protected_nopar:Npn \__xeCJK_gobble_CJKfamily: + { \cs_set_eq:NN \CJKfamily \__xeCJK_gobble_CJKfamily:wn } +\DeclareExpandableDocumentCommand \__xeCJK_gobble_CJKfamily:wn { t+ t- m } { } \cs_new_protected_nopar:Npn \xeCJK_family_if_exist_use:x #1 { \xeCJK_family_if_exist:xTF {#1} - { \use:c { __xeCJK/family/#1 } } + { \__xeCJK_family_use:x {#1} } { \__xeCJK_family_unknown_warning:x {#1} } } -\cs_new_protected_nopar:Npn \__xeCJK_family_unknown_warning:x #1 +\cs_new_protected_nopar:Npn \__xeCJK_family_unknown_warning:n #1 { - \seq_if_in:NxF \g__xeCJK_unknown_family_seq {#1} + \seq_if_in:NnF \g__xeCJK_unknown_family_seq {#1} { - \seq_gput_right:Nx \g__xeCJK_unknown_family_seq {#1} + \seq_gput_right:Nn \g__xeCJK_unknown_family_seq {#1} \__xeCJK_warning:nx { CJKfamily-Unknown } {#1} } } +\cs_generate_variant:Nn \__xeCJK_family_unknown_warning:n { x } \seq_new:N \g__xeCJK_unknown_family_seq \__xeCJK_msg_new:nn { CJKfamily-Unknown } { - Unknown~CJK~family~' - \str_case_x:nnn {#1} - { - \CJKrmdefault { \token_to_str:N \CJKrmdefault } - \CJKsfdefault { \token_to_str:N \CJKsfdefault } - \CJKttdefault { \token_to_str:N \CJKttdefault } - } - {#1} - '~is~ignored.\\\\ + Unknown~CJK~family~`\__xeCJK_msg_family_map:n {#1}'~is~being~ignored.\\\\ Try~to~use~ \str_case_x:nnn {#1} { @@ -1921,149 +2075,113 @@ { \token_to_str:N \setCJKfamilyfont {#1} } [...]{...}~to~define~it. } +\cs_new_nopar:Npn \__xeCJK_msg_family_map:n #1 + { + \str_case_x:nnn {#1} + { + \CJKrmdefault { \token_to_str:N \CJKrmdefault } + \CJKsfdefault { \token_to_str:N \CJKsfdefault } + \CJKttdefault { \token_to_str:N \CJKttdefault } + } + {#1} + } +\NewDocumentCommand \setCJKmainfont { O{} m } + { \xeCJK_set_family:xxx { \CJKrmdefault } {#1} {#2} } +\cs_new_eq:NN \setCJKromanfont \setCJKmainfont +\NewDocumentCommand \setCJKsansfont { O{} m } + { \xeCJK_set_family:xxx { \CJKsfdefault } {#1} {#2} } +\NewDocumentCommand \setCJKmonofont { O{} m } + { \xeCJK_set_family:xxx { \CJKttdefault } {#1} {#2} } +\@onlypreamble \setCJKmainfont +\@onlypreamble \setCJKmathfont +\@onlypreamble \setCJKsansfont +\@onlypreamble \setCJKmonofont +\@onlypreamble \setCJKromanfont \NewDocumentCommand \setCJKfamilyfont { m O{} m } - { \xeCJK_set_family:xnn {#1} {#2} {#3} } + { \xeCJK_set_family:xxx {#1} {#2} {#3} } \NewDocumentCommand \newCJKfontfamily { o m O{} m } { - \tl_set:Nx \l__xeCJK_family_aux_tl { \IfNoValueTF {#1} { \cs_to_str:N #2 } {#1} } - \xeCJK_set_family:xnn \l__xeCJK_family_aux_tl {#3} {#4} - \cs_new_protected_nopar:Npx #2 { \exp_not:N \CJKfamily { \l__xeCJK_family_aux_tl } } + \tl_set:Nx \l__xeCJK_tmpa_tl { \IfNoValueTF {#1} { \cs_to_str:N #2 } {#1} } + \cs_new_protected_nopar:Npx #2 { \CJKfamily { \l__xeCJK_tmpa_tl } } + \xeCJK_set_family:xxx { \l__xeCJK_tmpa_tl } {#3} {#4} } -\int_new:N \g__xeCJK_fontspec_int -\int_gdecr:N \g__xeCJK_fontspec_int \NewDocumentCommand \CJKfontspec { O{} m } { - \tl_set:Nx \l__xeCJK_CJKfontspec_id_tl { CJKfontspec/#1/#2/id } - \cs_if_free:cT \l__xeCJK_CJKfontspec_id_tl + \xeCJK_fontspec:xx {#1} {#2} + \tex_ignorespaces:D + } +\cs_new_protected_nopar:Npn \xeCJK_fontspec:nn #1#2 + { + \tl_set:Nx \l__xeCJK_tmpa_tl { \tl_to_str:n { CJKfontspec/#1/#2/id } } + \tl_if_exist:cF { \l__xeCJK_tmpa_tl } { - \int_gincr:N \g__xeCJK_fontspec_int - \tl_gset:Nx \g__xeCJK_family_spec_tl - { CJKfontspec ( \int_use:N \g__xeCJK_fontspec_int ) } - \xeCJK_set_family:xnn \g__xeCJK_family_spec_tl {#1} {#2} - \tl_gset:cx \l__xeCJK_CJKfontspec_id_tl \g__xeCJK_family_spec_tl + \tl_set:Nx \l__xeCJK_tmpb_tl + { CJKfontspec ( \int_eval:n { \g__xeCJK_family_int + \c_one } ) } + \tl_gset_eq:cN { \l__xeCJK_tmpa_tl } \l__xeCJK_tmpb_tl + \xeCJK_set_family:Vnn \l__xeCJK_tmpb_tl {#1} {#2} } - \exp_args:Nv \CJKfamily \l__xeCJK_CJKfontspec_id_tl - \tex_ignorespaces:D + \exp_args:Nc \CJKfamily { \l__xeCJK_tmpa_tl } } +\cs_generate_variant:Nn \xeCJK_fontspec:nn { VV , xx } \clist_new:N \g__xeCJK_default_features_clist \NewDocumentCommand \defaultCJKfontfeatures { m } { \clist_gset:Nn \g__xeCJK_default_features_clist {#1} } -\defaultCJKfontfeatures { Script = CJK } \@onlypreamble \defaultCJKfontfeatures \NewDocumentCommand \addCJKfontfeatures { m } { - \prop_if_in:NVTF \g__xeCJK_family_prop \l_xeCJK_family_tl + \xeCJK_add_font_features:x {#1} + \tex_ignorespaces:D + } +\cs_new_eq:NN \addCJKfontfeature \addCJKfontfeatures +\cs_new_protected_nopar:Npn \xeCJK_add_font_features:n #1 + { + \prop_get:NVNTF \g__xeCJK_family_font_name_prop \l_xeCJK_family_tl \l__xeCJK_tmpa_tl { - \group_begin: - \clist_set:Nx \l__xeCJK_tmpa_clist {#1} - \prop_get:NVN \g__xeCJK_family_prop \l_xeCJK_family_tl \l__xeCJK_tmpa_tl - \clist_map_inline:Nn \g__xeCJK_CJK_subclass_clist + \clist_set:Nn \l__xeCJK_tmpa_clist {#1} + \seq_map_function:NN + \g__xeCJK_CJK_sub_class_seq \__xeCJK_parse_sub_class_features:n + \prop_get:NVNT \g__xeCJK_family_font_options_prop + \l_xeCJK_family_tl \l__xeCJK_tmpb_clist { - \clist_if_in:NnT \l__xeCJK_tmpa_clist {##1} - { - \clist_remove_all:Nn \l__xeCJK_tmpa_clist {##1} - \prop_get:NxNF \g__xeCJK_family_prop { \l_xeCJK_family_tl/##1 } \l__xeCJK_tmpb_tl - { - \prop_get:NxNF \g__xeCJK_family_prop - { \CJKfamilydefault/##1 } \l__xeCJK_tmpb_tl - { \tl_set:Nx \l__xeCJK_tmpb_tl \l__xeCJK_tmpa_tl } - } - \clist_set:Nx \l__xeCJK_tmpa_clist - { ##1 = { [ \l__xeCJK_tmpa_clist ] { \l__xeCJK_tmpb_tl } } } - \clist_map_break: - } + \clist_concat:NNN + \l__xeCJK_tmpa_clist \l__xeCJK_tmpb_clist \l__xeCJK_tmpa_clist } - \prop_get:NVNF \g__xeCJK_family_options_prop \l_xeCJK_family_tl \l__xeCJK_tmpb_clist - { \clist_clear:N \l__xeCJK_tmpb_clist } - \clist_clear:N \l__xeCJK_tmpc_clist - \clist_map_inline:Nn \l__xeCJK_tmpb_clist - { - \clist_if_in:NnF \l__xeCJK_tmpa_clist {##1} - { \clist_put_right:Nn \l__xeCJK_tmpc_clist {##1} } - } - \clist_put_left:NV \l__xeCJK_tmpa_clist \l__xeCJK_tmpc_clist - \use:x - { \group_end: \CJKfontspec [ \l__xeCJK_tmpa_clist ] { \l__xeCJK_tmpa_tl } } + \xeCJK_fontspec:VV \l__xeCJK_tmpa_clist \l__xeCJK_tmpa_tl } { \__xeCJK_warning:n { addCJKfontfeature-ignored } } - \tex_ignorespaces:D } -\cs_new_eq:NN \addCJKfontfeature \addCJKfontfeatures +\cs_generate_variant:Nn \xeCJK_add_font_features:n { x } \__xeCJK_msg_new:nn { addCJKfontfeature-ignored } { \token_to_str:N \addCJKfontfeature (s)~ignored.\\\\ It~cannot~be~used~with~a~font~that~wasn't~selected~by~xeCJK. } -\NewDocumentCommand \setCJKmainfont { O{} m } - { \xeCJK_set_family:xnn \CJKrmdefault {#1} {#2} } -\cs_new_eq:NN \setCJKromanfont \setCJKmainfont -\NewDocumentCommand \setCJKsansfont { O{} m } - { \xeCJK_set_family:xnn \CJKsfdefault {#1} {#2} } -\tl_if_exist:NF \CJKrmdefault { \tl_set:Nn \CJKrmdefault { rm } } -\tl_if_exist:NF \CJKsfdefault { \tl_set:Nn \CJKsfdefault { sf } } -\tl_if_exist:NF \CJKttdefault { \tl_set:Nn \CJKttdefault { tt } } -\tl_if_exist:NF \CJKfamilydefault { \tl_set:Nn \CJKfamilydefault { \CJKrmdefault } } -\tl_new:c { __xeCJK/family/\CJKfamilydefault } -\AtEndOfPackage - { - \etex_protected:D \tl_put_right:Nn \normalfont { \CJKfamily \CJKfamilydefault } - \etex_protected:D \tl_put_right:Nn \rmfamily { \CJKfamily \CJKrmdefault } - \etex_protected:D \tl_put_right:Nn \sffamily { \CJKfamily \CJKsfdefault } - \etex_protected:D \tl_put_right:Nn \ttfamily { \CJKfamily \CJKttdefault } - \cs_set_eq:NN \reset@font \normalfont - } -\@onlypreamble \setCJKmainfont -\@onlypreamble \setCJKmathfont -\@onlypreamble \setCJKsansfont -\@onlypreamble \setCJKmonofont -\@onlypreamble \setCJKromanfont -\NewDocumentCommand \setCJKmathfont { O{} m } - { \xeCJK_set_family:xnn \c__xeCJK_math_tl {#1} {#2} } -\tl_const:Nn \c__xeCJK_math_tl { CJKmath } -\keys_define:nn { xeCJK / options } { CJKmath .bool_gset:N = \g__xeCJK_math_bool } -\NewDocumentCommand \xeCJKsetmathcode { m m m m } - { - \__xeCJK_check_num_range:nnNN {#1} {#2} \l__xeCJK_tmpa_int \l__xeCJK_tmpb_int - \int_set:Nn \l__xeCJK_tmpc_int { \__xeCJK_math_type:n {#3} } - \int_set:Nn \l_tmpa_int { \use:c { sym #4 } } - \xeCJK_int_until_do:nn { \l__xeCJK_tmpa_int > \l__xeCJK_tmpb_int } - { - \XeTeXmathcode \l__xeCJK_tmpa_int = \l__xeCJK_tmpc_int \l_tmpa_int \l__xeCJK_tmpa_int - \int_incr:N \l__xeCJK_tmpa_int - } - } -\cs_new_eq:NN \__xeCJK_math_type:n \mathchar@type -\cs_new_protected_nopar:Npn \xeCJK_set_mathfont: +\cs_new_protected_nopar:Npn \__xeCJK_parse_sub_class_features:n #1 { - \xeCJK_family_if_exist:xTF \c__xeCJK_math_tl - { \tl_set:Nx \l__xeCJK_tmpa_tl \c__xeCJK_math_tl } + \clist_if_in:NnT \l__xeCJK_tmpa_clist {#1} { - \xeCJK_family_if_exist:xTF \CJKfamilydefault - { \tl_set:Nx \l__xeCJK_tmpa_tl \CJKfamilydefault } - { \tl_set_eq:NN \l__xeCJK_tmpa_tl \q_no_value } - } - \prop_get:NVNT \g__xeCJK_family_name_prop \l__xeCJK_tmpa_tl \l__xeCJK_math_family_tl - { - \DeclareSymbolFont \c__xeCJK_math_tl \c__xeCJK_encoding_tl - \l__xeCJK_math_family_tl \mddefault \shapedefault - \SetSymbolFont \c__xeCJK_math_tl { bold } \c__xeCJK_encoding_tl - \l__xeCJK_math_family_tl \bfdefault \shapedefault - \clist_map_inline:nn { CJK, FullLeft, FullRight } + \clist_remove_all:Nn \l__xeCJK_tmpa_clist {#1} + \prop_get:NoNF \g__xeCJK_family_font_name_prop + { \l_xeCJK_family_tl/#1 } \l__xeCJK_tmpb_tl { - \clist_map_inline:cn { g__xeCJK_##1_range_clist } - { - \__xeCJK_set_char_class_aux:Nn \xeCJKsetmathcode {####1} - \mathalpha \c__xeCJK_math_tl - } + \prop_get:NxNF \g__xeCJK_family_font_name_prop + { \CJKfamilydefault/#1 } \l__xeCJK_tmpb_tl + { \tl_set_eq:NN \l__xeCJK_tmpb_tl \l__xeCJK_tmpa_tl } } + \clist_set:Nx \l__xeCJK_tmpa_clist + { #1 = { [ \exp_not:V \l__xeCJK_tmpa_clist ] { \exp_not:V \l__xeCJK_tmpb_tl } } } + \clist_map_break: } } -\__xeCJK_AtEndPreamble:n +\cs_generate_variant:Nn \prop_get:NnNF { Nx } +\__xeCJK_at_end_preamble:n { - \normalfont - \prop_if_empty:NTF \g__xeCJK_family_prop + \prop_if_empty:NTF \g__xeCJK_family_font_name_prop { \__xeCJK_warning:n { no-CJKfamily } } - { \bool_if:NT \g__xeCJK_math_bool { \xeCJK_set_mathfont: } } + { + \CJKfamily { \CJKfamilydefault } + \bool_if:NT \g__xeCJK_math_bool { \xeCJK_set_mathfont: } + } } \__xeCJK_msg_new:nn { no-CJKfamily } { @@ -2072,140 +2190,223 @@ \token_to_str:N \xeCJKmainfont[...]{...}\\\\ in~the~preamble~to~declare~the~main~CJKfamily.\\ } -\fp_new:N \g__xeCJK_monoscale_fp -\fp_set_eq:NN \g__xeCJK_monoscale_fp \c_one_fp -\dim_new:N \g__xeCJK_exspace_dim -\NewDocumentCommand \setCJKmonoscale { } +\keys_define:nn { xeCJK / options } { CJKmath .bool_gset:N = \g__xeCJK_math_bool } +\NewDocumentCommand \setCJKmathfont { O{} m } + { \xeCJK_set_family:xxx { \c__xeCJK_math_tl } {#1} {#2} } +\tl_const:Nn \c__xeCJK_math_tl { CJKmath } +\cs_new_protected_nopar:Npn \xeCJK_set_mathfont: { - \CJKflexiblespacing - \xeCJK_set_monoscale: - \addCJKfontfeatures { Scale = \fp_use:N \g__xeCJK_monoscale_fp } + \xeCJK_family_if_exist:xTF { \c__xeCJK_math_tl } + { \tl_set:Nx \l__xeCJK_tmpa_tl { \c__xeCJK_math_tl } } + { + \xeCJK_family_if_exist:xTF { \CJKfamilydefault } + { \tl_set:Nx \l__xeCJK_tmpa_tl { \CJKfamilydefault } } + { \use_none:nnnnn } + } + \prop_get:NVNT \g__xeCJK_family_name_prop \l__xeCJK_tmpa_tl \l__xeCJK_tmpb_tl + { + \tl_const:Nx \c__xeCJK_math_family_tl { \l__xeCJK_tmpb_tl } + \DeclareSymbolFont \c__xeCJK_math_tl + \c__xeCJK_encoding_tl \c__xeCJK_math_family_tl \mddefault \shapedefault + \SetSymbolFont \c__xeCJK_math_tl { bold } + \c__xeCJK_encoding_tl \c__xeCJK_math_family_tl \bfdefault \shapedefault + \int_const:Nn \c_xeCJK_math_fam_int { \use:c { sym \c__xeCJK_math_tl } } + \clist_concat:NNN + \l__xeCJK_tmpa_clist \c__xeCJK_CJK_chars_clist \c__xeCJK_FullLeft_chars_clist + \clist_concat:NNN + \l__xeCJK_tmpa_clist \l__xeCJK_tmpa_clist \c__xeCJK_FullRight_chars_clist + \clist_map_inline:Nn \l__xeCJK_tmpa_clist + { + \__xeCJK_set_char_class_aux:Nnw \xeCJK_gset_mathcode:nnnn {##1} + { \c_seven } { \c_xeCJK_math_fam_int } + } + } } -\cs_new_protected_nopar:Npn \xeCJK_set_monoscale: +\cs_new_protected_nopar:Npn \xeCJK_gset_mathcode:nnnn #1#2#3#4 { - \group_begin: - \fontfamily \ttdefault \selectfont - \fp_gset:Nn \g__xeCJK_monoscale_fp - { \dim_to_fp:n { \c_two \tex_fontdimen:D \c_two \tex_font:D } / ( \f@size ) } - \group_end: + \__xeCJK_check_num_range:nnNN {#1} {#2} \l__xeCJK_tmpa_int \l__xeCJK_tmpb_int + \xeCJK_int_until_do:nn { \l__xeCJK_tmpa_int > \l__xeCJK_tmpb_int } + { + \tex_global:D \XeTeXmathcode \l__xeCJK_tmpa_int = #3 ~ #4 \l__xeCJK_tmpa_int + \int_incr:N \l__xeCJK_tmpa_int + } } -\NewDocumentCommand \setCJKmonoexspace { } { \xeCJK_set_monoexspace: } -\cs_new_protected_nopar:Npn \xeCJK_set_monoexspace: +\NewDocumentCommand \xeCJKVerbAddon { } { - \group_begin: - \fontfamily \ttdefault \selectfont - \dim_gset:Nn \g__xeCJK_exspace_dim - { - \c_two \tex_fontdimen:D \c_two \tex_font:D - - \fp_to_dim:n { \g__xeCJK_monoscale_fp * ( \f@size ) } - } - \group_end: + \int_compare:nNnF \etex_currentgrouplevel:D = \c_zero + { + \__xeCJK_set_verb_exspace: + \bool_if:NF \l__xeCJK_verb_addon_bool + { + \bool_set_true:N \l__xeCJK_verb_addon_bool + \__xeCJK_set_char_class_eq:nn { CJK } { FullLeft } + \__xeCJK_set_char_class_eq:nn { CJK } { FullRight } + \__xeCJK_set_char_class_eq:nn { Default } { HalfLeft } + \__xeCJK_set_char_class_eq:nn { Default } { HalfRight } + \__xeCJK_set_char_class_eq:nn { Default } { NormalSpace } + \xeCJKsetup { xCJKecglue = false } + \cs_set_protected_nopar:Npn \CJKglue + { \skip_horizontal:N \g__xeCJK_verb_exspace_skip } + \cs_set_protected_nopar:Npn \CJKecglue + { \skip_horizontal:N 0.5 \g__xeCJK_verb_exspace_skip } + \cs_set_eq:NN \xeCJK_check_for_glue: \CJKecglue + \cs_set_eq:NN \xeCJK_ignore_spaces:w \CJKecglue + \skip_set:Nn \tex_rightskip:D { \c_zero_dim plus 1 fil } + } + } } -\NewDocumentCommand \CJKfixedspacing { } +\bool_new:N \l__xeCJK_verb_addon_bool +\cs_new_eq:NN \CJKfixedspacing \xeCJKVerbAddon +\__xeCJK_after_preamble:n + { \xeCJK_cs_add:Nnn \verbatim@font { } { \xeCJKVerbAddon } } +\cs_new_protected_nopar:Npn \__xeCJK_set_verb_exspace: { - \bool_if:NF \l__xeCJK_fixed_spacing_bool + \tl_if_exist:cTF { xeCJK/verb/\curr@fontshape/\f@size } + { + \skip_gset:Nn \g__xeCJK_verb_exspace_skip + { \tl_use:c { xeCJK/verb/\curr@fontshape/\f@size } } + } { - \bool_set_true:N \l__xeCJK_fixed_spacing_bool - \tl_set_eq:NN \l__xeCJK_flexible_punctstyle_tl \l_xeCJK_punctstyle_tl - \bool_set_eq:NN \l__xeCJK_fixed_xecglue_bool \l__xeCJK_xecglue_bool - \cs_set_eq:NN \__xeCJK_flexible_ecglue: \CJKecglue - \cs_set_eq:NN \__xeCJK_flexible_cjkglue: \CJKglue - \xeCJK_set_monoexspace: - \xeCJKsetup + \skip_gset:Nn \g__xeCJK_verb_exspace_skip { - PunctStyle = plain , - CJKglue = { \skip_horizontal:N \g__xeCJK_exspace_dim } , - CJKecglue = { \skip_horizontal:n { .5\g__xeCJK_exspace_dim } } , - xCJKecglue = false , + \dim_max:nn + { \c_zero_dim } + { \c_two \tex_fontdimen:D \c_two \tex_font:D - \f@size pt } } + \tl_gset:cV { xeCJK/verb/\curr@fontshape/\f@size } \g__xeCJK_verb_exspace_skip } } -\NewDocumentCommand \CJKflexiblespacing { } +\skip_new:N \g__xeCJK_verb_exspace_skip +\cs_new_protected_nopar:Npn \xeCJK_visible_space_fallback: + { { + \cs_if_exist_use:cF { xeCJK/space/\curr@fontshape/\f@size } + { \xeCJK_set_visible_space_font: } + \textvisiblespace + } } +\AtEndOfPackage { - \bool_if:NT \l__xeCJK_fixed_spacing_bool + \xeCJK_cs_add:Nnn \fontspec_visible_space: { \scan_stop: } { } + \cs_gset_eq:NN \fontspec_visible_space_fallback: \xeCJK_visible_space_fallback: + } +\cs_new_protected_nopar:Npn \xeCJK_set_visible_space_font: + { + \tl_set:Nx \l__xeCJK_current_coor_tl { xeCJK/space/\curr@fontshape/\f@size } + \dim_set:Nn \l__xeCJK_tmp_dim { \tex_fontdimen:D \c_two \tex_font:D } + \fontencoding { \g_fontspec_encoding_tl } + \fontfamily { lmtt } + \selectfont + \dim_compare:nNnF \l__xeCJK_tmp_dim = { \tex_fontdimen:D \c_two \tex_font:D } { - \bool_set_false:N \l__xeCJK_fixed_spacing_bool - \exp_args:Nx \xeCJKsetup + \fontsize { - PunctStyle = { \l__xeCJK_flexible_punctstyle_tl } , - CJKglue = { \exp_not:o { \__xeCJK_flexible_cjkglue: } } , - CJKecglue = { \exp_not:o { \__xeCJK_flexible_ecglue: } } , - xCJKecglue = { \bool_if:NTF \l__xeCJK_fixed_xecglue_bool { true } { false } } , + \dim_eval:n + { + \f@size pt * \dim_ratio:nn + { \l__xeCJK_tmp_dim } { \tex_fontdimen:D \c_two \tex_font:D } + } } + { \f@baselineskip } + \selectfont } + \xeCJK_font_gset_to_current:c { \l__xeCJK_current_coor_tl } } -\bool_new:N \l__xeCJK_fixed_spacing_bool -\__xeCJK_AfterPreamble:n { \tl_put_right:Nn \verbatim@font \CJKfixedspacing } -\NewDocumentCommand \setCJKmonofont { s t+ O{} m } +\keys_define:nn { xeCJK / options } { - \IfBooleanTF {#1} - { \xeCJK_set_family:xnn \CJKttdefault { Mono = Scale, #3 } {#4} } + LocalConfig .choice: , + LocalConfig / false .code:n = + { \bool_gset_false:N \g__xeCJK_config_bool } , + LocalConfig / true .code:n = { - \IfBooleanTF {#2} - { \xeCJK_set_family:xnn \CJKttdefault { Mono = Exspace, #3 } {#4} } - { \xeCJK_set_family:xnn \CJKttdefault {#3} {#4} } - } + \bool_gset_true:N \g__xeCJK_config_bool + \tl_gset:Nn \g__xeCJK_config_name_tl { xeCJK } + } , + LocalConfig / unknown .code:n = + { + \bool_gset_true:N \g__xeCJK_config_bool + \tl_gset:Nx \g__xeCJK_config_name_tl { xeCJK - \l_keys_value_tl } + } , + LocalConfig .default:n = { true } + } +\tl_new:N \g__xeCJK_config_name_tl +\bool_new:N \g__xeCJK_config_bool +\keys_define:nn { xeCJK / options } + { + CJKnumber .bool_gset:N = \g__xeCJK_number_bool , + indentfirst .bool_gset:N = \g__xeCJK_indent_bool , + normalindentfirst .meta:n = { indentfirst = false } } -\bool_new:N \g__xeCJK_indent_bool \keys_define:nn { xeCJK / options } { - CJKnumber .bool_set:N = \g__xeCJK_number_bool , - indentfirst .bool_set:N = \g__xeCJK_indent_bool , - normalindentfirst .meta:n = { indentfirst = false } , quiet .code:n = { \msg_redirect_module:nnn { xeCJK } { warning } { info } \msg_redirect_module:nnn { xeCJK } { info } { none } \xeCJK_if_package_loaded:nF { fontspec } { \PassOptionsToPackage { quiet } { fontspec } } - }, + } , silent .code:n = { \msg_redirect_module:nnn { xeCJK } { warning } { none } \msg_redirect_module:nnn { xeCJK } { info } { none } \xeCJK_if_package_loaded:nF { fontspec } { \PassOptionsToPackage { silent } { fontspec } } - }, + } , unknown .code:n = { \xeCJK_if_package_loaded:nTF { fontspec } { \__xeCJK_error:nx { key-unknown } { \l_keys_key_tl } } { \PassOptionsToPackage { \l_keys_key_tl } { fontspec } } - }, + } } \__xeCJK_msg_new:nn { key-unknown } { Sorry,~but~\l__keys_module_tl \ does~not~have~a~key~called~'#1'.\\\\ The~key~'#1'~is~being~ignored. } +\cs_new_nopar:Npn \CJKsymbol #1 {#1} +\cs_new_nopar:Npn \CJKpunctsymbol #1 {#1} \keys_set:nn { xeCJK / options } { - CJKglue = { \skip_horizontal:n { \c_zero_skip \@plus .08\baselineskip } } , + CJKglue = { \skip_horizontal:n { \c_zero_dim plus 0.08 \tex_baselineskip:D } } , CJKecglue = \c_space_token , xCJKecglue = false , CheckSingle = false , CJKspace = false , CJKmath = false , + CJKnumber = false , xeCJKactive = true , + LocalConfig = true , indentfirst = true , - EmboldenFactor = 4 , - SlantFactor = .167 , + EmboldenFactor = 4 , + SlantFactor = 0.167 , PunctStyle = quanjiao , KaiMingPunct = { ^^^^3002 ^^^^ff0e ^^^^ff1f ^^^^ff01 } , LongPunct = { ^^^^2014 ^^^^2015 ^^^^2500 ^^^^2025 ^^^^2026 } , MiddlePunct = { ^^^^2014 ^^^^2015 ^^^^2500 ^^^^00b7 ^^^^30fb ^^^^ff65 } , - AllowBreakBetweenPuncts = false , + AllowBreakBetweenPuncts = false } -\cs_new_nopar:Npn \CJKsymbol #1 {#1} -\cs_new_nopar:Npn \CJKpunctsymbol #1 {#1} +\defaultCJKfontfeatures { Script = CJK } \ProcessKeysOptions { xeCJK / options } \RequirePackage { fontspec } [ 2011/09/13 ] \tl_const:Nx \c__xeCJK_encoding_tl { \g_fontspec_encoding_tl } -\bool_if:NT \g__xeCJK_indent_bool +\bool_if:NT \g__xeCJK_indent_bool { \RequirePackage { indentfirst } } +\keys_define:nn { xeCJK / options } + { + LocalConfig .code:n = { \__xeCJK_warning:nx { option-invalid } { \l_keys_key_tl } } , + CJKnumber .code:n = { \__xeCJK_warning:nx { option-invalid } { \l_keys_key_tl } } , + indentfirst .code:n = { \__xeCJK_warning:nx { option-invalid } { \l_keys_key_tl } } + } +\__xeCJK_msg_new:nn { option-invalid } { - \cs_set_eq:NN \@afterindentfalse \@afterindenttrue - \@afterindenttrue + The~`#1'~option~only~can~be~set~in~the~optional~argument~to~the\\ + \token_to_str:N \usepackage \ command~when~xeCJK~is~being~loaded.\\\\ + Please~do~not~set~it~via~the~\token_to_str:N \xeCJKsetup \ command. } +\tl_if_exist:NF \CJKrmdefault { \tl_gset:Nn \CJKrmdefault { rm } } +\tl_if_exist:NF \CJKsfdefault { \tl_gset:Nn \CJKsfdefault { sf } } +\tl_if_exist:NF \CJKttdefault { \tl_gset:Nn \CJKttdefault { tt } } +\tl_if_exist:NF \CJKfamilydefault { \tl_gset:Nn \CJKfamilydefault { \CJKrmdefault } } +\tl_new:c { \__xeCJK_family_csname:n { \CJKfamilydefault } } \NewDocumentCommand \xeCJKsetup { m } { \keys_set:nn { xeCJK / options } {#1} @@ -2216,28 +2417,59 @@ \NewDocumentCommand \xeCJKsetslantfactor { m } { \xeCJKsetup { SlantFactor = {#1} } } \NewDocumentCommand \punctstyle { m } { \xeCJKsetup { PunctStyle = {#1} } } -\NewDocumentCommand \xeCJKplainchr { } { \punctstyle { plain } } +\NewDocumentCommand \xeCJKplainchr { } { \xeCJKsetup { PunctStyle = plain } } \NewDocumentCommand \CJKsetecglue { m } { \xeCJKsetup { CJKecglue = {#1} } } \cs_new_eq:NN \xeCJKsetecglue \CJKsetecglue -\cs_new_protected_nopar:Npn \__xeCJK_fix_itcorr: +\NewDocumentCommand \CJKspace { } { \xeCJKsetup { CJKspace = true } } +\NewDocumentCommand \CJKnospace { } { \xeCJKsetup { CJKspace = false } } +\NewDocumentCommand \xeCJKallowbreakbetweenpuncts { } + { \xeCJKsetup { AllowBreakBetweenPuncts = true } } +\NewDocumentCommand \xeCJKnobreakbetweenpuncts { } + { \xeCJKsetup { AllowBreakBetweenPuncts = false } } +\xeCJK_cs_add:Nnn \rmfamily { \CJKfamily { \CJKrmdefault } } { } +\xeCJK_cs_add:Nnn \sffamily { \CJKfamily { \CJKsfdefault } } { } +\xeCJK_cs_add:Nnn \ttfamily { \CJKfamily { \CJKttdefault } } { } +\xeCJK_cs_add:Nnn \normalfont { \CJKfamily { \CJKfamilydefault } } { } +\cs_set_eq:NN \reset@font \normalfont +\xeCJK_cs_add:Nnn \fontspec_init: { \__xeCJK_gobble_CJKfamily: } { } +\cs_new_eq:NN \xeCJK@fix@penalty \fix@penalty +\xeCJK_cs_patch:Nnn \xeCJK@fix@penalty \@@italiccorr \xeCJK@patch@italiccorr +\xeCJK_cs_patch:Nnn \sw@slant \fix@penalty \xeCJK@fix@penalty +\cs_new_protected_nopar:Npn \xeCJK@patch@italiccorr { - \scan_stop: - \xeCJK_if_last_node:nTF { default } + \int_compare:nNnTF \XeTeXinterchartokenstate > \c_zero { - \tex_unkern:D \tex_unkern:D - \__xeCJK_itcorr_aux - { \xeCJK_make_node:n { default_itcorr } } + \xeCJK_if_last_node:nTF { default } + { + \tex_unkern:D \tex_unkern:D \@@italiccorr + { \xeCJK_make_node:n { default } } + } + { + \xeCJK_if_last_node:nTF { CJK } + { + \tex_unkern:D \tex_unkern:D \@@italiccorr + { \xeCJK_make_node:n { CJK } } \use:n + } + { + \xeCJK_if_last_node:nTF { CJK-space } + { + \tex_unkern:D \tex_unkern:D \@@italiccorr + { \xeCJK_make_node:n { CJK-space } } \use:n + } + { \@@italiccorr \use_none:n } + } + { + \exp_after:wN \exp_after:wN \exp_after:wN + \exp_after:wN \exp_after:wN \exp_after:wN \exp_after:wN + \exp_after:wN \exp_after:wN \exp_after:wN \exp_after:wN + \exp_after:wN \exp_after:wN \exp_after:wN \exp_after:wN + \xeCJK_ignore_spaces:w + } + } } - { \__xeCJK_itcorr_aux } - } -\cs_new_eq:NN \__xeCJK_itcorr_aux \/ -\cs_set_protected_nopar:Npn \/ - { - \int_compare:nNnTF \XeTeXinterchartokenstate > \c_zero - { \__xeCJK_fix_itcorr: } { \__xeCJK_itcorr_aux } + { \@@italiccorr } } -\cs_set_eq:NN \@@italiccorr \/ -\__xeCJK_AfterEndPreamble:n +\__xeCJK_after_end_preamble:n { \int_compare:nNnF { \c_three + ( \seq_count:N \g__xeCJK_class_seq ) } = \xe@alloc@intercharclass @@ -2252,32 +2484,30 @@ \cs_new_protected_nopar:Npn \__xeCJK_set_others_toks:n #1 { \int_set:Nn \c__xeCJK_Others_class_int {#1} - \clist_map_inline:Nn \g__xeCJK_CJK_class_clist - { - \__xeCJK_copy_inter_class_toks:nnnn {##1} { Others } {##1} { NormalSpace } - \__xeCJK_copy_inter_class_toks:nnnn { Others } {##1} { NormalSpace } {##1} - \exp_args:Nnnx \__xeCJK_app_inter_class_toks:nnn {##1} { Others } - { \__xeCJK_get_inter_class_toks:nn { Default } { Others } } - \exp_args:Nnnx \__xeCJK_pre_inter_class_toks:nnn { Others } {##1} - { \__xeCJK_get_inter_class_toks:nn { Others } { Default } } + \seq_map_inline:Nn \g__xeCJK_CJK_class_seq + { + \xeCJK_copy_inter_class_toks:nnnn {##1} { Others } {##1} { NormalSpace } + \xeCJK_copy_inter_class_toks:nnnn { Others } {##1} { NormalSpace } {##1} + \xeCJK_app_inter_class_toks:nnx {##1} { Others } + { \xeCJK_get_inter_class_toks:nn { Default } { Others } } + \xeCJK_pre_inter_class_toks:nnx { Others } {##1} + { \xeCJK_get_inter_class_toks:nn { Others } { Default } } \xeCJK_if_blank_x:nT - { \__xeCJK_get_inter_class_toks:nn { Others } { Boundary } } + { \xeCJK_get_inter_class_toks:nn { Others } { Boundary } } { - \__xeCJK_copy_inter_class_toks:nnnn + \xeCJK_copy_inter_class_toks:nnnn { Others } { Boundary } { Default } { Boundary } } \xeCJK_if_blank_x:nT - { \__xeCJK_get_inter_class_toks:nn { Boundary } { Others } } + { \xeCJK_get_inter_class_toks:nn { Boundary } { Others } } { - \__xeCJK_copy_inter_class_toks:nnnn + \xeCJK_copy_inter_class_toks:nnnn { Boundary } { Others } { Boundary } { Default } } } } -\int_new:N \c__xeCJK_Others_class_int -\cs_new_protected_nopar:Npn \__xeCJK_patch:Nnn #1#2#3 - { \tl_put_left:Nn #1 {#2} \tl_put_right:Nn #1 {#3} } -\__xeCJK_AfterPreamble:n +\cs_new_eq:NN \c__xeCJK_Others_class_int \l__xeCJK_tmpa_int +\__xeCJK_after_preamble:n { \tl_map_inline:nn { @@ -2285,123 +2515,121 @@ \textquoteleft \textquoteright \textquotedblleft \textquotedblright } { - \__xeCJK_patch:Nnn #1 - { \__xeCJK_group_begin: \makexeCJKinactive } - { \__xeCJK_group_end: } + \xeCJK_cs_add:Nnn #1 + { \__xeCJK_group_begin: \makexeCJKinactive } { \__xeCJK_group_end: } } - \__xeCJK_patch:Nnn \tipaencoding { \makexeCJKinactive } { } - \cs_set_eq:NN \__xeCJK_aux_r \r - \cs_set_protected_nopar:Npn \r #1 { { \makexeCJKinactive \__xeCJK_aux_r {#1} } } + \xeCJK_cs_add:Nnn \tipaencoding { \makexeCJKinactive } { } + \cs_new_eq:NN \__xeCJK_aux_r:n \r + \cs_set_nopar:Npn \r #1 { { \makexeCJKinactive \__xeCJK_aux_r:n {#1} } } \xeCJK_if_package_loaded:nT { pifont } - { - \RenewDocumentCommand \Pifont { m } - { \makexeCJKinactive \usefont {U} {#1} {m} {n} } - } + { \xeCJK_cs_add:Nnn \Pifont { \makexeCJKinactive } { } } } \cs_new_eq:NN \__xeCJK_group_begin: \group_begin: \cs_new_eq:NN \__xeCJK_group_end: \group_end: -\__xeCJK_AfterEndPreamble:n +\__xeCJK_after_end_preamble:n { - \bool_if:nT - { - \xeCJK_if_package_loaded_p:n { hyperref } && - \tl_if_exist_p:N \pdfstringdefPreHook - } + \xeCJK_if_package_loaded:nT { hyperref } { \tl_gput_right:Nn \pdfstringdefPreHook { - \cs_set_eq:NN \makexeCJKinactive \prg_do_nothing: - \cs_set_eq:NN \__xeCJK_group_begin: \prg_do_nothing: - \cs_set_eq:NN \__xeCJK_group_end: \prg_do_nothing: - \cs_set_eq:NN \CJKfamily \use_none:n + \__xeCJK_gobble_CJKfamily: + \xeCJK_cs_clear:N \makexeCJKinactive + \xeCJK_cs_clear:N \__xeCJK_group_begin: + \xeCJK_cs_clear:N \__xeCJK_group_end: } } } -\tl_set:cn { ver@CJK.sty } { 2100/01/01 } -\cs_if_free:NT \CJK@ifundefined +\__xeCJK_after_end_preamble:n + { + \bool_if:nT + { \xeCJK_if_package_loaded_p:n { cprotect } && \cs_if_exist_p:N \icprotect } + { \exp_after:wN \tex_let:D \cs:w cprotect \cs_end: \icprotect } + } +\tl_set:cn { ver@CJK.sty } { 9999/99/99 } +\tl_set_eq:cc { ver@CJKpunct.sty } { ver@CJK.sty } +\cs_if_exist:NF \CJK@ifundefined { \cs_set_eq:NN \CJK@ifundefined \cs_if_free:NTF } \NewDocumentCommand \xeCJKcaption { o m } { \IfNoValueF {#1} { \XeTeXdefaultencoding "#1" } - \cs_set_nopar:Npx \__xeCJK_reset_at_catcode: + \use:x { - \exp_not:n { \char_set_catcode:nn { `\@ } } - { \char_value_catcode:n { `\@ } } + \char_set_catcode_letter:n { 64 } + \file_input:n { #2.cpx } + \char_set_catcode:nn { 64 } { \char_value_catcode:n { 64 } } } - \char_set_catcode_letter:N \@ - \file_input:n { #2.cpx } - \__xeCJK_reset_at_catcode: \XeTeXdefaultencoding "UTF-8" } -\cs_new_protected_nopar:Npn \xeCJK_ULprepunctchar:n #1 - { - { \makexeCJKinactive \CJKpunctsymbol {#1} \xeCJK_no_break: } - \tex_ignorespaces:D - } -\cs_new_protected_nopar:Npn \xeCJK_ULpostpunctchar:n #1 - { - { \makexeCJKinactive \CJKpunctsymbol {#1} } - \xeCJK_ignorespaces: - } -\cs_new_protected_nopar:Npn \xeCJK_ULroutines: +\cs_new_protected_nopar:Npn \xeCJK_hook_for_ulem: { - \__xeCJK_inter_class_toks:nnn { Default } { CJK } { \CJKecglue \CJKsymbol } - \__xeCJK_inter_class_toks:nnn { HalfLeft } { CJK } { \CJKsymbol } - \__xeCJK_inter_class_toks:nnn { HalfRight } { CJK } { \CJKecglue \CJKsymbol } - \__xeCJK_inter_class_toks:nnn { Boundary } { CJK } { \xeCJK_Boundary_and_CJK: } - \clist_map_inline:nn { Default, HalfLeft, HalfRight, Boundary } + \bool_if:NF \l__xeCJK_ulem_hook_used_bool { - \__xeCJK_inter_class_toks:nnn {##1} { FullLeft } { \xeCJK_ULprepunctchar:n } - \__xeCJK_inter_class_toks:nnn {##1} { FullRight } { \xeCJK_ULpostpunctchar:n } + \bool_set_true:N \l__xeCJK_ulem_hook_used_bool + \xeCJK_cs_clear:N \__xeCJK_CJK_FullLeft_glue: + \cs_set_protected_nopar:Npn \__xeCJK_FullLeft_ulem_hook: { { \CJKglue } } + \xeCJK_swap_cs:NN \CJKsymbol \__xeCJK_ulem_CJKsymbol:N + \xeCJK_swap_cs:NN \CJKpunctsymbol \__xeCJK_ulem_CJKpunctsymbol:N } - \__xeCJK_UL_subclass_patch_tl } -\__xeCJK_AfterPreamble:n +\bool_new:N \l__xeCJK_ulem_hook_used_bool +\__xeCJK_after_preamble:n { - \cs_if_exist:NT \UL@hook + \xeCJK_if_package_loaded:nT { ulem } { - \addto@hook \UL@hook + \xeCJK_cs_gclear:N \__xeCJK_FullLeft_ulem_hook: + \xeCJK_pre_inter_class_toks:nnn { Boundary } { FullLeft } + { \__xeCJK_FullLeft_ulem_hook: } + \cs_if_exist:NTF \XeTeX@CJKfntef@hook { - \cs_set_eq:NN \__xeCJK_UL_CJKsymbol \CJKsymbol - \cs_set_eq:NN \__xeCJK_UL_CJKpunctsymbol \CJKpunctsymbol - \cs_set_protected_nopar:Npn \CJKsymbol #1 - { - { \xeCJK_select_font: \__xeCJK_UL_CJKsymbol {#1} } - { \xeCJK_make_node:n { CJK } } \xeCJK_ignorespaces: - } - \cs_set_protected_nopar:Npn \CJKpunctsymbol #1 - { { \xeCJK_select_font: \__xeCJK_UL_CJKpunctsymbol {#1} } } - \xeCJK_ULroutines: + \xeCJK_cs_gclear:N \CJKf@global + \AtBeginEnvironment + { CJKfilltwosides } { \cs_set_eq:NN \CJKglue \tex_hfil:D } + \cs_set_protected_nopar:Npn \XeTeX@CJKfntef@hook + { \xeCJK_select_font: \makexeCJKinactive } } - } - \cs_if_exist:NT \XeTeX@CJKfntef@hook - { - \cs_set_nopar:Npn \XeTeX@CJKfntef@hook - { \xeCJK_select_font: \makexeCJKinactive } + { \RequirePackage { CJKulem } } + \addto@hook \UL@hook { \xeCJK_hook_for_ulem: } } } +\cs_new_protected_nopar:Npn \__xeCJK_ulem_CJKsymbol:N #1 + { + { \__xeCJK_ulem_CJKsymbol:N {#1} } + { \xeCJK_make_node:n { CJK } } \xeCJK_ignore_spaces:w + } +\cs_new_protected_nopar:Npn \__xeCJK_ulem_CJKpunctsymbol:N #1 + { { \__xeCJK_ulem_CJKpunctsymbol:N {#1} } \tex_ignorespaces:D } \bool_if:NT \g__xeCJK_number_bool { \tl_set:Nn \CJK@UnicodeEnc { UTF8 } - \cs_set_protected_nopar:Npn \CJKaddEncHook #1#2 - { \cs_set_nopar:cpn { __xeCJK_enc_#1 } {#2} } + \cs_set_protected:Npn \CJKaddEncHook #1#2 + { \cs_set:cpn { __xeCJK_enc_#1_hook: } {#2} } \cs_set_protected_nopar:Npn \Unicode #1#2 - { \tex_char:D \int_eval:n { (#1) * \c_two_hundred_fifty_six + (#2) } } + { \tex_char:D \etex_numexpr:D (#1) * \c_two_hundred_fifty_six + (#2) \scan_stop: } \RequirePackage { CJKnumb } - \cs_if_exist_use:cT { __xeCJK_enc_\CJK@UnicodeEnc } { } - \tl_set:Nx \CJK@tenthousand { ^^^^4e07 } - \tl_set:Nx \CJK@hundredmillion { ^^^^4ebf } + \cs_if_exist_use:c { __xeCJK_enc_ \CJK@UnicodeEnc _hook: } + \tl_set:Nn \CJK@tenthousand { \Unicode { 78 } { 7 } } + \tl_set:Nn \CJK@hundredmillion { \Unicode { 78 } { 191 } } + } +\bool_if:NT \g__xeCJK_config_bool + { + \tl_const:Nn \c__xeCJK_config_ext_tl { cfg } + \@onefilewithoptions + { \g__xeCJK_config_name_tl } [ ] [ ] { \c__xeCJK_config_ext_tl } } %% %% This package consists of the file xeCJK.dtx %% and the derived files xeCJK.pdf, %% xeCJK.sty, +%% xeCJK.cfg, %% xeCJK.ins, %% xeCJK-example-autofake.tex, %% xeCJK-example-fallback.tex, %% xeCJK-example-subCJKblock.tex, %% xeCJK-example-CJKecglue.tex, -%% xeCJK-example-checksingle.tex and +%% xeCJK-example-checksingle.tex, +%% xeCJK-example-CJKfntef.tex, +%% xeCJK-example-punctstyle.tex, +%% xeCJK-example-verbatim.tex, and %% README.txt. %% %% End of file `xeCJK.sty'. |