% \iffalse meta-comment % !TEX program = XeLaTeX %<*internal> \iffalse % %<*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 ---------------------------------------------------------------------- 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). % %<*internal> \fi \begingroup \def\temp{LaTeX2e} \expandafter\endgroup\ifx\temp\fmtname\else \csname fi\endcsname % %<*install> %\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-2022 by Qing Lee -------------------------------------------------------------------------- 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 { % %<*internal> \usedir{source/latex/xpinyin} \file{xpinyin.ins} {\from{\jobname.dtx}{install}} % %<*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 % %<*internal> \fi % %\NeedsTeXFormat{LaTeX2e} %\RequirePackage{expl3} %<+package>\GetIdInfo$Id: xpinyin.dtx dd0cc20 2022-07-14 18:53:49 +0800 Qing Lee $ % {Automatically add pinyin to Chinese characters} %\ProvidesExplPackage{\ExplFileName} % {\ExplFileDate}{3.1}{\ExplFileDescription} %\ProvidesFile{xpinyin-database.def}% % [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} % % \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} \{ =, =, ... \} % \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} % % \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 = [[ %< 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} % % \end{macrocode} % % \end{implementation} % % \Finale % \endinput