From e0c6872cf40896c7be36b11dcc744620f10adf1d Mon Sep 17 00:00:00 2001 From: Norbert Preining Date: Mon, 2 Sep 2019 13:46:59 +0900 Subject: Initial commit --- macros/latex/contrib/zhnumber/README.md | 65 + macros/latex/contrib/zhnumber/zhnumber.dtx | 1955 ++++++++++++++++++++++++++++ macros/latex/contrib/zhnumber/zhnumber.ins | 89 ++ macros/latex/contrib/zhnumber/zhnumber.pdf | Bin 0 -> 270690 bytes 4 files changed, 2109 insertions(+) create mode 100644 macros/latex/contrib/zhnumber/README.md create mode 100644 macros/latex/contrib/zhnumber/zhnumber.dtx create mode 100644 macros/latex/contrib/zhnumber/zhnumber.ins create mode 100644 macros/latex/contrib/zhnumber/zhnumber.pdf (limited to 'macros/latex/contrib/zhnumber') diff --git a/macros/latex/contrib/zhnumber/README.md b/macros/latex/contrib/zhnumber/README.md new file mode 100644 index 0000000000..a8ac1b7a7c --- /dev/null +++ b/macros/latex/contrib/zhnumber/README.md @@ -0,0 +1,65 @@ +zhnumber +======== + +The `zhnumber` package provides commands to typeset Chinese representations of +numbers. The main difference between this package and `CJKnumb` is that commands +provided by this package is expandable in the proper way. So, it seems that +zhnumber is a good alternative to `CJKnumb` package. + +Basic Usage +----------- +The package provides the following macros: + + \zhnumber{} + +Convert `` to a full Chinese representation. + + \zhnum{} + +Similar to `\arabic{}`, but representation of `` +as Chinese numerals. + + \zhdigits{} + \zhdigits*{} + +Handle `` as a string of digits and convert each of them into the +corresponding Chinese digit. The starred version uses the Chinese circle glyph +for digit zero; the unstarred version uses the traditional glyph. + +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, 2014-2019 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 zhnumber.dtx, + and the derived files zhnumber.pdf, + zhnumber.sty, + zhnumber-utf8.cfg, + zhnumber-gbk.cfg, + zhnumber-big5.cfg, + zhnumber.ins and + README.md (this file). diff --git a/macros/latex/contrib/zhnumber/zhnumber.dtx b/macros/latex/contrib/zhnumber/zhnumber.dtx new file mode 100644 index 0000000000..05472f8fd1 --- /dev/null +++ b/macros/latex/contrib/zhnumber/zhnumber.dtx @@ -0,0 +1,1955 @@ +% \iffalse meta-comment +% !TEX program = XeLaTeX +%<*internal> +\iffalse +% +%<*readme> +zhnumber +======== + +The `zhnumber` package provides commands to typeset Chinese representations of +numbers. The main difference between this package and `CJKnumb` is that commands +provided by this package is expandable in the proper way. So, it seems that +zhnumber is a good alternative to `CJKnumb` package. + +Basic Usage +----------- +The package provides the following macros: + + \zhnumber{} + +Convert `` to a full Chinese representation. + + \zhnum{} + +Similar to `\arabic{}`, but representation of `` +as Chinese numerals. + + \zhdigits{} + \zhdigits*{} + +Handle `` as a string of digits and convert each of them into the +corresponding Chinese digit. The starred version uses the Chinese circle glyph +for digit zero; the unstarred version uses the traditional glyph. + +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, 2014-2019 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 zhnumber.dtx, + and the derived files zhnumber.pdf, + zhnumber.sty, + zhnumber-utf8.cfg, + zhnumber-gbk.cfg, + zhnumber-big5.cfg, + zhnumber.ins and + README.md (this file). +% +%<*internal> +\fi +\begingroup + \def\temp{LaTeX2e} +\expandafter\endgroup\ifx\temp\fmtname\else +\csname fi\endcsname +% +%<*install> + +\input ctxdocstrip % + +\preamble + + Copyright (C) 2012, 2014-2019 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 zhnumber.dtx, + and the derived files zhnumber.pdf, + zhnumber.sty, + zhnumber-utf8.cfg, + zhnumber-gbk.cfg, + zhnumber-big5.cfg, + zhnumber.ins and + README.md. +\endpostamble + +\generate + { +% +%<*internal> + \usedir{source/latex/zhnumber} + \file{zhnumber.ins} {\from{\jobname.dtx}{install}} +% +%<*install> + \usedir{tex/latex/zhnumber} + \file{zhnumber.sty} {\from{\jobname.dtx}{package}} + \usedir{tex/latex/zhnumber/config} + \file{zhnumber-utf8.cfg} {\from{\jobname.dtx}{config,utf8}} + \file{zhnumber-big5.cfg} {\from{\jobname.dtx}{config,big5}} + \file{zhnumber-gbk.cfg} {\from{\jobname.dtx}{config,gbk}} + \nopreamble\nopostamble + \usedir{doc/latex/zhnumber} + \file{README.md} {\from{\jobname.dtx}{readme}} + } + +\endbatchfile +% +%<*internal> +\fi +% +%\NeedsTeXFormat{LaTeX2e} +%\RequirePackage{expl3} +%<+package|config>\GetIdInfo$Id: zhnumber.dtx 311c61d 2019-04-07 23:29:51 +0800 Qing Lee $ +% {Typesetting numbers with Chinese glyphs} +% {Chinese numerals with UTF8 encoding} +% {Chinese numerals with Big5 encoding} +% {Chinese numerals with GBK encoding} +%\ProvidesExplPackage{\ExplFileName} +%\ProvidesExplFile{\ExplFileName-utf8.cfg} +%\ProvidesExplFile{\ExplFileName-big5.cfg} +%\ProvidesExplFile{\ExplFileName-gbk.cfg} +% {\ExplFileDate}{2.7}{\ExplFileDescription} +%<*driver> +\documentclass{ctxdoc} +\begin{document} + \DocInput{\jobname.dtx} + \IndexLayout + \PrintIndex +\end{document} +% +% \fi +% +% \CheckSum{1186} +% \GetFileId{zhnumber.sty} +% +% \title{\bfseries\pkg{zhnumber} 宏包} +% \author{李清\\ \path{sobenlee@gmail.com}} +% \date{\filedate\qquad\fileversion\thanks{\ctexkitrev{\ExplFileVersion}.}} +% \maketitle +% +% \begin{documentation} +% +% \section{简介} +% \pkg{zhnumber} 宏包用于将阿拉伯数字按照中文格式输出。相比于 \pkg{CJKnumb},它提供 +% 的四个格式转换命令 \tn{zhnumber},\tn{zhdigits}、\tn{zhnum} 和 \tn{zhdig} +% 都是可以适当展开的,可以正常使用于 |PDF| 书签和交叉引用。 +% +% \pkg{zhnumber} 支持 |GBK|,|Big5| 和 |UTF8| 编码,依赖 \LaTeXiii{} 项目的 +% \pkg{expl3},\pkg{xparse} 和 \pkg{l3keys2e} 宏包。 +% +% \section{使用方法} +% +% \begin{function}[updated=2014-09-09]{encoding} +% \begin{syntax} +% encoding = +% \end{syntax} +% 用于指定编码的宏包选项,可以在调用宏包的时候设定,也可以用 \tn{zhnumsetup} +% 在导言区内设定。对于 \upLaTeX、\XeLaTeX{} 和 \LuaLaTeX,不用指定编码,宏包将 +% 自动使用 |UTF8| 编码。只有 \LaTeX{} 和 \pdfLaTeX{} 需要指定编码,如果没有指定, +% 默认将使用 |GBK|。 +% \end{function} +% +% \begin{function}[rEXP, updated=2014-09-12]{\zhnumber} +% \begin{syntax} +% \tn{zhnumber} \Arg{number} +% \end{syntax} +% 以中文格式输出数字。这里的数字可以是整数、小数和分数。例如 +% \begin{SideBySideExample}[frame=single,numbers=left,xrightmargin=.6\linewidth,gobble=5] +% \zhnumber{2012020120}\\ +% \zhnumber{2 012 020 120}\\ +% \zhnumber{2,012,020,120}\\ +% \zhnumber{2012.020120}\\ +% \zhnumber{2012.}\\ +% \zhnumber{.2012}\\ +% \zhnumber{20120/20120}\\ +% \zhnumber{/2012}\\ +% \zhnumber{2012/}\\ +% \zhnumber{201;2020/120} +% \end{SideBySideExample} +% \end{function} +% +% \begin{function}[rEXP, updated=2014-09-09]{\zhdigits} +% \begin{syntax} +% \tn{zhdigits} \Arg{number} +% \tn{zhdigits} * \Arg{number} +% \end{syntax} +% 将阿拉伯数字转换为中文数字串。缺省状态下,\tn{zhdigits} 将 0 映射为〇,如果需要 +% 将其映射为零,可以使用带星号的形式。例如 +% \begin{SideBySideExample}[frame=single,numbers=left,xrightmargin=.6\linewidth,gobble=5] +% \zhdigits{2012020120}\\ +% \zhdigits*{2012020120} +% \end{SideBySideExample} +% \end{function} +% +% \begin{function}[rEXP, updated=2016-05-01]{\zhnum} +% \begin{syntax} +% \tn{zhnum} \Arg{counter} +% \tn{pagenumbering} \{zhnum\} +% \end{syntax} +% 与 |\roman| 等类似,用于将 \LaTeX 计数器的值转换为中文数字。例如 +% \begin{SideBySideExample}[frame=single,numbers=left,xrightmargin=.6\linewidth,gobble=5] +% \zhnum{section} +% \end{SideBySideExample} +% \end{function} +% +% \begin{function}[rEXP, added=2016-05-01]{\zhdig} +% \begin{syntax} +% \tn{zhdig} \Arg{counter} +% \tn{pagenumbering} \{zhdig\} +% \end{syntax} +% 与 |\roman| 等类似,用于将 \LaTeX 计数器的值转换为中文数字串。例如 +% \begin{SideBySideExample}[frame=single,numbers=left,xrightmargin=.6\linewidth,gobble=5] +% \zhdig{section} +% \end{SideBySideExample} +% \end{function} +% +% \begin{function}[rEXP, added=2012-05-25]{\zhweekday} +% \begin{syntax} +% \tn{zhweekday} \Arg{yyyy/mm/dd} +% \end{syntax} +% 输出日期当天的星期。例如 +% \begin{SideBySideExample}[frame=single,numbers=left,xrightmargin=.6\linewidth,gobble=5] +% \zhweekday{2012/5/20} +% \end{SideBySideExample} +% \end{function} +% +% \begin{function}[rEXP, added=2012-05-25]{\zhdate} +% \begin{syntax} +% \tn{zhdate} \Arg{yyyy/mm/dd} +% \tn{zhdate} * \Arg{yyyy/mm/dd} +% \end{syntax} +% 以中文格式输出日期,其中带 |*| 的命令还输出星期。例如 +% \begin{SideBySideExample}[frame=single,numbers=left,xrightmargin=.6\linewidth,gobble=5] +% \zhdate{2012/5/21}\\ +% \zhdate*{2012/5/21} +% \end{SideBySideExample} +% \end{function} +% +% \begin{function}[rEXP, added=2012-05-25]{\zhtoday} +% 与 |\today| 类似,以中文输出当天的日期。例如 +% \begin{SideBySideExample}[frame=single,numbers=left,xrightmargin=.6\linewidth,gobble=5] +% \zhtoday +% \end{SideBySideExample} +% \end{function} +% +% \begin{function}[rEXP, added=2012-05-25]{\zhtime} +% \begin{syntax} +% \tn{zhtime} \Arg{hh:mm} +% \end{syntax} +% 以中文格式输出时间。例如 +% \begin{SideBySideExample}[frame=single,numbers=left,xrightmargin=.6\linewidth,gobble=5] +% \zhtime{23:56} +% \end{SideBySideExample} +% \end{function} +% +% \begin{function}[rEXP, added=2012-05-25]{\zhcurrtime} +% 输出当前的时间。例如 +% \begin{SideBySideExample}[frame=single,numbers=left,xrightmargin=.6\linewidth,gobble=5] +% \zhcurrtime +% \end{SideBySideExample} +% \end{function} +% +% \begin{function}[rEXP, added=2015-05-20]{\zhtiangan} +% \begin{syntax} +% \tn{zhtiangan} \Arg{number} +% \end{syntax} +% 输出对应的天干计数。\meta{number} 的正常范围是 1--10,超出范围的数字将输出空值。例如 +% \begin{SideBySideExample}[frame=single,numbers=left,xrightmargin=.4\linewidth,gobble=5] +% \zhtiangan{1} \zhtiangan{2} \zhtiangan{3} +% \zhtiangan{4} \zhtiangan{5} \zhtiangan{10} +% \end{SideBySideExample} +% \end{function} +% +% \begin{function}[rEXP, added=2015-05-20]{\zhdizhi} +% \begin{syntax} +% \tn{zhdizhi} \Arg{number} +% \end{syntax} +% 输出对应的地支计数。\meta{number} 的正常范围是 1--12,超出范围的数字将输出空值。例如 +% \begin{SideBySideExample}[frame=single,numbers=left,xrightmargin=.4\linewidth,gobble=5] +% \zhdizhi{1} \zhdizhi{2} \zhdizhi{3} +% \zhdizhi{4} \zhdizhi{5} \zhdizhi{12} +% \end{SideBySideExample} +% \end{function} +% +% \begin{function}[rEXP, added=2015-05-20]{\zhganzhi} +% \begin{syntax} +% \tn{zhganzhi} \Arg{number} +% \end{syntax} +% 输出对应的干支计数。\meta{number} 的正常范围是 1--60,超出范围的数字将输出空值。例如 +% \begin{SideBySideExample}[frame=single,numbers=left,xrightmargin=.4\linewidth,gobble=5] +% \zhganzhi{1} \zhganzhi{2} \zhganzhi{3} \\ +% \zhganzhi{4} \zhganzhi{5} \zhganzhi{60} +% \end{SideBySideExample} +% \end{function} +% +% \begin{function}[rEXP, added=2015-05-20]{\zhganzhinian} +% \begin{syntax} +% \tn{zhganzhinian} \Arg{year} +% \end{syntax} +% 输出公元纪年 \meta{year} 对应的干支纪年。公元前的年份用负数表示。例如 +% \begin{SideBySideExample}[frame=single,numbers=left,xrightmargin=.4\linewidth,gobble=5] +% \zhganzhinian{1898} \zhganzhinian{-246} \\ +% \zhganzhinian{-2697} \zhganzhinian{\year} +% \end{SideBySideExample} +% \end{function} +% +% \begin{function}[added=2012-05-25]{\zhnumExtendScaleMap} +% \begin{syntax} +% \tn{zhnumExtendScaleMap} \oarg{character} \{, , ..., \} +% \end{syntax} +% 缺省状态下 \tn{zhnumber} 能正确中文格式化的最大整数是 $10^{48}-1$,\tn{zhdigits} 不受 +% 这个大小的限制。可以通过 \tn{zhnumExtendScaleMap} 来扩展 \tn{zhnumber}。 +% \meta{character_i} 设置 $10^{4(i+11)}$。若给出可选项 \meta{character},则当 +% 数字大于 $10^{4(n+12)}-1$ 时,统一用 \meta{character} 设置输出数字的进位。 +% \end{function} +% +% \begin{function}{\zhnumsetup} +% \begin{syntax} +% \tn{zhnumsetup} \{=, =, ...\} +% \end{syntax} +% 用于在导言区或文档中,设置中文数字的输出格式。目前可以设置的 \meta{key} 如下介绍。 +% 以\textbf{粗体}表示选项的默认值。 +% \end{function} +% +% \begin{function}[added=2012-05-25]{time} +% \begin{syntax} +% time = <(Arabic)|Chinese> +% \end{syntax} +% 设置日期和时间的数字格式,\meta{Arabic} 为阿拉伯数字,而 \meta{Chinese} 为中文数字。 +% 例如 +% \begin{SideBySideExample}[frame=single,numbers=left,xrightmargin=.6\linewidth,gobble=5] +% \zhnumsetup{time=Chinese} +% \zhtoday\zhcurrtime +% \end{SideBySideExample} +% \end{function} +% +% \begin{function}[added=2016-05-01]{arabicsep} +% \begin{syntax} +% arabicsep = \Arg{sep} +% \end{syntax} +% 设置日期和时间的数字格式为阿拉伯数字时,阿拉伯数字与汉字的间隔内容。默认为一个空格。 +% \end{function} +% +% \begin{function}[updated=2012-05-25]{style} +% \begin{syntax} +% style = <(Simplified)|Traditional|(Normal)|Financial|Ancient> +% \end{syntax} +% 意义分别为 +% +% \begin{description}[font=\mdseries\ttfamily\small,align=right,leftmargin=*, +% labelsep=\marginparsep,labelindent=-\marginparsep] +% \item[Simplified] 以简体中文输出数字(对 |Big5| 编码无效); +% \item[Traditional] 以繁体中文输出数字(对 |Big5| 编码无效); +% \item[Normal] 以小写形式输出中文数字; +% \item[Financial] 以大写形式输出中文数字; +% \item[Ancient] 以廿输出 20,以卅输出 30,以卌输出 40,以皕输出 200。 +% \end{description} +% +% 可以设置 |style| 为其中一个,也可以是前三个与后两个的适当组合,默认是简体小写。例如 +% \begin{SideBySideExample}[frame=single,numbers=left,xrightmargin=.4\linewidth,gobble=5] +% \zhnumsetup{style={Traditional,Financial}} +% \zhnumber{62012.3}\\ +% \zhnumsetup{style=Ancient} +% \zhnumber{21} +% \end{SideBySideExample} +% \end{function} +% +% \begin{function}{null} +% \begin{syntax} +% null = <\TFF> +% \end{syntax} +% 缺省状态下,除了 \tn{zhdigits} 外,其它的格式转换命令,将 0 映射成零,如果需要将 0 映射 +% 成〇,可以使用这个选项。 +% \end{function} +% +% \begin{function}[added=2015-05-20]{ganzhi-cyclic} +% \begin{syntax} +% ganzhi-cyclic = <\TFF> +% \end{syntax} +% 天干、地支和干支的数字都有一定范围。若参数大于这个范围,\tn{tiangan} 等将输出空值。 +% 可以将本选项设置为 |true|,对超出范围的数字取相应的模。 +% 请注意,数字 |0| 的结果总是为空值。例如 +% \begin{SideBySideExample}[frame=single,numbers=left,xrightmargin=.3\linewidth,gobble=5] +% \zhnumsetup{ganzhi-cyclic} +% \zhtiangan{11} \zhtiangan{12} \zhtiangan{209} +% \zhtiangan{-1} \zhtiangan{-2} \zhtiangan{-683} \\ +% \zhdizhi{13} \zhdizhi{24} \zhdizhi{1211} +% \zhdizhi{-1} \zhdizhi{-2} \zhdizhi{-8199} \\ +% \zhganzhi{61} \zhganzhi{72} \zhganzhi{2158} \\ +% \zhganzhi{-1} \zhganzhi{-2} \zhganzhi{-789} +% \end{SideBySideExample} +% \end{function} +% +%\bigskip +% \pkg{zhnumber} 提供下列选项来控制阿拉伯数字的中文映射。 +% \begin{verbatim}[frame=single] +% - -0 0 1 2 3 4 5 6 7 8 9 10 20 30 40 100 200 1000 +% E2 E3 E4 E8 E12 E16 E20 E24 E28 E32 E36 E40 E44 +% F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F100 F1000 FE2 FE3 +% T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 +% D1 D2 D3 D4 D5 D6 D7 D8 D9 D10 D11 D12 +% GZ1 GZ2 GZ3 GZ4 GZ5 GZ6 GZ7 GZ8 GZ9 GZ10 ... GZ60 +% dot and parts +% year month day hour minute weekday mon tue wed thu fri sat sun +% \end{verbatim} +% 其中 |-| 设置负,|-0| 设置〇,|dot| 设置小数的点,|and| 和 |parts| 分别设置分数 +% 的“又”和“分之”,|E|$n$ 设置 $10^n$,|F|$n$ 设置数字 $n$ 的大写,|T|$n$ 设置 +% 数字 $n$ 的天干,|D|$n$ 设置数字 $n$ 的地支,而 |GZ|$n$ 设置数字 $n$ 的干支。 +% 其它的选项同字面意思,不再赘述。例如 +% \begin{verbatim}[frame=single] +% \zhnumsetup{2={两}} +% \end{verbatim} +% 可以将 2 映射成两。需要说明的是,\pkg{zhnumber} 将优先使用这里的设置,所以可能会影响 +% 到 |style| 选项。如果要恢复 |style| 的功能,可以使用 |reset| 选项。 +% +% \begin{function}[updated=2014-09-12]{reset} +% \begin{syntax} +% reset +% \end{syntax} +% 用于恢复 \pkg{zhnumber} 对阿拉伯数字的初始化映射。\pkg{zhnumber} 的中文数字初始化 +% 设置见源代码(第 \ref{sec:zhnum-map} 节)。 +% \end{function} +% +% \begin{function}[added=2014-09-09]{activechar} +% \begin{syntax} +% activechar = <\TTF> +% \end{syntax} +% 在 \LaTeX{} 或者 \pdfLaTeX{} 下面输出汉字,传统的办法需要将汉字的首字节设置为 +% 活动字符,然后再通过特殊的宏技巧来实现。因此,\pkg{zhnumber} 在载入配置文件的 +% 时候,默认会将汉字的首字节设置为活动字符。禁用本选项将不会改变汉字首字节的 +% 类代码。需要在本选项之后,使用 \texttt{encoding} 或者 \texttt{reset} 选项 +% 才会有效果。 +% \end{function} +% +% \begin{function}[updated=2016-05-01]{\zhnumber,\zhdigits,\zhnum,\zhdig} +% \begin{syntax} +% \tn{zhnumber} \oarg{options} \Arg{number} +% \tn{zhdigits} * \oarg{options} \Arg{number} +% \tn{zhnum} \oarg{options} \Arg{counter} +% \tn{zhdig} \oarg{options} \Arg{counter} +% \end{syntax} +% 如果只改变当前数字的中文输出格式,可以使用带选项的格式转换命令,其中 \meta{options} +% 与 \tn{zhnumsetup} 的参数相同,如上所介绍。这些带了选项的命令是不可展开的,在某些场合使 +% 用时要小心。 +% \end{function} +% +% \end{documentation} +% +% \StopEventually{} +% +% \begin{implementation} +% +% \section{\pkg{zhnumber} 宏包代码实现} +% +% \begin{macrocode} +%<*package> +% \end{macrocode} +% +% \begin{macrocode} +%<@@=zhnum> +% \end{macrocode} +% +% \begin{macrocode} +\msg_new:nnn { zhnumber } { 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 { zhnumber } { l3-too-old } } +% \end{macrocode} +% +% \begin{macrocode} +\RequirePackage { xparse , l3keys2e } +% \end{macrocode} +% +% \begin{macro}{\zhnumber} +% 用于将输入的数字按照中文格式输出。 +% \begin{macrocode} +\DeclareExpandableDocumentCommand \zhnumber { +o +m } + { + \IfNoValueTF {#1} + { \zhnum_number:f } + { \zhnumberwithoptions {#1} } + {#2} + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[int]{\zhnumberwithoptions} +% 带选项的用户函数。 +% \begin{macrocode} + \NewDocumentCommand \zhnumberwithoptions { +m +m } + { + \group_begin: + \keys_set:nn { zhnum / options } {#1} + \zhnum_number:f {#2} + \group_end: + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[int]{\zhnum_number:n} +% \begin{macro}{\@@_number:www} +% 先判断输入的是小数还是分数。 +% \begin{macrocode} +\cs_new:Npn \zhnum_number:n #1 + { \@@_number:www #1 . \q_nil . \q_stop } +\cs_new:Npn \@@_number:www #1 . #2 . #3 \q_stop + { + \quark_if_nil:nTF {#2} + { \@@_integer_or_fraction:www #1 / \q_nil / \q_stop } + { \zhnum_decimal:nn {#1} {#2} } + } +\cs_generate_variant:Nn \zhnum_number:n { f } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@@_integer_or_fraction:www} +% 判断是否输入的是分数。 +% \begin{macrocode} +\cs_new:Npn \@@_integer_or_fraction:www #1 / #2 / #3 \q_stop + { + \quark_if_nil:nTF {#2} + { \zhnum_integer:n {#1} } + { \@@_fraction:wwww #2 \q_mark #1 ; \q_nil ; \q_stop } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_fraction:wwww} +% 对分数进行预处理。 +% \begin{macrocode} +\cs_new:Npn \@@_fraction:wwww #1 \q_mark #2 ; #3 ; #4 \q_stop + { + \quark_if_nil:nTF {#3} + { + \zhnum_blank_to_zero:n {#1} + \c_@@_parts_tl + \zhnum_blank_to_zero:n {#2} + } + { + \tl_if_blank:nF {#2} + { + \zhnum_number:n {#2} + \c_@@_and_tl + } + \zhnum_blank_to_zero:n {#1} + \c_@@_parts_tl + \zhnum_blank_to_zero:n {#3} + } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[int]{\zhnum_decimal:nn} +% 对小数进行预处理。 +% \begin{macrocode} +\cs_new:Npn \zhnum_decimal:nn #1#2 + { + \zhnum_blank_to_zero:n {#1} \c_@@_dot_tl + \tl_if_blank:nTF {#2} + { \c_@@_zero_tl } + { \zhnum_digits_zero:n {#2} } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[int]{\zhnum_blank_to_zero:n} +% 输出小数的整数位。 +% \begin{macrocode} +\cs_new:Npn \zhnum_blank_to_zero:n #1 + { + \tl_if_blank:nTF {#1} + { \c_@@_zero_tl } + { \zhnum_number:n {#1} } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\zhnum,\zhnumberwithoptions} +% 用于将 \LaTeX{} 计数器按中文格式输出。 +% \begin{macrocode} +\DeclareExpandableDocumentCommand \zhnum { +o +m } + { + \IfNoValueTF {#1} + { \zhnum_counter:n } + { \zhnumwithoptions {#1} } + {#2} + } +\NewDocumentCommand \zhnumwithoptions { +m +m } + { + \group_begin: + \keys_set:nn { zhnum / options } {#1} + \zhnum_counter:n {#2} + \group_end: + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[int]{\zhnum_counter:n, \zhnum_int:n} +% 可以直接通过比较 \LaTeX{} 计数器的值来得到符号和绝对值。 +% \begin{macrocode} +\cs_new:Npn \zhnum_counter:n #1 + { + \int_if_exist:cTF { c@#1 } + { \exp_args:Nc \zhnum_int:n { c@#1 } } + { \@@_counter_error:n {#1} } + } +\cs_new:Npn \@@_counter_error:n #1 + { \msg_expandable_error:nnn { zhnumber } { not-counter } {#1} } +\msg_new:nnn { zhnumber } { not-counter } + { `#1'~is~not~a~LaTeX~counter. } +\cs_new:Npn \zhnum_int:n #1 + { + \int_compare:nNnTF {#1} > \c_zero_int + { \zhnum_parse_number:f { \int_eval:n {#1} } } + { + \int_compare:nNnTF {#1} < \c_zero_int + { + \c_@@_minus_tl + \zhnum_parse_number:f { \int_eval:n { - #1 } } + } + { \c_@@_zero_tl } + } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[int]{\@zhnum} +% 用于支持 |\pagenumbering{zhnum}|。 +% \begin{macrocode} +\cs_new_nopar:Npn \@zhnum { \zhnum_int:n } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[int]{\zhnum_integer:n} +% 对整数的处理。这个函数基本抄录自 \pkg{l3bigint} 的 \cs{__bingint_read_do:nn}。它可以 +% 正确取得符号,去掉多余的零,还可以循环展开数字。但它在遇到非数字的时候就停止了 +% 循环,我们可能需要非数字(例如逗号)来作为分隔符号。因此对它略作修改,跳过非数字。 +% \begin{macrocode} +\cs_new:Npn \zhnum_integer:n #1 + { + \exp_after:wN \@@_read_integer:www + \int_value:w + \exp_after:wN \@@_read_sign_loop:N + \exp:w \exp_end_continue_f:w \use:n + #1 \exp_stop_f: \q_recursion_tail \q_recursion_stop + \@@_result:nn { \c_zero_int } { } ; + } +\cs_new:Npn \@@_read_sign_loop:N #1 + { + \if:w + \if:w - \exp_not:N #1 + \fi: \exp_not:N #1 + \exp_after:wN \@@_read_sign_loop:N + \exp:w \exp_end_continue_f:w \exp_after:wN \use:n + \else: + 1 \exp_after:wN ; + \exp:w \exp_end_continue_f:w + \exp_after:wN \@@_read_zeros_loop:N + \exp_after:wN #1 + \fi: + } +\cs_new:Npn \@@_read_zeros_loop:N #1 + { + \if:w 0 \exp_not:N #1 + \exp_after:wN \@@_read_zeros_loop:N + \exp:w \exp_end_continue_f:w \exp_after:wN \use:n + \else: + \exp_after:wN \@@_read_abs_loop:Nw + \exp_after:wN #1 + \fi: + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_read_abs_loop:Nw} +% 当数字很大时,\pkg{l3bigint} 的实现会造成 \TeX{} 内存溢出: +% \begin{verbatim} +% ! TeX capacity exceeded, sorry [expansion depth=10000]. +% \end{verbatim} +% 我们在这里参考 \cs{__tl_act:NNNnn} 的实现对它进行了改进。 +% \begin{macrocode} +\cs_new:Npn \@@_read_abs_loop:Nw #1#2 \q_recursion_stop + { + \zhnum_if_digit:NTF #1 + { \@@_output:nnwnn { + 1 } #1 } + { \quark_if_recursion_tail_stop_do:Nn #1 { \@@_loop_end:wnn } } + \exp_after:wN \@@_read_abs_loop:Nw + \exp:w \exp_end_continue_f:w \use:n #2 \q_recursion_stop + } +\cs_new:Npn \@@_output:nnwnn #1#2#3 \@@_result:nn #4#5 + { #3 \@@_result:nn { #4#1 } { #5#2 } } +\cs_new:Npn \@@_loop_end:wnn #1 \@@_result:nn #2#3 + { \int_eval:n {#2} ; #3 } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_read_integer:www} +% |#1| 符号,|#3| 是绝对值,|#2| 是绝对值的长度。 +% \begin{macrocode} +\cs_new:Npn \@@_read_integer:www #1 ; #2 ; #3 ; + { + \int_compare:nNnTF {#2} = \c_zero_int + { \c_@@_zero_tl } + { + \int_compare:nNnF {#1} = \c_one_int + { \c_@@_minus_tl } + \zhnum_parse_number:nn {#2} {#3} + } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[int]{\zhnum_if_digit:NTF} +% 判断 |#1| 是否为数字位。 +% \begin{macrocode} +\cs_new:Npn \zhnum_if_digit:NTF #1 + { + \if_int_compare:w 9 < 1 \exp_not:N #1 \exp_stop_f: + \exp_after:wN \use_i:nn + \else: + \exp_after:wN \use_ii:nn + \fi: + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[int] +% { +% \zhnum_parse_number:n, +% \zhnum_parse_number:nn +% } +% \begin{macrocode} +\cs_new:Npn \zhnum_parse_number:n #1 + { \exp_args:Nf \zhnum_parse_number:nn { \tl_count:n {#1} } {#1} } +\cs_new:Npn \zhnum_parse_number:nn #1 + { \exp_args:Nf \@@_parse_number:nnn { \int_mod:nn {#1} { 4 } } {#1} } +\cs_new:Npn \@@_parse_number:nnn #1#2 + { + \int_compare:nNnTF {#2} < 2 + { \zhnum_digit_map:n } + { + \int_compare:nNnTF {#1} = \c_zero_int + { \zhnum_split_number:fn { \int_eval:n { #2 / 4 - 1 } } } + { \@@_split_number_aux:nnn {#1} {#2} } + } + } +\cs_generate_variant:Nn \zhnum_parse_number:n { f } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_split_number_aux:nnn} +% 为了处理的方便,在整数前面补上适当的 $0$,使其位数可以被 $4$ 整除。 +% \begin{macrocode} +\cs_new:Npn \@@_split_number_aux:nnn #1#2 + { + \exp_after:wN \@@_split_number_aux:wwn + \int_value:w \int_div_truncate:nn {#2} { 4 } + \if_case:w #1 \exp_stop_f: + \or: \exp_after:wN \use:n + \or: \exp_after:wN \use_i_ii:nnn + \or: \exp_after:wN \use_i:nnn + \fi: + { \exp_stop_f: ; 0 } 0 0 ; + } +\cs_new:Npn \@@_split_number_aux:wwn #1 ; #2 ; #3 + { \zhnum_split_number:nn {#1} { #2#3 } } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[int]{\zhnum_split_number:nn} +% 最后加入的 \cs{q_recursion_tail} 是停止递归的标志,而 \cs{q_nil} 用于占位。 +% \begin{macrocode} +\cs_new:Npn \zhnum_split_number:nn #1#2 + { + \zhnum_split_number:NNnNNNNw \c_true_bool \c_true_bool {#1} + #2 \q_recursion_tail \q_nil \q_nil \q_nil \q_recursion_stop + } +\cs_generate_variant:Nn \zhnum_split_number:nn { f } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[int]{\zhnum_split_number:NNnNNNNw} +% 将输入的整数由高位到低位,以四位为一段进行处理。 +% \begin{macrocode} +\cs_new:Npn \zhnum_split_number:NNnNNNNw #1#2#3#4#5#6#7 + { + \quark_if_recursion_tail_stop:N #4 + \int_compare:nNnTF { #4#5#6#7 } = \c_zero_int + { \use_i:nn } + { + \bool_if:NF #1 { \c_@@_zero_tl } + \zhnum_process_number:NNNNNN #4#5#6#7#1#2 + \zhnum_scale_map:n {#3} + \int_compare:nNnTF {#7} = \c_zero_int + } + { \zhnum_split_number:NNfNNNNw \c_false_bool \c_true_bool } + { \zhnum_split_number:NNfNNNNw \c_true_bool \c_false_bool } + { \int_eval:n { #3 - 1 } } + } +\cs_generate_variant:Nn \zhnum_split_number:NNnNNNNw { NNf } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[int]{\zhnum_process_number:NNNNNN} +% 对四位数字按情况进行处理。 +% \begin{macrocode} +\cs_new:Npn \zhnum_process_number:NNNNNN #1#2#3#4#5#6 + { + \int_compare:nNnTF {#1} = \c_zero_int + { \bool_if:NF #6 { \c_@@_zero_tl } } + { \zhnum_digit_map:n {#1} \c_@@_thousand_tl } + \int_compare:nNnTF {#2} = \c_zero_int + { \int_compare:nNnF { #1 * (#3#4) } = \c_zero_int { \c_@@_zero_tl } } + { + \bool_lazy_and:nnTF + { \l_@@_ancient_bool } + { \int_compare_p:nNn {#2} = 2 } + { \zhnum_digit_map:n { #2 00 } } + { \zhnum_digit_map:n {#2} \c_@@_hundred_tl } + } + \int_compare:nNnTF {#3} = \c_zero_int + { \int_compare:nNnF { #2 * #4 } = \c_zero_int { \c_@@_zero_tl } } + { + \bool_lazy_all:nF + { + { \int_compare_p:nNn {#3} = \c_one_int } + { \int_compare_p:nNn {#1#2} = \c_zero_int } + {#6} + {#5} + } + { + \bool_lazy_and:nnTF + { \l_@@_ancient_bool } + { \int_compare_p:n { 1 < #3 < 5 } } + { \zhnum_digit_map:n { #3 0 } \use_none:n } + { \zhnum_digit_map:n {#3} } + } + \c_@@_ten_tl + } + \int_compare:nNnF {#4} = \c_zero_int { \zhnum_digit_map:n {#4} } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\zhdig} +% 用于将 \LaTeX{} 计数器按中文数字串输出。 +% \begin{macrocode} +\DeclareExpandableDocumentCommand \zhdig { +o +m } + { + \IfNoValueTF {#1} + { \zhnum_digits_counter:n } + { \zhdigwithoptions {#1} } + {#2} + } +\NewDocumentCommand \zhdigwithoptions { +m +m } + { + \group_begin: + \keys_set:nn { zhnum / options } {#1} + \zhnum_digits_counter:n #1 {#2} + \group_end: + } +\cs_new:Npn \zhnum_digits_counter:n #1 + { + \int_if_exist:cTF { c@#1 } + { \zhnum_digits_null:v { c@#1 } } + { \@@_counter_error:n {#1} } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[int]{\@zhdig} +% 用于支持 |\pagenumbering{zhdig}|。 +% \begin{macrocode} +\cs_new_nopar:Npn \@zhdig #1 { \zhnum_digits_null:f { \int_eval:n {#1} } } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\zhdigits,\zhdigitswithoptions} +% 将输入的数字输出为中文数字串输出。 +% \begin{macrocode} +\DeclareExpandableDocumentCommand \zhdigits { +s +o +m } + { + \IfNoValueTF {#2} + { \zhnum_digits:Nn #1 } + { \zhdigitswithoptions {#1} {#2} } + {#3} + } +\NewDocumentCommand \zhdigitswithoptions { +m +m +m } + { + \group_begin: + \keys_set:nn { zhnum / options } {#2} + \zhnum_digits:Nn #1 {#3} + \group_end: + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[int]{\zhnum_digits_zero:n,\zhnum_digits_null:n} +% 快捷方式。 +% \begin{macrocode} +\cs_new_nopar:Npn \zhnum_digits_zero:n + { \zhnum_digits:Nn \BooleanTrue } +\cs_new_nopar:Npn \zhnum_digits_null:n + { \zhnum_digits:Nn \BooleanFalse } +\cs_generate_variant:Nn \zhnum_digits_null:n { V , v , f } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[int]{\zhnum_digits:Nn} +% 与 \cs{zhnum_integer:n} 类似,但不用去掉多余的零。 +% \begin{macrocode} +\cs_new:Npn \zhnum_digits:Nn #1#2 + { + \exp_after:wN \@@_read_digits:w + \int_value:w + \exp_after:wN \@@_read_sign_loop:NN \exp_after:wN #1 + \exp:w \exp_end_continue_f:w \use:n + #2 \exp_stop_f: \q_recursion_tail \q_recursion_stop + } +\cs_new:Npn \@@_read_sign_loop:NN #1#2 + { + \if:w + \if:w - \exp_not:N #2 + \fi: \exp_not:N #2 + \exp_after:wN \@@_read_sign_loop:NN \exp_after:wN #1 + \exp:w \exp_end_continue_f:w \exp_after:wN \use:n + \else: + 1 \exp_after:wN ; + \exp_after:wN \@@_read_digits_loop:NN + \exp_after:wN #1 + \exp_after:wN #2 + \fi: + } +\cs_new:Npn \@@_read_digits_loop:NN #1#2 + { + \zhnum_if_digit:NTF #2 + { \@@_output_digits:NN #1#2 } + { + \quark_if_recursion_tail_stop:N #2 + \if:w .\exp_not:N #2 \exp_after:wN \c_@@_dot_tl \fi: + } + \exp_after:wN \@@_read_digits_loop:NN \exp_after:wN #1 + \exp:w \exp_end_continue_f:w \use:n + } +\cs_new:Npn \@@_read_digits:w #1 ; + { + \int_compare:nNnF {#1} = \c_one_int + { \c_@@_minus_tl } + } +\cs_new:Npn \@@_output_digits:NN #1#2 + { + \cs:w + c_@@_ + \if_int_compare:w #2 = \c_zero_int + \IfBooleanTF #1 { zero } { null } + \else: + #2 + \fi: + _tl + \cs_end: + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\zhdate} +% 输出中文日期。 +% \begin{macrocode} +\DeclareExpandableDocumentCommand \zhdate { +s +m } + { + \@@_date:www #2 \q_stop + \IfBooleanT #1 + { \@@_week_day:www #2 \q_stop } + } +\cs_new:Npn \@@_date:www #1/#2/#3 \q_stop + { \@@_date_aux:nnn {#1} {#2} {#3} } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\zhtoday} +% 输出当天日期。 +% \begin{macrocode} +\cs_new_nopar:Npn \zhtoday + { \@@_date_aux:Vnn \tex_year:D \tex_month:D \tex_day:D } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_date_aux:nnn} +% \begin{macrocode} +\cs_new_nopar:Npn \@@_date_aux:nnn + { + \bool_if:NTF \l_@@_time_bool + { \@@_date_aux:NNnnnn \zhnum_digits_null:n \zhnum_int:n { } } + { \@@_date_aux:Nnnnn \int_to_arabic:n { \l_@@_arabic_sep_tl } } + } +\cs_new:Npn \@@_date_aux:Nnnnn #1 + { \@@_date_aux:NNnnnn #1#1 } +\cs_new:Npn \@@_date_aux:NNnnnn #1#2#3#4#5#6 + { + #1 {#4} #3 \c_@@_year_tl #3 + #2 {#5} #3 \c_@@_month_tl #3 + #2 {#6} #3 \c_@@_day_tl + } +\cs_generate_variant:Nn \@@_date_aux:nnn { V } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\zhweekday} +% 输出星期 +% \begin{macrocode} +\cs_new:Npn \zhweekday #1 + { \@@_week_day:www #1 \q_stop } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_week_day:www} +% 用 Zeller 公式计算的结果 $h$ 与实际星期的关系是 $d=h+5\pmod7+1$。 +% \begin{macrocode} +\cs_new:Npn \@@_week_day:www #1/#2/#3 \q_stop + { + \if_case:w \zhnum_Zeller:nnn {#1} {#2} {#3} \exp_stop_f: + \c_@@_sat_tl + \or: \c_@@_sun_tl + \or: \c_@@_mon_tl + \or: \c_@@_tue_tl + \or: \c_@@_wed_tl + \or: \c_@@_thu_tl + \or: \c_@@_fri_tl + \fi: + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[int]{\zhnum_Zeller:nnn,\zhnum_Zeller_aux:Nnnn,\zhnum_two_digits:n} +% 用 Zeller 公式\footnote{\url{http://en.wikipedia.org/wiki/Zeller's_congruence}} +% 计算星期几。 +% \begin{macrocode} +\cs_new:Npn \zhnum_Zeller:nnn #1#2#3 + { + \int_compare:nNnTF + { #1 \zhnum_two_digits:n {#2} \zhnum_two_digits:n {#3} } > { 1582 10 04 } + { \@@_Zeller_aux:Nnnn \zhnum_Zeller_Gregorian:nnn } + { \@@_Zeller_aux:Nnnn \zhnum_Zeller_Julian:nnn } + {#1} {#2} {#3} + } +\cs_new:Npn \@@_Zeller_aux:Nnnn #1#2#3#4 + { + \int_compare:nNnTF {#3} < 3 + { #1 { #2 - 1 } { #3 + 12 } {#4} } + { #1 {#2} {#3} {#4} } + } +\cs_new:Npn \zhnum_two_digits:n #1 + { + \int_compare:nNnT {#1} < { 10 } { 0 } + \int_eval:n {#1} + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[int]{\zhnum_Zeller_Gregorian:nnn} +% 格里历(\zhdate{1582/10/15}及以后)的计算公式 +% \[ +% h = \biggl(q + \biggl\lfloor\frac{26(m+1)}{10}\biggr\rfloor + Y + +% \biggl\lfloor\frac Y4\biggr\rfloor + 6\biggl\lfloor\frac Y{100}\biggr\rfloor +% + \biggl\lfloor\frac Y{400}\biggr\rfloor\biggr) \pmod 7 +% \] +% 其中 $Y$ 为年,$m$ 为月,$q$ 为日;若 $m=1,2$,则令 $m\mathbin{{+}{=}}12$,同时 $Y\mathop{--}{}$。 +% \begin{macrocode} +\cs_new:Npn \zhnum_Zeller_Gregorian:nnn #1#2#3 + { + \int_mod:nn + { + (#3) + + \int_div_truncate:nn { 26 * ( #2 + 1 ) } { 10 } + + (#1) + + \int_div_truncate:nn {#1} { 4 } + + 6 * \int_div_truncate:nn {#1} { 100 } + + \int_div_truncate:nn {#1} { 400 } + } + { 7 } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[int]{\zhnum_Zeller_Julian:nnn} +% 儒略历(\zhdate{1582/10/04}及以前)的计算公式 +% \[ +% h = \biggl(q + \biggl\lfloor\frac{26(m+1)}{10}\biggr\rfloor + Y + +% \biggl\lfloor\frac Y4\biggr\rfloor + 5\biggr) \pmod 7 +% \] +% \begin{macrocode} +\cs_new:Npn \zhnum_Zeller_Julian:nnn #1#2#3 + { + \int_mod:nn + { + (#3) + + \int_div_truncate:nn { 26 * ( #2 + 1 ) } { 10 } + + (#1) + + \int_div_truncate:nn {#1} { 4 } + + 5 + } + { 7 } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\zhtime} +% 输出时间。 +% \begin{macrocode} +\cs_new:Npn \zhtime #1 + { \@@_time:ww #1 \q_stop } +\use:x + { + \cs_new:Npn \exp_not:N \@@_time:ww ##1 \c_colon_str ##2 \exp_not:N \q_stop + } + { \@@_time_aux:nn {#1} {#2} } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\zhcurrtime} +% 输出当前时间。 +% \begin{macrocode} +\cs_new_nopar:Npn \zhcurrtime + { + \@@_time_aux:nn + { \int_div_truncate:nn \tex_time:D { 60 } } + { \int_mod:nn \tex_time:D { 60 } } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_time_aux:nn,\@@_time_aux:Nnnn} +% \begin{macrocode} +\cs_new_nopar:Npn \@@_time_aux:nn + { + \bool_if:NTF \l_@@_time_bool + { \@@_time_aux:Nnnn \zhnum_int:n { } } + { \@@_time_aux:Nnnn \int_to_arabic:n { \l_@@_arabic_sep_tl } } + } +\cs_new:Npn \@@_time_aux:Nnnn #1#2#3#4 + { + #1 {#3} #2 \c_@@_hour_tl #2 + #1 {#4} #2 \c_@@_minute_tl + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[int]{\zhnum_digit_map:n} +% 阿拉伯数字与中文数字的映射。 +% \begin{macrocode} +\cs_new:Npn \zhnum_digit_map:n #1 + { \use:c { c_@@_ #1 _tl } } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[int]{\zhnum_scale_map:n,\zhnum_scale_map_loop:n} +% 大数系统的映射。 +% \begin{macrocode} +\cs_new:Npn \zhnum_scale_map:n #1 + { + \cs_if_exist_use:cF { c_@@_s #1 _tl } + { \zhnum_scale_map_hook:n {#1} } + } +\cs_new:Npn \zhnum_scale_map_loop:n #1 + { \zhnum_scale_map:n { \int_mod:nn {#1} \l_@@_scale_int } } +\cs_generate_variant:Nn \zhnum_scale_map:n { f } +\int_new:N \l_@@_scale_int +\int_set:Nn \l_@@_scale_int { 11 } +\cs_new_eq:NN \zhnum_scale_map_hook:n \zhnum_scale_map_loop:n +\tl_const:cn { c_@@_s0_tl } { } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\zhnumExtendScaleMap} +% 扩展进位系统。 +% \begin{macrocode} +\NewDocumentCommand \zhnumExtendScaleMap { > { \TrimSpaces } +o +m } + { + \int_zero:N \l_tmpa_int + \clist_map_function:nN {#2} \zhnum_set_scale:n + \IfNoValueF {#1} + { \cs_set:Npn \zhnum_scale_map_hook:n ##1 {#1} } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[int]{\zhnum_set_scale:n} +% \begin{macrocode} +\cs_new_protected:Npn \zhnum_set_scale:n #1 + { + \int_incr:N \l_tmpa_int + \tl_set:Nx \l_tmpa_tl + { c_@@_s \int_eval:n { \l_tmpa_int + 11 } _tl } + \tl_if_exist:cF { \l_tmpa_tl } + { \int_incr:N \l_@@_scale_int } + \tl_set:cn { \l_tmpa_tl } {#1} + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[int]{\zhnum_ganzhi_normal:nnn} +% 保证干支的参数为正数。 +% \begin{macrocode} +\cs_new:Npn \zhnum_ganzhi_normal:nnn #1#2#3 + { + \int_compare:nNnF {#1} < \c_one_int + { \cs_if_exist_use:c { c_@@_ #2 _ #1 _tl } } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[int]{\zhnum_ganzhi_cyclic:nnn} +% \begin{macro}{\@@_ganzhi_cyclic_mod:nnnn} +% 对超出范围的数字取模,参数 |0| 的结果是空值。 +% \begin{macrocode} +\cs_new:Npn \zhnum_ganzhi_cyclic:nnn #1#2#3 + { + \int_compare:nNnF {#1} = \c_zero_int + { + \cs_if_exist_use:cF { c_@@_ #2 _ #1 _tl } + { + \@@_ganzhi_cyclic_mod:fnnn + { \int_mod:nn {#1} {#3} } {#1} {#2} {#3} + } + } + } +\cs_new:Npn \@@_ganzhi_cyclic_mod:nnnn #1#2#3#4 + { + \int_compare:nNnTF {#2} > \c_zero_int + { \use:c { c_@@_ #3 _ #1 _tl } } + { + \int_compare:nNnTF {#1} = \c_zero_int + { \use:c { c_@@_ #3 _ 1 _tl } } + { \use:c { c_@@_ #3 _ \int_eval:n { #1 + #4 + 1 } _tl } } + } + } +\cs_generate_variant:Nn \@@_ganzhi_cyclic_mod:nnnn { f } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}[int]{\zhnum_ganzhi:nnn} +% 默认不对超出范围的数字取模。 +% \begin{macrocode} +\cs_new_eq:NN \zhnum_ganzhi:nnn \zhnum_ganzhi_normal:nnn +\cs_generate_variant:Nn \zhnum_ganzhi:nnn { f } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\zhtiangan} +% 天干。 +% \begin{macrocode} +\cs_new:Npn \zhtiangan #1 + { \zhnum_ganzhi:fnn { \int_eval:n {#1} } { tiangan } { 10 } } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\zhdizhi} +% 地支。 +% \begin{macrocode} +\cs_new:Npn \zhdizhi #1 + { \zhnum_ganzhi:fnn { \int_eval:n {#1} } { dizhi } { 12 } } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\zhganzhi} +% 干支。 +% \begin{macrocode} +\cs_new:Npn \zhganzhi #1 + { \zhnum_ganzhi:fnn { \int_eval:n {#1} } { ganzhi } { 60 } } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\zhganzhinian} +% 干支纪年。 +% \begin{macrocode} +\cs_new:Npn \zhganzhinian #1 + { \zhnum_ganzhi_nian:f { \int_eval:n {#1} } } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[int]{\zhnum_ganzhi_nian:n} +% 干支纪年。公元元年是 |\zhganzhi{58}|。 +% \begin{macrocode} +\cs_new:Npn \zhnum_ganzhi_nian:n #1 + { + \int_compare:nNnTF {#1} > \c_zero_int + { \use:c { c_@@_ganzhi_ \int_mod:nn { #1 + 57 } { 60 } _tl } } + { + \int_compare:nNnF {#1} = \c_zero_int + { + \use:c + { + c_@@_ganzhi_ + \int_eval:n { \int_mod:nn { #1 - 2 } { 60 } + 60 } + _tl + } + } + } + } +\cs_generate_variant:Nn \zhnum_ganzhi_nian:n { f } +% \end{macrocode} +% \end{macro} +% +% 根据需要设置中文阿拉伯数字。 +% \begin{macrocode} +\group_begin: + \tl_set:Nn \l_tmpa_tl + { + - .tl_set:N = \l_@@_minus_tl , + -0 .tl_set:N = \l_@@_null_tl , + } + \tl_put_right:Nx \l_tmpa_tl + { + E2 .tl_set:N = \exp_not:c { l_@@_ 100 _tl } , + E3 .tl_set:N = \exp_not:c { l_@@_ 1000 _tl } , + FE2 .tl_set:N = \exp_not:c { l_@@_financial_ 100 _tl } , + FE3 .tl_set:N = \exp_not:c { l_@@_financial_ 1000 _tl } , + D11 .tl_set:N = \exp_not:c { l_@@_dizhi_ 11 _tl } , + D12 .tl_set:N = \exp_not:c { l_@@_dizhi_ 12 _tl } , + E44 .tl_set:N = \exp_not:c { l_@@_ s11 _tl } , + } + \int_step_inline:nn { 10 } + { + \tl_put_right:Nx \l_tmpa_tl + { + #1 .tl_set:N = \exp_not:c { l_@@_ #1 _tl } , + F#1 .tl_set:N = \exp_not:c { l_@@_financial_ #1 _tl } , + T#1 .tl_set:N = \exp_not:c { l_@@_tiangan_ #1 _tl } , + D#1 .tl_set:N = \exp_not:c { l_@@_dizhi_ #1 _tl } , + GZ#1 .tl_set:N = \exp_not:c { l_@@_ganzhi_ #1 _tl } , + E \int_eval:n { #1 * 4 } + .tl_set:N = \exp_not:c { l_@@_ s#1 _tl } , + } + } + \int_step_inline:nnn { 11 } { 60 } + { + \tl_put_right:Nx \l_tmpa_tl + { GZ#1 .tl_set:N = \exp_not:c { l_@@_ganzhi_ #1 _tl } , } + } + \clist_map_inline:nn { 0 , 100 , 1000 } + { + \tl_put_right:Nx \l_tmpa_tl + { + #1 .tl_set:N = \exp_not:c { l_@@_ #1 _tl } , + F#1 .tl_set:N = \exp_not:c { l_@@_financial_ #1 _tl } , + } + } + \clist_map_inline:nn { 20 , 30 , 40 , 200 } + { + \tl_put_right:Nx \l_tmpa_tl + { #1 .tl_set:N = \exp_not:c { l_@@_ #1 _tl } , } + } + \clist_map_inline:nn + { + dot , and , parts , year , month , day , weekday , hour , minute + mon , tue , wed , thu , fri , sat , sun + } + { + \tl_put_right:Nx \l_tmpa_tl + { #1 .tl_set:N = \exp_not:c { l_@@_ #1 _tl } , } + } +\use:x + { + \group_end: + \keys_define:nn { zhnum / options } { \exp_not:o \l_tmpa_tl } + } +% \end{macrocode} +% +% \begin{macro}[int] +% { +% \zhnum_set_digits_map:nn, +% \zhnum_set_digits_map:nnn, +% \zhnum_set_financial_map:nn, +% \zhnum_set_financial_map:nnn, +% \zhnum_set_tiangan_map:nn, +% \zhnum_set_dizhi_map:nn +% } +% \begin{variable} +% { +% \l_@@_cfg_map_prop, +% \l_@@_cfg_map_var_prop, +% \l_@@_cfg_map_finan_prop, +% \l_@@_cfg_map_ganzhi_prop +% } +% 将配置文件中的中文数字保存到 \texttt{prop} 变量中。 +% \begin{macrocode} +\cs_new_protected:Npn \zhnum_set_digits_map:nn #1#2 + { \prop_put:Nnn \l_@@_cfg_map_prop {#1} {#2} } +\cs_new_protected:Npn \zhnum_set_digits_map:nnn #1#2#3 + { + \prop_put_if_new:Nnn \l_@@_cfg_map_prop {#1} {#3} + \prop_put:Nnn \l_@@_cfg_map_var_prop {#1_#2} {#3} + } +\cs_new_protected:Npn \zhnum_set_financial_map:nn #1#2 + { \prop_put:Nnn \l_@@_cfg_map_finan_prop {#1} {#2} } +\cs_new_protected:Npn \zhnum_set_financial_map:nnn #1#2#3 + { + \prop_put_if_new:Nnn \l_@@_cfg_map_finan_prop {#1} {#3} + \prop_put:Nnn \l_@@_cfg_map_var_prop { financial_#1_#2 } {#3} + } +\cs_new_protected:Npn \zhnum_set_tiangan_map:nn #1#2 + { \prop_put:Nnn \l_@@_cfg_map_ganzhi_prop { tiangan_#1 } {#2} } +\cs_new_protected:Npn \zhnum_set_dizhi_map:nn #1#2 + { \prop_put:Nnn \l_@@_cfg_map_ganzhi_prop { dizhi_#1 } {#2} } +\prop_new:N \l_@@_cfg_map_prop +\prop_new:N \l_@@_cfg_map_var_prop +\prop_new:N \l_@@_cfg_map_finan_prop +\prop_new:N \l_@@_cfg_map_ganzhi_prop +% \end{macrocode} +% \end{variable} +% \end{macro} +% +% \begin{macro}[int] +% { +% \zhnum_parse_config:, +% \zhnum_check_simp:nn, +% \zhnum_check_financial:nn, +% \zhnum_set_zero:, +% \zhnum_set_week_day: +% } +% 将 \texttt{prop} 表转化到单独的 \texttt{tl} 变量。 +% \begin{macrocode} +\cs_new_protected_nopar:Npn \zhnum_parse_config: + { + \prop_map_function:NN \l_@@_cfg_map_prop \zhnum_check_simp:nn + \prop_map_function:NN \l_@@_cfg_map_ganzhi_prop \zhnum_assgin_ganzhi:nn + \zhnum_set_zero: + \zhnum_set_week_day: + \bool_if:NF \l_@@_reset_bool + { + \zhnum_assgin_const: + \bool_set_true:N \l_@@_reset_bool + } + } +\cs_new_protected:Npn \zhnum_check_simp:nn #1#2 + { + \@@_check_simp_aux:nn {#2} {#1} + \prop_get:NnNT \l_@@_cfg_map_finan_prop {#1} \l_tmpa_tl + { \exp_args:No \@@_check_simp_aux:nn { \l_tmpa_tl } { financial_ #1 } } + } +\cs_new_protected:Npn \@@_check_simp_aux:nn #1#2 + { + \prop_get:NnNTF \l_@@_cfg_map_var_prop { #2 _trad } \l_tmpa_tl + { + \prop_get:NnNF \l_@@_cfg_map_var_prop { #2 _simp } \l_tmpb_tl + { \tl_set:Nn \l_tmpb_tl {#1} } + \tl_set:cx { l_@@_ #2 _tl } + { + \exp_not:n { \bool_if:NTF \l_@@_simp_bool } + { \exp_not:o \l_tmpb_tl } { \exp_not:o \l_tmpa_tl } + } + } + { \tl_set:cn { l_@@_ #2 _tl } {#1} } + } +\cs_new_protected_nopar:Npn \zhnum_assgin_const: + { + \prop_map_function:NN \l_@@_cfg_map_prop \zhnum_check_financial:nn + \zhnum_set_alias: + } +\cs_new_protected:Npn \zhnum_check_financial:nn #1#2 + { + \prop_get:NnNTF \l_@@_cfg_map_finan_prop {#1} \l_tmpa_tl + { + \zhnum_assgin_const_tl:cx { c_@@_ #1 _tl } + { + \exp_not:n { \bool_if:NTF \l_@@_normal_bool } + { \exp_not:c { l_@@_ #1 _tl } } + { \exp_not:c { l_@@_financial_ #1 _tl } } + } + } + { + \zhnum_assgin_const_tl:cx + { c_@@_ #1 _tl } { \exp_not:c { l_@@_ #1 _tl } } + } + } +\cs_new_protected_nopar:Npn \zhnum_set_zero: + { + \tl_set:cx { l_@@_0_tl } + { + \exp_not:n { \bool_if:NTF \l_@@_null_bool } + { \exp_not:o \l_@@_null_tl } { \exp_not:v { l_@@_0_tl } } + } + } +\cs_new_protected_nopar:Npn \zhnum_set_week_day: + { + \tl_set:Nx \l_@@_mon_tl + { \exp_not:N \c_@@_weekday_tl \exp_not:v { l_@@_1_tl } } + \tl_set:Nx \l_@@_tue_tl + { \exp_not:N \c_@@_weekday_tl \exp_not:v { l_@@_2_tl } } + \tl_set:Nx \l_@@_wed_tl + { \exp_not:N \c_@@_weekday_tl \exp_not:v { l_@@_3_tl } } + \tl_set:Nx \l_@@_thu_tl + { \exp_not:N \c_@@_weekday_tl \exp_not:v { l_@@_4_tl } } + \tl_set:Nx \l_@@_fri_tl + { \exp_not:N \c_@@_weekday_tl \exp_not:v { l_@@_5_tl } } + \tl_set:Nx \l_@@_sat_tl + { \exp_not:N \c_@@_weekday_tl \exp_not:v { l_@@_6_tl } } + \tl_set:Nx \l_@@_sun_tl + { \exp_not:N \c_@@_weekday_tl \exp_not:o \l_@@_day_tl } + } +\clist_map_inline:nn { mon , tue , wed , thu , fri , sat , sun } + { \tl_const:cx { c_@@_ #1 _tl } { \exp_not:c { l_@@_ #1 _tl } } } +\cs_new_protected:Npn \zhnum_assgin_ganzhi:nn #1#2 + { \tl_set:cn { l_@@_ #1 _tl } {#2} } +\cs_new:Npn \zhnum_zero_mod:nn #1#2 + { \exp_args:Nf \@@_zero_mod_aux:nn { \int_mod:nn {#1} {#2} } {#2} } +\cs_new:Npn \@@_zero_mod_aux:nn #1#2 + { \int_compare:nNnTF {#1} = \c_zero_int {#2} {#1} } +\int_step_inline:nn { 60 } + { + \tl_const:cx { c_@@_ganzhi_ #1 _tl } { \exp_not:c { l_@@_ganzhi_ #1 _tl } } + \tl_set:cx { l_@@_ganzhi_ #1 _tl } + { + \exp_not:c { l_@@_tiangan_ \zhnum_zero_mod:nn {#1} { 10 } _tl } + \exp_not:c { l_@@_dizhi_ \zhnum_zero_mod:nn {#1} { 12 } _tl } + } + } +\cs_new_eq:cc { c_@@_ganzhi_ 0 _tl } { c_@@_ganzhi_ 60 _tl } +\cs_new_eq:NN \zhnum_assgin_const_tl:cx \tl_const:cx +\AtEndOfPackage + { + \prop_map_inline:Nn \l_@@_cfg_map_ganzhi_prop + { \tl_const:cx { c_@@_ #1 _tl } { \exp_not:c { l_@@_ #1 _tl } } } + \cs_new_eq:cc { c_@@_tiangan_ 0 _tl } { c_@@_tiangan_ 10 _tl } + \cs_new_eq:cc { c_@@_dizhi_ 0 _tl } { c_@@_dizhi_ 12 _tl } + \cs_set_eq:NN \zhnum_assgin_const_tl:cx \tl_set:cx + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[int]{\zhnum_set_alias:} +% 一些易于使用的别名。 +% \begin{macrocode} +\cs_new_eq:NN \zhnum_set_alias:NN \cs_new_eq:NN +\cs_new_protected_nopar:Npx \zhnum_set_alias: + { + \zhnum_set_alias:NN \exp_not:N \c_@@_zero_tl + \exp_not:c { c_@@_ 0 _tl } + \zhnum_set_alias:NN \exp_not:N \c_@@_ten_tl + \exp_not:c { c_@@_ 10 _tl } + \zhnum_set_alias:NN \exp_not:N \c_@@_hundred_tl + \exp_not:c { c_@@_ 100 _tl } + \zhnum_set_alias:NN \exp_not:N \c_@@_thousand_tl + \exp_not:c { c_@@_ 1000 _tl } + } +\AtEndOfPackage + { \cs_set_eq:NN \zhnum_set_alias:NN \tl_set_eq:NN } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[int]{\zhnum_load_cfg:n} +% 根据选定编码载入配置文件。 +% \begin{macrocode} +\cs_new_protected:Npn \zhnum_load_cfg:n #1 + { + \zhnum_set_cfg_name:Nn \l_@@_cfg_str {#1} + \str_if_eq:NNF \l_@@_cfg_str \l_@@_last_cfg_str + { \zhnum_update_cfg:n {#1} } + \zhnum_parse_config: + } +\cs_generate_variant:Nn \zhnum_load_cfg:n { o } +\cs_new_protected:Npn \zhnum_update_cfg:n #1 + { + \prop_if_exist:cTF { g_@@_cfg_ \l_@@_cfg_str _prop } + { \str_set_eq:NN \l_@@_last_cfg_str \l_@@_cfg_str } + { \zhnum_input_cfg:n {#1} } + \@@_update_cfg_prop:N \prop_set_eq:Nc + } +\cs_new_protected:Npn \zhnum_input_cfg:n #1 + { + \file_if_exist:nTF { zhnumber - #1 .cfg } + { + \bool_set_false:N \l_@@_reset_bool + \@@_update_cfg_prop:N \@@_prop_initial:Nn + \group_begin: + \zhnum_set_catcode: + \file_input:n { zhnumber - #1 .cfg } + \@@_update_cfg_prop:N \@@_prop_gset_eq:Nn + \group_end: + } + { \msg_error:nnx { zhnumber } { file-not-found } {#1} } + } +\cs_new_protected:Npn \@@_update_cfg_prop:N #1 + { + #1 \l_@@_cfg_map_prop { g_@@_cfg_ \l_@@_cfg_str _prop } + #1 \l_@@_cfg_map_var_prop { g_@@_cfg_var_ \l_@@_cfg_str _prop } + #1 \l_@@_cfg_map_finan_prop { g_@@_cfg_finan_ \l_@@_cfg_str _prop } + #1 \l_@@_cfg_map_ganzhi_prop { g_@@_cfg_ganzhi_ \l_@@_cfg_str _prop } + } +\cs_new_protected:Npn \@@_prop_initial:Nn #1#2 + { + \prop_clear:N #1 + \prop_new:c {#2} + } +\cs_new_protected:Npn \@@_prop_gset_eq:Nn #1#2 + { \prop_gset_eq:cN {#2} #1 } +\str_new:N \l_@@_cfg_str +\str_new:N \l_@@_last_cfg_str +\bool_new:N \l_@@_reset_bool +\msg_new:nnnn { zhnumber } { file-not-found } + { File~`#1'~not~found. } + { + The~requested~file~could~not~be~found~in~the~current~directory,~ + in~the~TeX~search~path~or~in~the~LaTeX~search~path. + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[int,pTF]{\zhnum_if_unicode_engine:} +% 使用 \upTeX{} 的时候,也不必将汉字的首字符设置为活动字符。判断 |^^^^0021| 是否为 +% 单个记号的办法对 \upTeX{} 不适用。 +% \begin{macrocode} +\bool_lazy_any:nTF + { + { \sys_if_engine_xetex_p: } + { \sys_if_engine_luatex_p: } + { \sys_if_engine_uptex_p: } + } + { + \cs_new_eq:NN \zhnum_if_unicode_engine_p: \c_true_bool + \cs_new_eq:NN \zhnum_if_unicode_engine:TF \use_i:nn + } + { + \cs_new_eq:NN \zhnum_if_unicode_engine_p: \c_false_bool + \cs_new_eq:NN \zhnum_if_unicode_engine:TF \use_ii:nn + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[int] +% { +% \zhnum_set_catcode:, +% \zhnum_set_cfg_name:Nn, +% \zhnum_reset_config: +% } +% 设置与恢复配置文件前后的 catcode。\pdfLaTeX{} 需要将汉字的首字节设置为活动字符。 +% \begin{macrocode} +\if_predicate:w \zhnum_if_unicode_engine_p: + \cs_new_eq:NN \zhnum_set_catcode: \prg_do_nothing: + \cs_new_protected:Npn \zhnum_set_cfg_name:Nn #1#2 + { + \str_set:Nx \l_@@_encoding_str {#2} + \str_set_eq:NN #1 \l_@@_encoding_str + } + \cs_new_eq:NN \zhnum_reset_config: \zhnum_parse_config: +\else: + \cs_new_protected_nopar:Npn \zhnum_set_catcode: + { \bool_if:NT \l_@@_active_char_bool { \zhnum_set_active: } } + \cs_new_protected_nopar:Npn \zhnum_set_active: + { + \str_case:onTF { \l_@@_encoding_str } + { + { gbk } { \int_set:Nn \l_@@_byte_min_int { "81 } } + { big5 } { \int_set:Nn \l_@@_byte_min_int { "A1 } } + } + { \int_set:Nn \l_@@_byte_max_int { "FE } } + { + \int_set:Nn \l_@@_byte_min_int { "E0 } + \int_set:Nn \l_@@_byte_max_int { "EF } + } + \int_step_function:nnN + { \l_@@_byte_min_int } + { \l_@@_byte_max_int } \char_set_catcode_active:n + } + \int_new:N \l_@@_byte_min_int + \int_new:N \l_@@_byte_max_int + \cs_new_protected:Npn \zhnum_set_cfg_name:Nn #1#2 + { + \str_set:Nx \l_@@_encoding_str {#2} + \str_set:Nx #1 + { + \l_@@_encoding_str + \bool_if:NT \l_@@_active_char_bool { _active } + } + } + \cs_new_protected_nopar:Npn \zhnum_reset_config: + { \zhnum_load_cfg:o { \l_@@_encoding_str } } + \bool_new:N \l_@@_active_char_bool + \bool_set_true:N \l_@@_active_char_bool +\fi: +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{encoding,style,null,reset} +% 宏包设置选项。 +% \begin{macrocode} +\keys_define:nn { zhnum / options } + { + encoding .choices:nn = + { UTF8 , GBK , Big5 } + { + \str_set:Nx \l_@@_encoding_str + { \str_fold_case:V \l_keys_choice_tl } + \zhnum_load_cfg:o { \l_@@_encoding_str } + } , + encoding .default:n = { GBK } , + encoding / Bg5 .meta:n = { encoding = Big5 } , + encoding / unknown .code:n = + { \msg_error:nnn { zhnumber } { encoding-invalid } {#1} } , + style .multichoice: , + style / Normal .code:n = + { + \bool_set_false:N \l_@@_ancient_bool + \bool_set_true:N \l_@@_normal_bool + } , + style / Financial .code:n = + { + \bool_set_false:N \l_@@_ancient_bool + \bool_set_false:N \l_@@_normal_bool + } , + style / Ancient .code:n = + { + \bool_set_true:N \l_@@_ancient_bool + \bool_set_true:N \l_@@_normal_bool + } , + style / Simplified .code:n = { \bool_set_true:N \l_@@_simp_bool } , + style / Traditional .code:n = { \bool_set_false:N \l_@@_simp_bool } , + style .default:n = { Normal , Simplified } , + null .bool_set:N = \l_@@_null_bool , + time .choice: , + time / Chinese .code:n = { \bool_set_true:N \l_@@_time_bool } , + time / Arabic .code:n = { \bool_set_false:N \l_@@_time_bool } , + time .default:n = { Arabic } , + reset .code:n = { \zhnum_reset_config: } , + activechar .bool_set:N = \l_@@_active_char_bool , + ganzhi-cyclic .choice: , + ganzhi-cyclic / true .code:n = + { \cs_set_eq:NN \zhnum_ganzhi:nnn \zhnum_ganzhi_cyclic:nnn } , + ganzhi-cyclic / false.code:n = + { \cs_set_eq:NN \zhnum_ganzhi:nnn \zhnum_ganzhi_normal:nnn } , + ganzhi-cyclic .default:n = { true } , + arabicsep .tl_set:N = \l_@@_arabic_sep_tl + } +\str_new:N \l_@@_encoding_str +\msg_new:nnnn { zhnumber } { encoding-invalid } + { The~encoding~`#1'~is~invalid. } + { Available~encodings~are~`UTF8',~`GBK'~and~`Big5'. } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\zhnumsetup} +% 在文档中设置 \pkg{zhnumber} 的接口。 +% \begin{macrocode} +\NewDocumentCommand \zhnumsetup { +m } + { + \keys_set:nn { zhnum / options } {#1} + \tex_ignorespaces:D + } +% \end{macrocode} +% \end{macro} +% +% 初始化设置和执行宏包选项。 +% \begin{macrocode} +\keys_set:nn { zhnum / options } { style , time , arabicsep = { ~ } } +\ProcessKeysOptions { zhnum / options } +% \end{macrocode} +% +% 如果没有选定编码,则根据引擎自动设置编码。 +% \begin{macrocode} +\str_if_empty:NT \l_@@_encoding_str + { + \zhnum_if_unicode_engine:TF + { \keys_set:nn { zhnum / options } { encoding = UTF8 } } + { \keys_set:nn { zhnum / options } { encoding = GBK } } + } +% \end{macrocode} +% +% \begin{macrocode} +% +% \end{macrocode} +% +% \section{中文数字配置文件} +% \label{sec:zhnum-map} +% +% \begin{macrocode} +%<*config> +% \end{macrocode} +% +% \begin{macrocode} +%<*!big5> +\zhnum_set_digits_map:nnn { minus } { simp } { 负 } +\zhnum_set_digits_map:nnn { minus } { trad } { 負 } +% +%<*big5> +\zhnum_set_digits_map:nn { minus } { 負 } +% +\zhnum_set_digits_map:nn { 0 } { 零 } +%<*!big5> +\zhnum_set_digits_map:nn { null } { 〇 } +% +%<*big5> +\zhnum_set_digits_map:nn { null } { ○ } +% +\zhnum_set_digits_map:nn { 1 } { 一 } +\zhnum_set_digits_map:nn { 2 } { 二 } +\zhnum_set_digits_map:nn { 3 } { 三 } +\zhnum_set_digits_map:nn { 4 } { 四 } +\zhnum_set_digits_map:nn { 5 } { 五 } +\zhnum_set_digits_map:nn { 6 } { 六 } +\zhnum_set_digits_map:nn { 7 } { 七 } +\zhnum_set_digits_map:nn { 8 } { 八 } +\zhnum_set_digits_map:nn { 9 } { 九 } +\zhnum_set_digits_map:nn { 10 } { 十 } +\zhnum_set_digits_map:nn { 100 } { 百 } +\zhnum_set_digits_map:nn { 1000 } { 千 } +\zhnum_set_digits_map:nn { 20 } { 廿 } +\zhnum_set_digits_map:nn { 30 } { 卅 } +\zhnum_set_digits_map:nn { 40 } { 卌 } +\zhnum_set_digits_map:nn { 200 } { 皕 } +%<*!big5> +\zhnum_set_digits_map:nnn { dot } { simp } { 点 } +\zhnum_set_digits_map:nnn { dot } { trad } { 點 } +% +%<*big5> +\zhnum_set_digits_map:nn { dot } { 點 } +% +\zhnum_set_digits_map:nn { and } { 又 } +\zhnum_set_digits_map:nn { parts } { 分之 } +%<*!big5> +\zhnum_set_digits_map:nnn { s1 } { simp } { 万 } +\zhnum_set_digits_map:nnn { s1 } { trad } { 萬 } +\zhnum_set_digits_map:nnn { s2 } { simp } { 亿 } +\zhnum_set_digits_map:nnn { s2 } { trad } { 億 } +% +%<*big5> +\zhnum_set_digits_map:nn { s1 } { 萬 } +\zhnum_set_digits_map:nn { s2 } { 億 } +% +\zhnum_set_digits_map:nn { s3 } { 兆 } +\zhnum_set_digits_map:nn { s4 } { 京 } +\zhnum_set_digits_map:nn { s5 } { 垓 } +\zhnum_set_digits_map:nn { s6 } { 秭 } +\zhnum_set_digits_map:nn { s7 } { 穰 } +%<*!big5> +\zhnum_set_digits_map:nnn { s8 } { simp } { 沟 } +\zhnum_set_digits_map:nnn { s8 } { trad } { 溝 } +\zhnum_set_digits_map:nnn { s9 } { simp } { 涧 } +\zhnum_set_digits_map:nnn { s9 } { trad } { 澗 } +% +%<*big5> +\zhnum_set_digits_map:nn { s8 } { 溝 } +\zhnum_set_digits_map:nn { s9 } { 澗 } +% +\zhnum_set_digits_map:nn { s10 } { 正 } +%<*!big5> +\zhnum_set_digits_map:nnn { s11 } { simp } { 载 } +\zhnum_set_digits_map:nnn { s11 } { trad } { 載 } +% +%<*big5> +\zhnum_set_digits_map:nn { s11 } { 載 } +% +\zhnum_set_digits_map:nn { year } { 年 } +\zhnum_set_digits_map:nn { month } { 月 } +\zhnum_set_digits_map:nn { day } { 日 } +%<*!big5> +\zhnum_set_digits_map:nnn { hour } { simp } { 时 } +\zhnum_set_digits_map:nnn { hour } { trad } { 時 } +% +%<*big5> +\zhnum_set_digits_map:nn { hour } { 時 } +% +\zhnum_set_digits_map:nn { minute } { 分 } +\zhnum_set_digits_map:nn { weekday } { 星期 } +\zhnum_set_financial_map:nn { null } { 零 } +\zhnum_set_financial_map:nn { 0 } { 零 } +\zhnum_set_financial_map:nn { 1 } { 壹 } +\zhnum_set_financial_map:nn { 2 } { 貳 } +%<*!big5> +\zhnum_set_financial_map:nnn { 3 } { simp } { 叁 } +\zhnum_set_financial_map:nnn { 3 } { trad } { 叄 } +% +%<*big5> +\zhnum_set_financial_map:nn { 3 } { 參 } +% +\zhnum_set_financial_map:nn { 4 } { 肆 } +\zhnum_set_financial_map:nn { 5 } { 伍 } +%<*!big5> +\zhnum_set_financial_map:nnn { 6 } { simp } { 陆 } +\zhnum_set_financial_map:nnn { 6 } { trad } { 陸 } +% +%<*big5> +\zhnum_set_financial_map:nn { 6 } { 陸 } +% +\zhnum_set_financial_map:nn { 7 } { 柒 } +\zhnum_set_financial_map:nn { 8 } { 捌 } +\zhnum_set_financial_map:nn { 9 } { 玖 } +\zhnum_set_financial_map:nn { 10 } { 拾 } +\zhnum_set_financial_map:nn { 100 } { 佰 } +\zhnum_set_financial_map:nn { 1000 } { 仟 } +\zhnum_set_tiangan_map:nn { 1 } { 甲 } +\zhnum_set_tiangan_map:nn { 2 } { 乙 } +\zhnum_set_tiangan_map:nn { 3 } { 丙 } +\zhnum_set_tiangan_map:nn { 4 } { 丁 } +\zhnum_set_tiangan_map:nn { 5 } { 戊 } +\zhnum_set_tiangan_map:nn { 6 } { 己 } +\zhnum_set_tiangan_map:nn { 7 } { 庚 } +\zhnum_set_tiangan_map:nn { 8 } { 辛 } +\zhnum_set_tiangan_map:nn { 9 } { 壬 } +\zhnum_set_tiangan_map:nn { 10 } { 癸 } +\zhnum_set_dizhi_map:nn { 1 } { 子 } +\zhnum_set_dizhi_map:nn { 2 } { 丑 } +\zhnum_set_dizhi_map:nn { 3 } { 寅 } +\zhnum_set_dizhi_map:nn { 4 } { 卯 } +\zhnum_set_dizhi_map:nn { 5 } { 辰 } +\zhnum_set_dizhi_map:nn { 6 } { 巳 } +\zhnum_set_dizhi_map:nn { 7 } { 午 } +\zhnum_set_dizhi_map:nn { 8 } { 未 } +\zhnum_set_dizhi_map:nn { 9 } { 申 } +\zhnum_set_dizhi_map:nn { 10 } { 酉 } +\zhnum_set_dizhi_map:nn { 11 } { 戌 } +\zhnum_set_dizhi_map:nn { 12 } { 亥 } +% \end{macrocode} +% +% \begin{macrocode} +% +% \end{macrocode} +% +% \end{implementation} +% +% \Finale +% +\endinput diff --git a/macros/latex/contrib/zhnumber/zhnumber.ins b/macros/latex/contrib/zhnumber/zhnumber.ins new file mode 100644 index 0000000000..d403166319 --- /dev/null +++ b/macros/latex/contrib/zhnumber/zhnumber.ins @@ -0,0 +1,89 @@ +%% +%% This is file `zhnumber.ins', +%% generated with the docstrip utility. +%% +%% The original source files were: +%% +%% zhnumber.dtx (with options: `install') +%% +%% Copyright (C) 2012, 2014-2019 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. +%% +%% -------------------------------------------------------------------------- +%% + +\input ctxdocstrip % + +\preamble + + Copyright (C) 2012, 2014-2019 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 zhnumber.dtx, + and the derived files zhnumber.pdf, + zhnumber.sty, + zhnumber-utf8.cfg, + zhnumber-gbk.cfg, + zhnumber-big5.cfg, + zhnumber.ins and + README.md. +\endpostamble + +\generate + { + \usedir{tex/latex/zhnumber} + \file{zhnumber.sty} {\from{\jobname.dtx}{package}} + \usedir{tex/latex/zhnumber/config} + \file{zhnumber-utf8.cfg} {\from{\jobname.dtx}{config,utf8}} + \file{zhnumber-big5.cfg} {\from{\jobname.dtx}{config,big5}} + \file{zhnumber-gbk.cfg} {\from{\jobname.dtx}{config,gbk}} + \nopreamble\nopostamble + \usedir{doc/latex/zhnumber} + \file{README.md} {\from{\jobname.dtx}{readme}} + } + +\endbatchfile +%% +%% This package consists of the file zhnumber.dtx, +%% and the derived files zhnumber.pdf, +%% zhnumber.sty, +%% zhnumber-utf8.cfg, +%% zhnumber-gbk.cfg, +%% zhnumber-big5.cfg, +%% zhnumber.ins and +%% README.md. +%% +%% End of file `zhnumber.ins'. diff --git a/macros/latex/contrib/zhnumber/zhnumber.pdf b/macros/latex/contrib/zhnumber/zhnumber.pdf new file mode 100644 index 0000000000..7a3936c5ff Binary files /dev/null and b/macros/latex/contrib/zhnumber/zhnumber.pdf differ -- cgit v1.2.3