summaryrefslogtreecommitdiff
path: root/macros/latex/contrib/xpinyin
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
committerNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
commite0c6872cf40896c7be36b11dcc744620f10adf1d (patch)
tree60335e10d2f4354b0674ec22d7b53f0f8abee672 /macros/latex/contrib/xpinyin
Initial commit
Diffstat (limited to 'macros/latex/contrib/xpinyin')
-rw-r--r--macros/latex/contrib/xpinyin/README.md48
-rw-r--r--macros/latex/contrib/xpinyin/xpinyin.dtx1437
-rw-r--r--macros/latex/contrib/xpinyin/xpinyin.ins132
-rw-r--r--macros/latex/contrib/xpinyin/xpinyin.pdfbin0 -> 207276 bytes
4 files changed, 1617 insertions, 0 deletions
diff --git a/macros/latex/contrib/xpinyin/README.md b/macros/latex/contrib/xpinyin/README.md
new file mode 100644
index 0000000000..7c11c0fb0a
--- /dev/null
+++ b/macros/latex/contrib/xpinyin/README.md
@@ -0,0 +1,48 @@
+xpinyin
+=======
+
+`xpinyin` is a LaTeX package written to simplify the input of Hanyu Pinyin.
+The package provides macros to automatically add pinyin to Chinese characters.
+It can only be used in conjunction with `xeCJK` or `CJK/CJKutf8` package.
+
+Given that the implementation of pinyin package of `CJK` bundle is not very
+well, it seems that xpinyin is a good replacement of it.
+
+You can read the package manual (in Chinese) for more detailed explanations.
+
+Contributing
+------------
+
+This package is a part of the [ctex-kit](https://github.com/CTeX-org/ctex-kit) project.
+
+Issues and pull requests are welcome.
+
+Copyright and Licence
+---------------------
+
+ Copyright (C) 2012-2019 by Qing Lee <sobenlee@gmail.com>
+ ----------------------------------------------------------------------
+
+ This work may be distributed and/or modified under the
+ conditions of the LaTeX Project Public License, either
+ version 1.3c of this license or (at your option) any later
+ version. This version of this license is in
+ http://www.latex-project.org/lppl/lppl-1-3c.txt
+ and the latest version of this license is in
+ http://www.latex-project.org/lppl.txt
+ and version 1.3 or later is part of all distributions of
+ LaTeX version 2005/12/01 or later.
+
+ This work has the LPPL maintenance status `maintained'.
+
+ The Current Maintainer of this work is Qing Lee.
+
+ This package consists of the file xpinyin.dtx,
+ and the derived files xpinyin.sty,
+ xpinyin.pdf,
+ xpinyin.ins,
+ xpinyin.lua,
+ xpinyin.db,
+ xpinyin-database.def and
+ README.md (this file).
+
diff --git a/macros/latex/contrib/xpinyin/xpinyin.dtx b/macros/latex/contrib/xpinyin/xpinyin.dtx
new file mode 100644
index 0000000000..8d50b231f2
--- /dev/null
+++ b/macros/latex/contrib/xpinyin/xpinyin.dtx
@@ -0,0 +1,1437 @@
+% \iffalse meta-comment
+% !TEX program = XeLaTeX
+%<*internal>
+\iffalse
+%</internal>
+%<*readme>
+xpinyin
+=======
+
+`xpinyin` is a LaTeX package written to simplify the input of Hanyu Pinyin.
+The package provides macros to automatically add pinyin to Chinese characters.
+It can only be used in conjunction with `xeCJK` or `CJK/CJKutf8` package.
+
+Given that the implementation of pinyin package of `CJK` bundle is not very
+well, it seems that xpinyin is a good replacement of it.
+
+You can read the package manual (in Chinese) for more detailed explanations.
+
+Contributing
+------------
+
+This package is a part of the [ctex-kit](https://github.com/CTeX-org/ctex-kit) project.
+
+Issues and pull requests are welcome.
+
+Copyright and Licence
+---------------------
+
+ Copyright (C) 2012-2019 by Qing Lee <sobenlee@gmail.com>
+ ----------------------------------------------------------------------
+
+ This work may be distributed and/or modified under the
+ conditions of the LaTeX Project Public License, either
+ version 1.3c of this license or (at your option) any later
+ version. This version of this license is in
+ http://www.latex-project.org/lppl/lppl-1-3c.txt
+ and the latest version of this license is in
+ http://www.latex-project.org/lppl.txt
+ and version 1.3 or later is part of all distributions of
+ LaTeX version 2005/12/01 or later.
+
+ This work has the LPPL maintenance status `maintained'.
+
+ The Current Maintainer of this work is Qing Lee.
+
+ This package consists of the file xpinyin.dtx,
+ and the derived files xpinyin.sty,
+ xpinyin.pdf,
+ xpinyin.ins,
+ xpinyin.lua,
+ xpinyin.db,
+ xpinyin-database.def and
+ README.md (this file).
+
+%</readme>
+%<*internal>
+\fi
+\begingroup
+ \def\temp{LaTeX2e}
+\expandafter\endgroup\ifx\temp\fmtname\else
+\csname fi\endcsname
+%</internal>
+%<*install>
+
+%<install>\begingroup\expandafter\expandafter\expandafter\endgroup
+%<install>\expandafter\ifx\csname directlua\endcsname\relax
+%<install> \begingroup
+%<install> \newlinechar=10 %
+%<install> \errmessage{^^J
+%<install> ********************************************^^J
+%<install> * LuaTeX is required to unpack this package.^^J
+%<install> ********************************************^^J
+%<install> }
+%<install> \endgroup
+%<install> \csname @@end\expandafter\endcsname\expandafter\end
+%<install>\fi
+
+\input ctxdocstrip %
+
+\let\MetaPrefix\relax
+
+\preamble
+
+ Copyright (C) 2012-2019 by Qing Lee <sobenlee@gmail.com>
+--------------------------------------------------------------------------
+
+ This work may be distributed and/or modified under the
+ conditions of the LaTeX Project Public License, either
+ version 1.3c of this license or (at your option) any later
+ version. This version of this license is in
+ http://www.latex-project.org/lppl/lppl-1-3c.txt
+ and the latest version of this license is in
+ http://www.latex-project.org/lppl.txt
+ and version 1.3 or later is part of all distributions of
+ LaTeX version 2005/12/01 or later.
+
+ This work has the LPPL maintenance status `maintained'.
+
+ The Current Maintainer of this work is Qing Lee.
+
+--------------------------------------------------------------------------
+
+\endpreamble
+
+\postamble
+
+ This package consists of the file xpinyin.dtx,
+ and the derived files xpinyin.sty,
+ xpinyin.pdf,
+ xpinyin.ins,
+ xpinyin.lua,
+ xpinyin.db,
+ xpinyin-database.def and
+ README.md.
+\endpostamble
+
+\declarepostamble\emptypostamble
+\endpostamble
+
+\def\MetaPrefix{-- }
+
+\generate
+ {
+ \usedir{source/latex/xpinyin}
+ \usepostamble\emptypostamble
+ \file{xpinyin.lua} {\from{\jobname.dtx}{lua}}
+ }
+
+\let\MetaPrefix\DoubleperCent
+
+%<install>\directlua
+%<install> {
+%<install> if not kpse.find_file("xpinyin.db") then
+%<install> dofile(kpse.find_file("xpinyin.lua"))
+%<install> end
+%<install> }
+%<install>\generate
+%<install> {
+%<install> \usedir{tex/latex/xpinyin}
+%<install> \usepostamble\emptypostamble
+%<install> \file{xpinyin-database.def}
+%<install> {
+%<install> \from{\jobname.dtx} {database}
+%<install> \from{xpinyin.db} {}
+%<install> }
+%<install> }
+
+\generate
+ {
+%</install>
+%<*internal>
+ \usedir{source/latex/xpinyin}
+ \file{xpinyin.ins} {\from{\jobname.dtx}{install}}
+%</internal>
+%<*install>
+ \usedir{tex/latex/xpinyin}
+ \file{xpinyin.sty} {\from{\jobname.dtx}{package}}
+ \nopreamble\nopostamble
+ \usedir{doc/latex/xpinyin}
+ \file{README.md} {\from{\jobname.dtx}{readme}}
+ }
+
+\endbatchfile
+%</install>
+%<*internal>
+\fi
+%</internal>
+%<package>\NeedsTeXFormat{LaTeX2e}
+%<package>\RequirePackage{expl3}
+%<+package>\GetIdInfo$Id: xpinyin.dtx 81bb941 2019-04-07 23:27:58 +0800 Qing Lee <sobenlee@gmail.com> $
+%<package> {Automatically add pinyin to Chinese characters}
+%<package>\ProvidesExplPackage{\ExplFileName}
+%<package> {\ExplFileDate}{2.7}{\ExplFileDescription}
+%<database>\ProvidesFile{xpinyin-database.def}%
+%<database> [2019/04/07 v2.7 xpinyin database]
+%<*driver>
+\documentclass{ctxdoc}
+\usepackage{xpinyin}
+\newfontfamily\PinYinFont{TeX Gyre Adventor}
+\xpinyinsetup{font=\PinYinFont,multiple=\color{red}}
+\begin{document}
+ \DocInput{\jobname.dtx}
+ \IndexLayout
+ \PrintIndex
+\end{document}
+%</driver>
+% \fi
+%
+% \CheckSum{696}
+% \GetFileId{xpinyin.sty}
+%
+% \title{\bfseries\pkg{xpinyin} 宏包}
+% \author{李清\\ \path{sobenlee@gmail.com}}
+% \date{\filedate\qquad\fileversion\thanks{\ctexkitrev{\ExplFileVersion}.}}
+% \maketitle
+%
+% \begin{documentation}
+%
+% \section{简介}
+%
+% \pkg{xpinyin} 是一个 \LaTeX 宏包,提供了为汉字自动注音的功能。
+%
+% \section{基本用法}
+%
+% \pkg{xpinyin} 支持采用 \texttt{GBK} 和 \texttt{UTF-8} 编码的 \TeX 源文件,建议
+% 总是使用 \texttt{UTF-8}。如果使用 \LaTeX 或 \pdfLaTeX\ 的编译方式,则根据编码的
+% 情况,\pkg{xpinyin} 依赖 \package{CJK} 或者 \package[cjk]{CJKutf8} 宏包。
+% 如果使用 \XeLaTeX,则依赖 \package{xeCJK} 宏包。如果它们没有在 \pkg{xpinyin}
+% 之前被载入,\pkg{xpinyin} 将根据编译方式自动选择,\LaTeX 或 \pdfLaTeX\ 将使用
+% \pkg{CJKutf8}。
+%
+% \pkg{xpinyin} 还依赖 \package{l3kernel} 和 \package{l3packages},使用 (pdf)\LaTeX
+% 下的 \texttt{GBK} 编码时,还将依赖 \package{xCJK2uni}。
+%
+% 需要注意的是,\pkg{xpinyin} 缺省将拼音的字体设置为与文档的主字体(\tn{normalfont})相同,
+% 所以为了保证声调字母的正确输出,应该选用合适的西文主字体。也可以通过将在下一节介绍的
+% \meta{font} 选项来单独设置拼音的字体。
+%
+% \begin{minipage}[t]{\dimexpr(\linewidth-\parindent-2em)/2\relax}
+% \XeLaTeX 下的简单示例:
+% \begin{verbatim}[frame=single,gobble=3]
+% \documentclass{article}
+% \usepackage{xeCJK}
+% \usepackage{xpinyin}
+% \setmainfont{CMU Serif}
+% \setCJKmainfont{SimSun}
+%
+% \begin{document}
+% \xpinyin*{汉语拼音示例}
+% \end{document}
+% \end{verbatim}
+% \end{minipage}\qquad
+% \begin{minipage}[t]{\dimexpr(\linewidth-\parindent-2em)/2\relax}
+% (pdf)\LaTeX 下的简单示例:
+% \begin{verbatim}[frame=single,gobble=3]
+% \documentclass{article}
+% \usepackage{CJKutf8}
+% \usepackage{xpinyin}
+% \usepackage[T1]{fontenc}
+% \usepackage{lmodern}
+%
+% \begin{document}
+% \begin{CJK}{UTF8}{gbsn}
+% \xpinyin*{汉语拼音示例}
+% \end{CJK}
+% \end{document}
+% \end{verbatim}
+% \hrule height \dp\strutbox width 0pt \relax
+% \end{minipage}
+%
+% 运行上述示例要求系统安装了设置的字体,源文件用 |UTF-8| 编码保存,使用相应的编译方式。
+%
+% \pkg{xpinyin} 可以与 \package{ctex} 宏包或文档类共同使用,使用方式与上面类似。
+%
+% \section{用户手册}
+%
+% \begin{function}{pinyinscope}
+% \begin{syntax}
+% \tn{begin}\{pinyinscope\}\oarg{options}
+% .....
+% \tn{end}\{pinyinscope\}
+% \end{syntax}
+% 为 \env{pinyinscope} 环境中的汉字自动注音。例如
+% \begin{Example}[frame=single,numbers=left,gobble=5]
+% \begin{pinyinscope}
+% 列位看官:你道此书从何而来?说起根由,虽近荒唐,细按则深有趣味。
+% 待在下将此来历注明,方使阅者\xpinyin{了}{liao3}然不惑。
+% \end{pinyinscope}
+% \end{Example}
+% \end{function}
+%
+% 可选项 \meta{options} 用于局部设置拼音的格式,将在下面说明。
+%
+% \begin{function}{\xpinyin}
+% \begin{syntax}
+% \tn{xpinyin} \oarg{options} \Arg{单个汉字} \Arg{拼音}
+% \tn{xpinyin*} \oarg{options} \Arg{文字}
+% \end{syntax}
+% 对于多音字,可以使用 \tn{xpinyin} 为其设置拼音;而 \tn{xpinyin*} 相当于
+% \env{pinyinscope} 环境的命令形式。\tn{xpinyin} 可以在 \env{pinyinscope} 环境和
+% \tn{xpinyin*} 中使用。例如,
+% \begin{SideBySideExample}[frame=single,numbers=left,xrightmargin=.5\linewidth,gobble=5]
+% \xpinyin{长}{chang2}\\
+% \xpinyin*{甄士隐梦幻识通灵}\\
+% \xpinyin*{\xpinyin{重}{zhong4}要}
+% \end{SideBySideExample}
+% \end{function}
+%
+% \begin{function}{\pinyin}
+% \begin{syntax}
+% \tn{pinyin} \oarg{options} \Arg{拼音}
+% \end{syntax}
+% 用于输出拼音,为了输入的方便 \texttt{\"u} 可以用 |v| 代替。例如,
+% \begin{SideBySideExample}[frame=single,numbers=left,xrightmargin=.5\linewidth,gobble=5]
+% \pinyin{lv2zi}\\
+% \pinyin{nv3hai2zi}
+% \end{SideBySideExample}
+% \end{function}
+%
+% \begin{function}{\setpinyin}
+% \begin{syntax}
+% \tn{setpinyin} \Arg{汉字} \Arg{拼音}
+% \end{syntax}
+% \pkg{xpinyin} 宏包的拼音数据(\file{xpinyin-database.def})来源于 \texttt{Unicode}
+% 的 \texttt{Unihan} 数据库\footnotemark 中的 \file{Unihan_Readings.txt} 文件。对于多
+% 音字,一般来说这个文件选用的是常用读音。可以使用 \tn{setpinyin} 来设置多音字的首选读音。
+% \end{function}
+%
+% \footnotetext{\url{http://www.unicode.org/Public/UNIDATA/Unihan.zip}}
+%
+% \begin{function}{\xpinyinsetup}
+% \begin{syntax}
+% \tn{xpinyinsetup} \{ <key_1>=<val_1>, <key_2>=<val_2>, ... \}
+% \end{syntax}
+% 用于在导言区或文档中,设置拼音的格式。目前可以设置的 \meta{key} 如下介绍。
+% \end{function}
+%
+% \begin{function}{ratio}
+% \begin{syntax}
+% ratio = \Arg{number}
+% \end{syntax}
+% 设置拼音字体大小与当前正文字体大小的比例,缺省值是 |0.4|。
+% \end{function}
+%
+% \begin{function}{vsep}
+% \begin{syntax}
+% vsep = \Arg{dimen}
+% \end{syntax}
+% 设置拼音的基线与汉字基线的间距,缺省值是 |1 em|。
+% \end{function}
+%
+% \begin{function}{hsep}
+% \begin{syntax}
+% hsep = \Arg{skip}
+% \end{syntax}
+% 设置注音汉字之间的间距,缺省值与 \tn{CJKglue} 的值相同。为了断行时行末的对齐,设置
+% 的 \meta{skip} 最后有一定的弹性。例如
+% \begin{Example}[frame=single,numbers=left,gobble=5]
+% \xpinyin*[ratio={.7},hsep={.5em plus .1em},vsep={1.1em}]{贾雨村风尘怀闺秀}
+% \end{Example}
+% \end{function}
+%
+% \begin{function}{pysep}
+% \begin{syntax}
+% pysep = \Arg{glue}
+% \end{syntax}
+% 设置 \tn{pinyin} 输出的相邻两个汉语拼音的空白,缺省值是一个空格。
+% \end{function}
+%
+% \begin{function}{font}
+% \begin{syntax}
+% font = \Arg{font}
+% \end{syntax}
+% 设置拼音的字体,缺省值是 \tn{normalfont},即以正文西文字体相同。为了保证拼音能正确
+% 输出,最好选用收字量较大的西文字体。
+% \end{function}
+%
+% \begin{function}{format}
+% \begin{syntax}
+% format = \Arg{format}
+% \end{syntax}
+% 设置拼音的其它格式,例如颜色等,缺省值为空。
+% \end{function}
+%
+% \begin{function}{multiple}
+% \begin{syntax}
+% multiple = \Arg{format}
+% \end{syntax}
+% 设置多音字拼音的其它格式,缺省值为空。可以通过这个选项来提醒校正多音字的拼音。例如
+% 本文档设置多音字拼音的颜色是红色(需要载入 \pkg{color} 宏包):
+% \begin{frameverb}
+% \xpinyinsetup{multiple={\color{red}}}
+% \end{frameverb}
+% \end{function}
+%
+% \begin{function}[added=2014/01/12]{footnote}
+% \begin{syntax}
+% footnote = <\TFF>
+% \end{syntax}
+% 是否对拼音环境中的脚注(\tn{footnote})汉字加上拼音。缺省值为 \texttt{false}。
+% 更一般的情况,请使用 \tn{disablepinyin}。
+% \end{function}
+%
+% \begin{function}[added=2014/01/12]{\disablepinyin,\enablepinyin}
+% \tn{disablepinyin} 用于在拼音环境(\env{pinyinscope})中临时取消对汉字的注音,而
+% \tn{enablepinyin} 用于其后的恢复。
+% \end{function}
+%
+% \end{documentation}
+%
+% \StopEventually{}
+%
+% \begin{implementation}
+%
+% \section{代码实现}
+%
+% \begin{macrocode}
+%<*package>
+%<@@=xpinyin>
+% \end{macrocode}
+%
+% \begin{macrocode}
+\msg_new:nnn { xpinyin } { l3-too-old }
+ {
+ Support~package~'expl3'~too~old. \\\\
+ Please~update~an~up~to~date~version~of~the~bundles\\\\
+ 'l3kernel'~and~'l3packages'\\\\
+ using~your~TeX~package~manager~or~from~CTAN.
+ }
+\@ifpackagelater { expl3 } { 2019/03/05 } { }
+ { \msg_error:nn { xpinyin } { l3-too-old } }
+% \end{macrocode}
+%
+% \begin{macrocode}
+\msg_new:nnn { xpinyin } { engine-not-supported }
+ { Engine~`\c_sys_engine_str'~is~not~yet~supported,~xpinyin~will~abort! }
+\bool_lazy_or:nnF
+ { \sys_if_engine_xetex_p: }
+ { \sys_if_engine_pdftex_p: }
+ { \msg_critical:nn { xpinyin } { engine-not-supported } }
+% \end{macrocode}
+%
+% \begin{macrocode}
+\RequirePackage { xparse }
+\RequirePackage { l3keys2e }
+% \end{macrocode}
+%
+% \begin{variable}{\c_@@_tone_prop}
+% 重音标记 |\`|、|\'| 和 |\=| 在 \env{tabbing} 环境中被移作他用,为避免错误,
+% 我们使用内部命令 \tn{@tabacckludge} 或 \tn{a} 来定义。
+% \begin{macrocode}
+\prop_const_from_keyval:Nn \c_@@_tone_prop
+ {
+ { ā } = { \@tabacckludge= a } ,
+ { á } = { \@tabacckludge' a } ,
+ { ǎ } = { \v a } ,
+ { à } = { \@tabacckludge` a } ,
+ { ō } = { \@tabacckludge= o } ,
+ { ó } = { \@tabacckludge' o } ,
+ { ǒ } = { \v o } ,
+ { ò } = { \@tabacckludge` o } ,
+ { ē } = { \@tabacckludge= e } ,
+ { é } = { \@tabacckludge' e } ,
+ { ě } = { \v e } ,
+ { è } = { \@tabacckludge` e } ,
+ { ū } = { \@tabacckludge= u } ,
+ { ú } = { \@tabacckludge' u } ,
+ { ǔ } = { \v u } ,
+ { ù } = { \@tabacckludge` u } ,
+ { ḿ } = { \@tabacckludge' m } ,
+ { ń } = { \@tabacckludge' n } ,
+ { ň } = { \v n } ,
+ { ǹ } = { \@tabacckludge` n } ,
+ { ī } = { \@tabacckludge= { \i } } ,
+ { í } = { \@tabacckludge' { \i } } ,
+ { ǐ } = { \v { \i } } ,
+ { ì } = { \@tabacckludge` { \i } } ,
+ { ü } = { \" u } ,
+ { ǖ } = { \@tabacckludge= { \" u } } ,
+ { ǘ } = { \@tabacckludge' { \" u } } ,
+ { ǚ } = { \v { \" u } } ,
+ { ǜ } = { \@tabacckludge` { \" u } }
+ }
+% \end{macrocode}
+% \end{variable}
+%
+%
+% \begin{macro}{\@@_UTF_char:nn}
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \@@_UTF_char:nn #1#2
+ {
+ \cs_if_exist:cF { u8:#1 }
+ { \tl_const:cn { u8:#1 } {#2} }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+%
+% \begin{macro}{\@@_GBK_char:nn}
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \@@_GBK_char:nn #1#2
+ {
+ \@@_UTF_char:nn {#1} {#2}
+ \exp_args:Nx \@@_GBK_char_aux:nn { \tl_head:n {#1} } {#1}
+ }
+\cs_new_protected_nopar:Npn \@@_GBK_char_aux:nn #1#2
+ { \exp_args:Nf \@@_GBK_char_aux:nnn { \int_eval:n { `#1 } } {#1} {#2} }
+\cs_new_protected_nopar:Npn \@@_GBK_char_aux:nnn #1#2#3
+ {
+ \cs_if_exist:cF { @@_UTF_ #1 :w }
+ {
+ \exp_args:Nf \@@_GBK_char_def:nnn
+ {
+ \int_case:nn { \tl_count:n {#3} }
+ {
+ { 2 } { ##1 }
+ { 3 } { ##1##2 }
+ { 4 } { ##1##2##3 }
+ }
+ }
+ {#1} {#2}
+ \exp_args:Nc \@@_save_UTF_cs:Nn { @@_UTF_ #1 :w } {#1}
+ \tl_gput_right:Nx \c_@@_reset_UTF_catcode_tl
+ { \char_set_catcode:nn {#1} { \char_value_catcode:n {#1} } }
+ \char_set_catcode_active:n {#1}
+ }
+ }
+\cs_new_protected_nopar:Npn \@@_GBK_char_def:nnn #1#2#3
+ {
+ \cs_new_protected_nopar:cpn { @@_UTF_ #2 :w } #1
+ { \use:c { u8: \tl_to_str:n { #3#1 } } }
+ }
+\tl_new:N \c_@@_reset_UTF_catcode_tl
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_save_UTF_cs:Nn}
+% \begin{macrocode}
+\group_begin:
+\char_set_catcode_active:n { 126 }
+\cs_new_protected_nopar:Npn \@@_save_UTF_cs:Nn #1#2
+ {
+ \group_begin:
+ \char_set_lccode:nn { 126 } {#2}
+ \tex_lowercase:D
+ {
+ \group_end:
+ \tl_gput_right:Nn \c_@@_reset_UTF_cs_tl { \cs_set_eq:NN ~ #1 }
+ }
+ }
+\group_end:
+\tl_new:N \c_@@_reset_UTF_cs_tl
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macrocode}
+\bool_new:N \g_@@_GBK_bool
+\@ifpackageloaded { xeCJK }
+ { \AtEndOfPackage { \@@_adjust_xeCJK_hook: } }
+ {
+ \@ifpackageloaded { CJKutf8 }
+ {
+ \prop_map_function:NN \c_@@_tone_prop \@@_UTF_char:nn
+ \AtEndOfPackage { \@@_adjust_CJK_hook: }
+ }
+ {
+ \@ifpackageloaded { CJK }
+ {
+ \RequirePackage { xCJK2uni }
+ \prop_map_function:NN \c_@@_tone_prop \@@_GBK_char:nn
+ \AtEndOfPackage
+ {
+ \tl_put_right:Nn \l_@@_pinyin_box_hook_tl
+ { \c_@@_reset_UTF_cs_tl }
+ \@@_adjust_CJK_hook:
+ \tl_use:N \c_@@_reset_UTF_catcode_tl
+ }
+ \bool_gset_true:N \g_@@_GBK_bool
+ }
+ {
+ \sys_if_engine_xetex:TF
+ {
+ \RequirePackage { xeCJK }
+ \AtEndOfPackage { \@@_adjust_xeCJK_hook: }
+ }
+ {
+ \RequirePackage { CJKutf8 }
+ \prop_map_function:NN \c_@@_tone_prop \@@_UTF_char:nn
+ \AtEndOfPackage { \@@_adjust_CJK_hook: }
+ }
+ }
+ }
+ }
+% \end{macrocode}
+%
+% \begin{variable}{\l_@@_tmpa_box,\l_@@_tmpb_box}
+% \begin{macrocode}
+\box_new:N \l_@@_tmpa_box
+\box_new:N \l_@@_tmpb_box
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{macro}{\@@_width:Nn}
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_width:Nn #1#2
+ {
+ \hbox_set:Nn \l_@@_tmpa_box {#2}
+ #1 = \box_wd:N \l_@@_tmpa_box
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_make_pinyin_box:nnn}
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \@@_make_pinyin_box:nnn #1#2#3
+ {
+ \@@_leavevmode:
+ \hbox_overlap_right:n
+ {
+ \hbox_set:Nn \l_@@_tmpa_box
+ { \@@_CJKsymbol_hook: \@@_save_CJKsymbol:n {#2} }
+ \hbox_set:Nn \l_@@_tmpb_box
+ {
+ \color_group_begin: \color_ensure_current:
+ \l_@@_pinyin_box_hook_tl
+ \@@_select_font:
+ \clist_if_exist:cTF { c_@@_multiple_ #1 _clist }
+ { \l_@@_multiple_tl \l_@@_format_tl }
+ { \l_@@_format_tl }
+ {#3}
+ \color_group_end:
+ }
+ \dim_compare:nNnT
+ { \box_wd:N \l_@@_tmpb_box } >
+ { \box_wd:N \l_@@_tmpa_box + \l_@@_CJKglue_dim }
+ {
+ \box_resize_to_wd_and_ht:Nnn \l_@@_tmpb_box
+ { \box_wd:N \l_@@_tmpa_box + \l_@@_CJKglue_dim }
+ { \box_ht:N \l_@@_tmpb_box }
+ }
+ \box_move_up:nn { \l_@@_vsep_tl }
+ {
+ \hbox_to_wd:nn { \box_wd:N \l_@@_tmpa_box }
+ { \tex_hss:D \box_use_drop:N \l_@@_tmpb_box \tex_hss:D }
+ }
+ }
+ }
+\tl_new:N \l_@@_pinyin_box_hook_tl
+\sys_if_engine_pdftex:T
+ {
+ \tl_put_right:Nn \l_@@_pinyin_box_hook_tl
+ { \cs_set_eq:NN \CJK@plane \tex_undefined:D }
+ }
+\cs_generate_variant:Nn \@@_make_pinyin_box:nnn { x }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_CJKsymbol:n}
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \@@_CJKsymbol:n #1
+ { \@@_CJKsymbol:xn { \@@_to_unicode:n {#1} } {#1} }
+\cs_new_protected_nopar:Npn \@@_CJKsymbol:nn #1#2
+ {
+ \@@_make_pinyin_box:nnn {#1} {#2} { \use:c { c_@@_ #1 _tl } }
+ \@@_save_CJKsymbol:n {#2}
+ }
+\cs_generate_variant:Nn \@@_CJKsymbol:nn { x }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{pinyinscope}
+% \begin{macrocode}
+\NewDocumentEnvironment { pinyinscope } { O { } }
+ {
+ \keys_set:nn { xpinyin } {#1}
+ \enablepinyin
+ }
+ { }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\xpinyin}
+% \begin{macrocode}
+\NewDocumentCommand \xpinyin { s O { } m }
+ {
+ \mode_leave_vertical:
+ \IfBooleanTF {#1}
+ {
+ \group_begin:
+ \keys_set:nn { xpinyin } {#2}
+ \enablepinyin
+ #3
+ \group_end:
+ }
+ {
+ \group_begin:
+ \keys_set:nn { xpinyin } {#2}
+ \bool_if:NF \l_@@_enable_bool
+ { \@@_width:Nn \l_@@_CJKglue_dim { \CJKglue } }
+ \@@_single_aux:nn {#3}
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{variable}{\l_@@_enable_bool}
+% \begin{macrocode}
+\bool_new:N \l_@@_enable_bool
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{macro}{\@@_CJKglue:}
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \@@_CJKglue:
+ { \skip_horizontal:n { \l_@@_hsep_tl } }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\enablepinyin}
+% \begin{macrocode}
+\NewDocumentCommand \enablepinyin { }
+ {
+ \bool_if:NF \l_@@_enable_bool
+ {
+ \tl_if_empty:NF \l_@@_hsep_tl
+ {
+ \cs_set_eq:NN \@@_save_CJKglue: \CJKglue
+ \cs_set_eq:NN \CJKglue \@@_CJKglue:
+ }
+ \@@_width:Nn \l_@@_CJKglue_dim { \CJKglue }
+ \@@_replace_CJKsymbol:
+ \@@_restore_footnote:
+ \bool_set_true:N \l_@@_enable_bool
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\disablepinyin}
+% \begin{macrocode}
+\NewDocumentCommand \disablepinyin { }
+ {
+ \bool_if:NT \l_@@_enable_bool
+ {
+ \cs_if_eq:NNT \CJKglue \@@_CJKglue:
+ { \cs_set_eq:NN \CJKglue \@@_save_CJKglue: }
+ \@@_restore_CJKsymbol:
+ \bool_set_false:N \l_@@_enable_bool
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_restore_footnote:}
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \@@_restore_footnote:
+ {
+ \bool_if:NF \l_@@_footnote_bool
+ { \tl_put_left:Nn \@parboxrestore { \l_@@_restore_footnote_tl } }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{variable}{\l_@@_restore_footnote_tl}
+% \begin{macrocode}
+\tl_new:N \l_@@_restore_footnote_tl
+\tl_set:Nn \l_@@_restore_footnote_tl
+ {
+ \int_compare:nNnT \tex_currentgrouptype:D = { 11 }
+ { \disablepinyin }
+ }
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\l_@@_CJKglue_dim}
+% \begin{macrocode}
+\dim_new:N \l_@@_CJKglue_dim
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{macro}{\@@_single_aux:nn}
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \@@_single_aux:nn #1#2
+ {
+ \@@_replace_CJKsymbol_single:n {#2}
+ #1
+ \group_end:
+ }
+\cs_new_protected_nopar:Npn \@@_replace_CJKsymbol_single_aux:n #1
+ {
+ \bool_if:NF \l_@@_enable_bool { \@@_replace_CJKsymbol: }
+ \cs_set_protected_nopar:Npn \CJKsymbol ##1
+ { \@@_single_CJKsymbol:nn {##1} {#1} }
+ }
+\cs_new_protected_nopar:Npn \@@_single_CJKsymbol:nn #1#2
+ {
+ \@@_make_pinyin_box:xnn
+ { \@@_to_unicode:n {#1} } {#1} { \@@_pinyin:n {#2} }
+ \@@_save_CJKsymbol:n {#1}
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_replace_CJKsymbol_aux:}
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \@@_replace_CJKsymbol_aux:
+ {
+ \cs_set_eq:NN \@@_save_CJKsymbol:n \CJKsymbol
+ \cs_set_eq:NN \CJKsymbol \@@_CJKsymbol:n
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_restore_CJKsymbol_aux:}
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \@@_restore_CJKsymbol_aux:
+ { \cs_set_eq:NN \CJKsymbol \@@_save_CJKsymbol:n }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_select_font_xetex:}
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \@@_select_font_xetex:
+ {
+ \cs_if_exist_use:cF { \l_@@_coor_tl }
+ {
+ \tl_set:Nx \l_@@_current_coor_tl { \l_@@_coor_tl }
+ \@@_select_font_aux:
+ \int_compare:nNnF { \tex_XeTeXfonttype:D \tex_font:D } = \c_zero_int
+ {
+ \exp_last_unbraced:NNV
+ \cs_gset_eq:cN \l_@@_current_coor_tl \tex_font:D
+ }
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_select_font_aux:}
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \@@_select_font_aux:
+ {
+ \fontsize
+ { \l_@@_ratio_tl \tex_dimexpr:D \f@size pt \scan_stop: }
+ { \f@baselineskip }
+ \normalfont
+ \l_@@_font_tl
+ \selectfont
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_to_unicode_xetex:n}
+% \begin{macrocode}
+\cs_new_nopar:Npn \@@_to_unicode_xetex:n #1
+ { \int_to_arabic:n { `#1 } }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_UTF_to_unicode:n,\@@_UTFchar_to_unicode:n}
+% \begin{macrocode}
+\cs_new_nopar:Npn \@@_UTF_to_unicode:n #1
+ {
+ \int_to_arabic:n
+ { \exp_args:No \int_from_hex:n { \CJK@plane } * "100 + #1 }
+ }
+\cs_new_nopar:Npn \@@_UTFchar_to_unicode:n #1
+ { \int_to_arabic:n { \@@_UTF_viii_to_unicode:NNNw #1 \q_stop } }
+\cs_new_nopar:Npn \@@_UTF_viii_to_unicode:NNNw #1#2#3#4 \q_stop
+ {
+ \tl_if_empty:nTF {#4}
+ { ( `#1 - "E0 ) * "1000 + ( `#2 - "80 ) * "40 + ( `#3 - "80 ) }
+ { ( `#1 - "F0 ) * "4000 + ( `#2 - "80 ) * "1000 + ( `#3 - "80 ) * "40 + ( `#4 - "80 ) }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_GBK_to_unicode:n,\@@_GBKchar_to_unicode:n}
+% \begin{macrocode}
+\cs_new_nopar:Npn \@@_GBK_to_unicode:n #1
+ { \int_to_arabic:n { " \CJKtu_sfd_map:nn { \CJK@plane } {#1} } }
+\cs_new_nopar:Npn \@@_GBKchar_to_unicode:n #1
+ { \int_to_arabic:n { " \CJKchartouni {#1} } }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_adjust_xeCJK_hook:}
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \@@_adjust_xeCJK_hook:
+ {
+ \cs_new_eq:NN \@@_select_font: \@@_select_font_xetex:
+ \cs_new_eq:NN \@@_to_unicode:n \@@_to_unicode_xetex:n
+ \cs_new_eq:NN \@@_char_to_unicode:n \@@_to_unicode:n
+ \cs_new_eq:NN \@@_restore_CJKsymbol: \@@_restore_CJKsymbol_aux:
+ \cs_new_eq:NN \@@_replace_CJKsymbol: \@@_replace_CJKsymbol_aux:
+ \cs_new_eq:NN \@@_replace_CJKsymbol_single:n
+ \@@_replace_CJKsymbol_single_aux:n
+ \tl_if_exist:NTF \l_xeCJK_current_font_tl
+ {
+ \tl_set:Nn \l_@@_coor_tl
+ {
+ ( \tl_to_str:N \l_@@_font_tl ) /
+ \l_xeCJK_current_font_tl/\l_@@_ratio_tl
+ }
+ }
+ {
+ \tl_set:Nn \l_@@_coor_tl
+ {
+ ( \tl_to_str:N \l_@@_font_tl ) /
+ \xeCJK@family/\f@series/\f@shape/\f@size/\l_@@_ratio_tl
+ }
+ }
+ \cs_new_eq:NN \@@_leavevmode: \prg_do_nothing:
+ \cs_new_protected_nopar:Npx \@@_CJKsymbol_hook:
+ {
+ \exp_not:N \makexeCJKinactive
+ \cs_if_exist_use:NF \xeCJK_select_font:
+ { \exp_not:N \xeCJK@setfont }
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_adjust_CJK_hook:}
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \@@_adjust_CJK_hook:
+ {
+ \bool_if:NTF \g_@@_GBK_bool
+ {
+ \cs_new_eq:NN \@@_to_unicode:n \@@_GBK_to_unicode:n
+ \cs_new_eq:NN \@@_char_to_unicode:n \@@_GBKchar_to_unicode:n
+ }
+ {
+ \cs_new_eq:NN \@@_to_unicode:n \@@_UTF_to_unicode:n
+ \cs_new_eq:NN \@@_char_to_unicode:n \@@_UTFchar_to_unicode:n
+ }
+ \cs_new_eq:NN \@@_select_font: \@@_select_font_aux:
+ \cs_new_eq:NN \@@_leavevmode: \mode_leave_vertical:
+ \cs_new_eq:NN \@@_CJKsymbol_hook: \prg_do_nothing:
+ \@ifpackageloaded { CJKpunct }
+ { \@@_adjust_CJKpunct_hook: }
+ {
+ \cs_new_eq:NN \@@_restore_CJKsymbol: \@@_restore_CJKsymbol_aux:
+ \cs_new_eq:NN \@@_replace_CJKsymbol: \@@_replace_CJKsymbol_aux:
+ \cs_new_eq:NN \@@_replace_CJKsymbol_single:n
+ \@@_replace_CJKsymbol_single_aux:n
+ \AtBeginDocument
+ {
+ \@ifpackageloaded { CJKpunct }
+ {
+ \cs_undefine:N \@@_restore_CJKsymbol:
+ \cs_undefine:N \@@_replace_CJKsymbol:
+ \cs_undefine:N \@@_replace_CJKsymbol_single:n
+ \@@_adjust_CJKpunct_hook:
+ } { }
+ }
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_adjust_CJKpunct_hook:}
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \@@_adjust_CJKpunct_hook:
+ {
+ \cs_new_protected_nopar:Npn \@@_restore_CJKsymbol:
+ {
+ \int_compare:nNnTF { \CJKpunct@punctstyle } = { \CJKpunct@ps@plain }
+ { \@@_restore_CJKsymbol_aux: }
+ { \cs_set_eq:NN \CJKosymbol \@@_save_CJKsymbol:n }
+ }
+ \cs_new_protected_nopar:Npn \@@_replace_CJKsymbol:
+ {
+ \int_compare:nNnTF { \CJKpunct@punctstyle } = { \CJKpunct@ps@plain }
+ { \@@_replace_CJKsymbol_aux: }
+ {
+ \cs_set_eq:NN \@@_save_CJKsymbol:n \CJKosymbol
+ \cs_set_eq:NN \CJKosymbol \@@_CJKsymbol:n
+ }
+ }
+ \cs_new_protected_nopar:Npn \@@_replace_CJKsymbol_single:n ##1
+ {
+ \int_compare:nNnTF { \CJKpunct@punctstyle } = { \CJKpunct@ps@plain }
+ { \@@_replace_CJKsymbol_single_aux:n { ##1 } }
+ {
+ \bool_if:NF \l_@@_enable_bool
+ { \cs_set_eq:NN \@@_save_CJKsymbol:n \CJKosymbol }
+ \cs_set_protected_nopar:Npn \CJKosymbol ####1
+ { \@@_single_CJKsymbol:nn { ####1 } { ##1 } }
+ }
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\pinyin}
+% \begin{macrocode}
+\NewDocumentCommand \pinyin { O { } m }
+ {
+ \group_begin:
+ \keys_set:nn { xpinyin } {#1}
+ \l_@@_font_tl
+ \l_@@_format_tl { }
+ \selectfont
+ \c_@@_reset_UTF_cs_tl
+ \@@_pinyin:n {#2}
+ \group_end:
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_pinyin:n}
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \@@_pinyin:n #1
+ {
+ \@@_pinyin_init:
+ \bool_set_true:N \l_@@_first_bool
+ \tl_set:Nn \l_@@_save_tl {#1}
+ \@@_pinyin_aux:n #1 \q_recursion_tail \q_recursion_stop
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_pinyin_aux:n}
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \@@_pinyin_aux:n #1
+ {
+ \quark_if_recursion_tail_stop_do:nn {#1}
+ {
+ \bool_if:NTF \l_@@_first_bool { \l_@@_save_tl }
+ { \tl_if_empty:NF \l_@@_item_tl { \l_@@_pysep_tl \l_@@_item_tl } }
+ }
+ \@@_if_number:nTF {#1}
+ {
+ \bool_if:NTF \l_@@_first_bool
+ { \bool_set_false:N \l_@@_first_bool }
+ { \l_@@_pysep_tl }
+ \l_@@_pre_tl
+ \@@_tone:Vn \l_@@_tone_tl {#1}
+ \l_@@_post_tl
+ \@@_pinyin_init:
+ }
+ {
+ \int_compare:nNnTF
+ { 0 \cs_if_exist_use:c { c_@@_ \tl_to_str:N \l_@@_tone_tl _tl } } >
+ { 0 \cs_if_exist_use:c { c_@@_ \tl_to_str:n {#1} _tl } }
+ { \tl_put_right:Nn \l_@@_post_tl {#1} }
+ {
+ \tl_set:Nn \l_@@_tone_tl {#1}
+ \tl_set_eq:NN \l_@@_pre_tl \l_@@_item_tl
+ \tl_clear:N \l_@@_post_tl
+ }
+ \tl_put_right:Nx \l_@@_item_tl { \@@_replace_v:n {#1} }
+ }
+ \@@_pinyin_aux:n
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_tone:nn}
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \@@_tone:nn #1#2
+ { \use:c { @@_num_to_tone_ #1 :Nn } {#1} {#2} }
+\cs_generate_variant:Nn \@@_tone:nn { V }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_replace_v:n}
+% \begin{macrocode}
+\cs_new_nopar:Npn \@@_replace_v:n #1
+ {
+ \str_if_eq:nnTF {#1} { v }
+ {
+ \str_case:onTF { \l_@@_item_tl }
+ { { l } { } { n } { } { L } { } { N } { } }
+ { \exp_not:n { ü } } { u }
+ }
+ { \exp_not:n {#1} }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_pinyin_init:}
+% \begin{macrocode}
+\cs_new_nopar:Npn \@@_pinyin_init:
+ {
+ \tl_clear:N \l_@@_pre_tl \tl_clear:N \l_@@_post_tl
+ \tl_clear:N \l_@@_item_tl \tl_clear:N \l_@@_tone_tl
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_if_number:nTF}
+% \begin{macrocode}
+\prg_new_conditional:Npnn \@@_if_number:n #1 { TF }
+ {
+ \if_int_compare:w \c_one_int < 1 \tl_to_str:n {#1} \exp_stop_f:
+ \prg_return_true: \else: \prg_return_false: \fi:
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{variable}{\l_@@_first_bool}
+% \begin{macrocode}
+\bool_new:N \l_@@_first_bool
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}
+% {\c_@@_a_tl,\c_@@_o_tl,\c_@@_e_tl,\c_@@_i_tl,\c_@@_u_tl,\c_@@_v_tl}
+% \begin{macrocode}
+\tl_const:Nn \c_@@_a_tl { 3 }
+\tl_const:Nn \c_@@_o_tl { 2 }
+\tl_const:Nn \c_@@_e_tl { 2 }
+\tl_const:Nn \c_@@_i_tl { 1 }
+\tl_const:Nn \c_@@_u_tl { 1 }
+\tl_const:Nn \c_@@_v_tl { 1 }
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{macro}{\@@_num_to_tone:Nn}
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \@@_num_to_tone:Nn #1#2
+ {
+ \if_case:w \int_eval:n { #2 - 1 } \exp_stop_f:
+ \= {#1} \or: \'{#1} \or: \v {#1} \or: \` {#1} \else: #1 \fi:
+ }
+\tl_map_inline:nn { a o e u }
+ { \cs_new_eq:cN { @@_num_to_tone_ #1 :Nn } \@@_num_to_tone:Nn }
+\cs_new_nopar:Npn \@@_num_to_tone_i:Nn #1#2
+ {
+ \if_case:w \int_eval:n { #2 - 1 } \exp_stop_f:
+ ī \or: í \or: ǐ \or: ì \else: i \fi:
+ }
+\cs_new_protected_nopar:Npn \@@_num_to_tone_v:Nn #1#2
+ {
+ \str_case:onTF { \l_@@_pre_tl }
+ { { l } { } { n } { } { L } { } { N } { } }
+ {
+ \if_case:w \int_eval:n { #2 - 1 } \exp_stop_f:
+ ǖ \or: ǘ \or: ǚ \or: ǜ \else: ü \fi:
+ }
+ { \@@_num_to_tone:Nn u {#2} }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\xpinyinsetup}
+% \begin{macrocode}
+\NewDocumentCommand \xpinyinsetup { m } { \keys_set:nn { xpinyin } {#1} }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{ratio,vsep,hsep,pysep,font,format,multiple,footnote}
+% \begin{macrocode}
+\clist_map_inline:nn
+ { ratio , vsep , hsep , pysep , font , format , multiple }
+ { \keys_define:nn { xpinyin } { #1 .tl_set:c = { l_@@_ #1 _tl } } }
+\keys_define:nn { xpinyin }
+ { footnote .bool_set:N = \l_@@_footnote_bool }
+\keys_set:nn { xpinyin }
+ {
+ ratio = .4 ,
+ vsep = 1 em ,
+ pysep = \c_space_tl ,
+ font = \normalfont ,
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[int]{\xpinyin_customary:nnn,\xpinyin_multiple:nnn}
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \xpinyin_customary:nnn #1#2#3
+ { \cs_gset_nopar:cpn { c_@@_ #2 _tl } {#3} }
+\cs_new_protected_nopar:Npn \xpinyin_multiple:nnn #1#2#3
+ { \cs_gset_nopar:cpn { c_@@_multiple_ #2 _clist } {#3} }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macrocode}
+\group_begin:
+ \cs_set_eq:NN \XPYU \xpinyin_customary:nnn
+ \cs_set_eq:NN \XPYUM \xpinyin_multiple:nnn
+ \file_input:n { xpinyin-database.def }
+\group_end:
+% \end{macrocode}
+%
+% \begin{macro}{\setpinyin}
+% \begin{macrocode}
+\NewDocumentCommand \setpinyin { m m }
+ {
+ \tl_set:cn
+ { c_@@_ \@@_char_to_unicode:n {#1} _tl }
+ { \@@_pinyin:n {#2} }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macrocode}
+\ProcessKeysOptions { xpinyin }
+% \end{macrocode}
+%
+% \begin{macrocode}
+%</package>
+% \end{macrocode}
+%
+% \section{\pkg{xpinyin.lua}}
+%
+% \begin{macrocode}
+%<*lua>
+% \end{macrocode}
+%
+% \begin{macrocode}
+xpinyin = xpinyin or { }
+local xpinyin = xpinyin
+% \end{macrocode}
+%
+% 计算时区\footnote{\url{http://lua-users.org/wiki/TimeZone}}。
+% \begin{macrocode}
+xpinyin.tzoffset = "+0000"
+do
+ -- Compute the difference in seconds between local time and UTC.
+ local function get_timezone()
+ local now = os.time()
+ return os.difftime(now, os.time(os.date("!*t", now)))
+ end
+ -- Return a timezone string in ISO 8601:2000 standard form (+hhmm or -hhmm)
+ local function get_tzoffset(timezone)
+ local h, m = math.modf(timezone / 3600)
+ return string.format("%+.4d", 100 * h + 60 * m)
+ end
+ xpinyin.tzoffset = get_tzoffset(get_timezone())
+end
+% \end{macrocode}
+%
+% \begin{macrocode}
+xpinyin = {
+ uchar = unicode.utf8.char,
+ readings = { },
+ fixreadings = {
+% \end{macrocode}
+% 为汉字“〇”增加拼音。
+% \begin{macrocode}
+ {"U+3007", "Mandarin", "líng"}
+ },
+% \end{macrocode}
+%
+% \begin{macrocode}
+ database = {
+ source = "http://www.unicode.org/Public/UNIDATA/Unihan.zip",
+ file = "Unihan_Readings.txt",
+ date = "Date: 2014-05-09 18:17:02 GMT [JHJ]",
+ version = "Unicode version: 7.0.0",
+ dbfile = "xpinyin.db"
+ },
+ preamble = [[
+%<<COMMENT
+%%
+%% Do not edit this file!
+%% Created from Unihan database:
+%%
+%% $file
+%% $date
+%% $version
+%%
+%% by "texlua xpinyin.lua" on ]]
+ .. os.date("%Y-%m-%d %X ") .. xpinyin.tzoffset
+ .. "\n%%"
+%COMMENT
+}
+% \end{macrocode}
+%
+% \begin{macrocode}
+local http_request = require("socket.http").request
+local ltn12_sink_file = require("ltn12").sink.file
+local zip_open = require("zip").open
+% \end{macrocode}
+%
+% 将 \file{Unihan_Readings.txt}^^A
+% \footnote{\url{http://http://www.unicode.org/reports/tr38/}。} 保存到一张表里面。
+% \begin{macrocode}
+function xpinyin.maketable (txt)
+ local f = io.open(txt or xpinyin.database.file, "r")
+ if not f then
+ local source = xpinyin.database.source
+ local zfilename = source:match("[^/]+$")
+ local zfile = zip_open(zfilename)
+ if not zfile then
+ xpinyin.download(source, zfilename)
+ zfile = assert(zip_open(zfilename))
+ end
+ f = assert(zfile:open(xpinyin.database.file))
+ zfile:close()
+ end
+ local s, prop
+ for line in f:lines() do
+ s = line:explode("\t")
+ if #s == 3 then
+ prop = s[2]:sub(2)
+ if prop == "Mandarin" or
+ prop == "HanyuPinyin" or
+ prop == "XHC1983" or
+ prop == "HanyuPinlu" then
+ xpinyin.insert(s[1], prop, s[3])
+ end
+ elseif line:find("Date") then
+ xpinyin.database.date = line:match("^[#%s]*(.*)")
+ elseif line:find("Unicode version:") then
+ xpinyin.database.version = line:match("^[#%s]*(.*)")
+ end
+ end
+ f:close()
+ if xpinyin.fixreadings then
+ for _, s in pairs(xpinyin.fixreadings) do
+ xpinyin.insert(s[1], s[2], s[3])
+ end
+ end
+end
+% \end{macrocode}
+%
+% 下载 \file{Unihan.zip}。
+% \begin{macrocode}
+function xpinyin.download (source, zip)
+ print("\nRetrieving Unihan Database from\n", source)
+ local status, err = http_request{
+ url = source,
+ sink = ltn12_sink_file(io.open(zip, "wb")) }
+ if not status then
+ error([[Download ']] .. zip .. [[' failed because of ]] .. err .. ".")
+ end
+end
+% \end{macrocode}
+%
+% 往拼音表中加入项目。
+% \begin{macrocode}
+function xpinyin.insert (unicode, prop, value)
+ local index = tonumber(unicode:match("%x+$"), 16)
+ if not xpinyin.readings[index] then
+ xpinyin.readings[index] = { }
+ end
+ xpinyin.readings[index][prop] = value
+end
+% \end{macrocode}
+%
+% 输出需要的格式文件。
+% \begin{macrocode}
+function xpinyin.output (db)
+ local f = assert(io.open(db or xpinyin.database.dbfile, "w"))
+ local preamble = xpinyin.preamble:gsub("%$(%w+)", xpinyin.database)
+ f:write(preamble, "\n")
+ local hanzi, pinyin
+ local mt = { }
+ for index, pyt in xpinyin.pairsByKeys(xpinyin.readings) do
+ pinyin = assert(xpinyin.grep(pyt))
+ hanzi = xpinyin.uchar(index)
+ f:write("\\XPYU{", hanzi, "}{", index, "}{", pinyin, "}\n")
+ pinyin = xpinyin.multiple(pyt)
+ if pinyin then
+ mt[#mt + 1] = "\\XPYUM{" .. hanzi .. "}{" .. index .. "}{" .. pinyin .."}"
+ end
+ end
+ f:write(table.concat(mt, "\n"), "\n")
+ f:close()
+end
+% \end{macrocode}
+%
+% 将表按照索引排序,代码来源于
+% \href{http://www.lua.org/pil/19.3.html}{\textit{Programming in Lua}}。
+% \begin{macrocode}
+function xpinyin.pairsByKeys (t, f)
+ local a = { }
+ for n in pairs(t) do a[#a + 1] = n end
+ table.sort(a, f)
+ local i = 0 -- iterator variable
+ return function () -- iterator function
+ i = i + 1
+ return a[i], t[a[i]]
+ end
+end
+% \end{macrocode}
+%
+% 按照 \texttt{Mandarin}、\texttt{XHC1983}、\texttt{HanyuPinyin}
+% 的顺序选择最常用的拼音。\texttt{HanyuPinlu} 的质量较差,不采用。
+% \begin{macrocode}
+function xpinyin.grep (pyt)
+ if pyt.Mandarin then
+ return pyt.Mandarin:match("%S+"), "Mandarin"
+ elseif pyt.XHC1983 then
+ return pyt.XHC1983:match(":(%S+)"), "XHC1983"
+ elseif pyt.HanyuPinyin then
+ return pyt.HanyuPinyin:match(":([^,%s]+)"), "HanyuPinyin"
+ end
+end
+% \end{macrocode}
+%
+% 根据 \texttt{XHC1983} 和 \texttt{HanyuPinyin} 选出多音字。
+% \begin{macrocode}
+function xpinyin.multiple (pyt)
+ if pyt.XHC1983 then
+ local s = pyt.XHC1983:explode()
+ if s[2] then
+ local t = { }
+ for i, v in ipairs(s) do
+ t[#t + 1] = v:explode(":")[2]
+ end
+ return xpinyin.unique(t), "XHC1983"
+ end
+ elseif pyt.HanyuPinyin and pyt.HanyuPinyin:find("%D,") then
+ local t = { }
+ for _, v in ipairs(pyt.HanyuPinyin:explode()) do
+ for _, py in ipairs(v:explode(":")[2]:explode(",")) do
+ t[#t + 1] = py
+ end
+ end
+ return xpinyin.unique(t), "HanyuPinyin"
+ end
+end
+% \end{macrocode}
+%
+% 删除掉数组中的重复元素。
+% \begin{macrocode}
+function xpinyin.unique (t)
+ local rt = xpinyin.remove_duplicate(t)
+ if #rt > 1 then
+ return table.concat(rt, ",")
+ end
+end
+function xpinyin.remove_duplicate (t)
+ local ht = { }
+ local nt = { }
+ for i, v in ipairs(t) do
+ if not ht[v] then
+ nt[#nt + 1] = v
+ ht[v] = true
+ end
+ end
+ return nt
+end
+% \end{macrocode}
+%
+% \begin{macrocode}
+xpinyin.maketable()
+% \end{macrocode}
+%
+% \begin{macrocode}
+xpinyin.output()
+% \end{macrocode}
+%
+% \begin{macrocode}
+%</lua>
+% \end{macrocode}
+%
+% \end{implementation}
+%
+% \Finale
+%
+\endinput
diff --git a/macros/latex/contrib/xpinyin/xpinyin.ins b/macros/latex/contrib/xpinyin/xpinyin.ins
new file mode 100644
index 0000000000..bc0657b87a
--- /dev/null
+++ b/macros/latex/contrib/xpinyin/xpinyin.ins
@@ -0,0 +1,132 @@
+%%
+%% This is file `xpinyin.ins',
+%% generated with the docstrip utility.
+%%
+%% The original source files were:
+%%
+%% xpinyin.dtx (with options: `install')
+%%
+%% Copyright (C) 2012-2019 by Qing Lee <sobenlee@gmail.com>
+%% --------------------------------------------------------------------------
+%%
+%% This work may be distributed and/or modified under the
+%% conditions of the LaTeX Project Public License, either
+%% version 1.3c of this license or (at your option) any later
+%% version. This version of this license is in
+%% http://www.latex-project.org/lppl/lppl-1-3c.txt
+%% and the latest version of this license is in
+%% http://www.latex-project.org/lppl.txt
+%% and version 1.3 or later is part of all distributions of
+%% LaTeX version 2005/12/01 or later.
+%%
+%% This work has the LPPL maintenance status `maintained'.
+%%
+%% The Current Maintainer of this work is Qing Lee.
+%%
+%% --------------------------------------------------------------------------
+%%
+
+\begingroup\expandafter\expandafter\expandafter\endgroup
+\expandafter\ifx\csname directlua\endcsname\relax
+ \begingroup
+ \newlinechar=10 %
+ \errmessage{^^J
+ ********************************************^^J
+ * LuaTeX is required to unpack this package.^^J
+ ********************************************^^J
+ }
+ \endgroup
+ \csname @@end\expandafter\endcsname\expandafter\end
+\fi
+
+\input ctxdocstrip %
+
+\let\MetaPrefix\relax
+
+\preamble
+
+ Copyright (C) 2012-2019 by Qing Lee <sobenlee@gmail.com>
+--------------------------------------------------------------------------
+
+ This work may be distributed and/or modified under the
+ conditions of the LaTeX Project Public License, either
+ version 1.3c of this license or (at your option) any later
+ version. This version of this license is in
+ http://www.latex-project.org/lppl/lppl-1-3c.txt
+ and the latest version of this license is in
+ http://www.latex-project.org/lppl.txt
+ and version 1.3 or later is part of all distributions of
+ LaTeX version 2005/12/01 or later.
+
+ This work has the LPPL maintenance status `maintained'.
+
+ The Current Maintainer of this work is Qing Lee.
+
+--------------------------------------------------------------------------
+
+\endpreamble
+
+\postamble
+
+ This package consists of the file xpinyin.dtx,
+ and the derived files xpinyin.sty,
+ xpinyin.pdf,
+ xpinyin.ins,
+ xpinyin.lua,
+ xpinyin.db,
+ xpinyin-database.def and
+ README.md.
+\endpostamble
+
+\declarepostamble\emptypostamble
+\endpostamble
+
+\def\MetaPrefix{-- }
+
+\generate
+ {
+ \usedir{source/latex/xpinyin}
+ \usepostamble\emptypostamble
+ \file{xpinyin.lua} {\from{\jobname.dtx}{lua}}
+ }
+
+\let\MetaPrefix\DoubleperCent
+
+\directlua
+ {
+ if not kpse.find_file("xpinyin.db") then
+ dofile(kpse.find_file("xpinyin.lua"))
+ end
+ }
+\generate
+ {
+ \usedir{tex/latex/xpinyin}
+ \usepostamble\emptypostamble
+ \file{xpinyin-database.def}
+ {
+ \from{\jobname.dtx} {database}
+ \from{xpinyin.db} {}
+ }
+ }
+
+\generate
+ {
+ \usedir{tex/latex/xpinyin}
+ \file{xpinyin.sty} {\from{\jobname.dtx}{package}}
+ \nopreamble\nopostamble
+ \usedir{doc/latex/xpinyin}
+ \file{README.md} {\from{\jobname.dtx}{readme}}
+ }
+
+\endbatchfile
+%%
+%% This package consists of the file xpinyin.dtx,
+%% and the derived files xpinyin.sty,
+%% xpinyin.pdf,
+%% xpinyin.ins,
+%% xpinyin.lua,
+%% xpinyin.db,
+%% xpinyin-database.def and
+%% README.md.
+%%
+%% End of file `xpinyin.ins'.
diff --git a/macros/latex/contrib/xpinyin/xpinyin.pdf b/macros/latex/contrib/xpinyin/xpinyin.pdf
new file mode 100644
index 0000000000..e3ab9f27a2
--- /dev/null
+++ b/macros/latex/contrib/xpinyin/xpinyin.pdf
Binary files differ