1442 lines
41 KiB
TeX
1442 lines
41 KiB
TeX
% \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-2022 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-2022 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 dd0cc20 2022-07-14 18:53:49 +0800 Qing Lee <sobenlee@gmail.com> $
|
||
%<package> {Automatically add pinyin to Chinese characters}
|
||
%<package>\ProvidesExplPackage{\ExplFileName}
|
||
%<package> {\ExplFileDate}{3.1}{\ExplFileDescription}
|
||
%<database>\ProvidesFile{xpinyin-database.def}%
|
||
%<database> [2022/07/14 v3.1 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{695}
|
||
% \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}
|
||
% \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}
|
||
% \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}
|
||
% 设置多音字拼音的其他格式,缺省值为空。可以通过这个选项来提醒校正多音字的拼音。
|
||
% 注意这个选项会覆盖 \opt{format} 设置的格式。例如本文档设置多音字拼音的颜色是
|
||
% 红色(需要载入 \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}
|
||
\cs_if_exist:NF \NewDocumentCommand
|
||
{ \RequirePackage { xparse } }
|
||
% \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: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: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:Npn \@@_GBK_char_aux:nn #1#2
|
||
{ \exp_args:Nf \@@_GBK_char_aux:nnn { \int_eval:n { `#1 } } {#1} {#2} }
|
||
\cs_new_protected: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:Npn \@@_GBK_char_def:nnn #1#2#3
|
||
{
|
||
\cs_new_protected: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: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: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
|
||
{
|
||
\l_@@_pinyin_box_hook_tl
|
||
\@@_select_font:
|
||
\l_@@_format_tl
|
||
\clist_if_exist:cT { c_@@_multiple_ #1 _clist }
|
||
{ \l_@@_multiple_tl }
|
||
{#3}
|
||
}
|
||
\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:Npn \@@_CJKsymbol:n #1
|
||
{ \@@_CJKsymbol:xn { \@@_to_unicode:n {#1} } {#1} }
|
||
\cs_new_protected: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: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: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:Npn \@@_single_aux:nn #1#2
|
||
{
|
||
\@@_replace_CJKsymbol_single:n {#2}
|
||
#1
|
||
\group_end:
|
||
}
|
||
\cs_new_protected:Npn \@@_replace_CJKsymbol_single_aux:n #1
|
||
{
|
||
\bool_if:NF \l_@@_enable_bool { \@@_replace_CJKsymbol: }
|
||
\cs_set_protected:Npn \CJKsymbol ##1
|
||
{ \@@_single_CJKsymbol:nn {##1} {#1} }
|
||
}
|
||
\cs_new_protected: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: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: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: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: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: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:Npn \@@_UTF_to_unicode:n #1
|
||
{
|
||
\int_to_arabic:n
|
||
{ \exp_args:No \int_from_hex:n { \CJK@plane } * "100 + #1 }
|
||
}
|
||
\cs_new:Npn \@@_UTFchar_to_unicode:n #1
|
||
{ \int_to_arabic:n { \@@_UTF_viii_to_unicode:NNNw #1 \q_stop } }
|
||
\cs_new: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:Npn \@@_GBK_to_unicode:n
|
||
{ \CJKtu_sfd_map:nn { \CJK@plane } }
|
||
\cs_new:Npn \@@_GBKchar_to_unicode:n
|
||
{ \CJKtu_char_to_unicode:n }
|
||
% \end{macrocode}
|
||
% \end{macro}
|
||
%
|
||
% \begin{macro}{\@@_adjust_xeCJK_hook:}
|
||
% \begin{macrocode}
|
||
\cs_new_protected: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: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: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:Npn \@@_adjust_CJKpunct_hook:
|
||
{
|
||
\cs_new_protected: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: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: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: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: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: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: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: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: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: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: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: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:Npn \xpinyin_customary:nnn #1#2
|
||
{ \cs_gset_nopar:cpn { c_@@_ #2 _tl } }
|
||
\cs_new_protected:Npn \xpinyin_multiple:nnn #1#2
|
||
{ \cs_gset_nopar:cpn { c_@@_multiple_ #2 _clist } }
|
||
% \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}
|
||
\cs_if_exist:NTF \ProcessKeyOptions
|
||
{ \ProcessKeyOptions [ xpinyin ] }
|
||
{
|
||
\RequirePackage { l3keys2e }
|
||
\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
|