% \iffalse meta-comment % !TEX program = XeLaTeX %<*internal> \iffalse % %<*readme> xCJK2uni ======== The `xCJK2uni` package provides commands to convert CJK character to Unicode in non-UTF-8 encoding. It provides hooks for `hyperref` to get the correct bookmarks. It also provides some `/ToUnicode` mapping file for CJK subfont. They can be used with `cmap` package and make CJK character searchable and copyable in PDF files generated by pdfLaTeX. Basic Usage ----------- The package provides the following macros: \useCJKencmap{} Set the current encoding. The default encoding is GBK. \CJKchartouni{} Convert a single CJK character to its Unicode. \CJKsfdtouni{}{} Convert the .sfd coordinate to its Unicode. 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) 2013-2014, 2016, 2018-2020 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 xCJK2uni.dtx, and the derived files xCJK2uni.pdf, xCJK2uni.sty, xCJK2uni.ins, xCJK2uni-make.tex, xCJK2uni-sfd.def, xCJK2uni-UBg5plus.def, xCJK2uni-UBig5.def, xCJK2uni-UGB.def, xCJK2uni-UGBK.def, xCJK2uni-UJIS.def, xCJK2uni-UKS.def, c****.cmap, 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) 2013-2014, 2016, 2018-2020 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 xCJK2uni.dtx, and the derived files xCJK2uni.pdf, xCJK2uni.sty, xCJK2uni.ins, xCJK2uni-make.tex, xCJK2uni-sfd.def, xCJK2uni-UBg5plus.def, xCJK2uni-UBig5.def, xCJK2uni-UGB.def, xCJK2uni-UGBK.def, xCJK2uni-UJIS.def, xCJK2uni-UKS.def, c****.cmap, and README.md. \endpostamble \generate { % %<*internal> \usedir{source/latex/xcjk2uni} \file{xCJK2uni.ins} {\from{\jobname.dtx}{install}} % %<*install> \usedir{tex/latex/xcjk2uni} \file{xCJK2uni.sty} {\from{\jobname.dtx}{package}} \file{xCJK2uni-make.tex} {\from{\jobname.dtx}{make}} \nopreamble\nopostamble \usedir{doc/latex/xcjk2uni} \file{README.md} {\from{\jobname.dtx}{readme}} } \let\input\@@input \def\CJKtuend{\ExplSyntaxOff} \input xCJK2uni-make % \let\input\skip@input \generate { \usedir{tex/latex/xcjk2uni} \usepostamble\emptypostamble \file{xCJK2uni-UBig5.def} { \from{\jobname.dtx} {def,Bg5} \from{xCJK2uni-sfd.def} {Bg5} } \file{xCJK2uni-UBg5plus.def} { \from{\jobname.dtx} {def,Bg5+} \from{xCJK2uni-sfd.def} {Bg5+} } \file{xCJK2uni-UGB.def} { \from{\jobname.dtx} {def,GB} \from{xCJK2uni-sfd.def} {GB} } \file{xCJK2uni-UGBK.def} { \from{\jobname.dtx} {def,GBK} \from{xCJK2uni-sfd.def} {GBK} } \file{xCJK2uni-UJIS.def} { \from{\jobname.dtx} {def,JIS} \from{xCJK2uni-sfd.def} {JIS} } \file{xCJK2uni-UKS.def} { \from{\jobname.dtx} {def,KS} \from{xCJK2uni-sfd.def} {KS} } } \endbatchfile % %<*internal> \fi % %\NeedsTeXFormat{LaTeX2e} %\RequirePackage{expl3} %\input expl3-generic % %<+package|make|def>\GetIdInfo$Id: xCJK2uni.dtx daef005 2020-05-01 21:09:45 +0800 Qing Lee $ % {Convert CJK character to Unicode.} %<*driver> \def\ctxaux#1#2#3{\def\ctxversion{v#2}}\ctxaux % %\ProvidesExplPackage{\ExplFileName} %\ExplSyntaxOn %\cs_if_exist:NF \ProvidesExplFile % { % \group_begin: % \cs_set:Npn \ProvidesExplFile #1#2#3#4 % { \iow_log:x { File:~#1~#2~v#3~#4 } } % \exp_after:wN \group_end: % } %\ProvidesExplFile{xCJK2uni-make.tex} %\ProvidesExplFile{xCJK2uni-UBig5.def} %\ProvidesExplFile{xCJK2uni-UBg5plus.def} %\ProvidesExplFile{xCJK2uni-UGB.def} %\ProvidesExplFile{xCJK2uni-UGBK.def} %\ProvidesExplFile{xCJK2uni-UJIS.def} %\ProvidesExplFile{xCJK2uni-UKS.def} %<*driver|package|make|def> {\ExplFileDate}{1.0}{\ExplFileDescription} % %<*driver> \documentclass{ctxdoc} \begin{document} \DocInput{\jobname.dtx} \IndexLayout \PrintIndex \end{document} % % \fi % % \CheckSum{532} % \GetFileId{xCJK2uni.sty} % % \title{\bfseries\pkg{xCJK2uni} 宏包} % \author{李清\\ \path{sobenlee@gmail.com}} % \date{\ExplFileDate\qquad\ctxversion\thanks{\ctexkitrev{\ExplFileVersion}.}} % \maketitle % % \begin{documentation} % % \section{简介} % % \pkg{xCJK2uni} 是一个 \LaTeX 宏包,提供了将 CJK 文字转换成 Unicode 的功能。以 % 宏包形式实现 \texttt{gbk2uni} 程序的功能,使得使用 \package{CJK} 和 % \package{hyperref} 宏包时,可以得到正确的书签。并提供了 \texttt{/ToUnicode} % 映射文件,使得使用 GBK 等编码时,配合 \package{cmap} 宏包,用 \pdfLaTeX\ 编译 % 得到的 pdf 文件支持查找、复制和粘贴。 % % \pkg{xCJK2uni} 只适用于下一节说明的有效编码和以 \pdfTeX\ 作为编译引擎的工作方式。 % % \pkg{xCJK2uni} 依赖 \package{l3kernel}。应该与 \package{CJK} 或 % \href{http://lsec.cc.ac.cn/~zlb/}{\pkg{CCT}} 等配合使用,但 % \pkg{xCJK2uni} 不会自动引入它们。 % % \section{基本命令} % % \begin{function}{\useCJKencmap} % \begin{syntax} % \cs{useCJKencmap} \Arg{Bg5|Bg5+|GB|GBK|JIS|KS} % \end{syntax} % 设置当前的编码环境。以上是 \pkg{xCJK2uni} 支持的文字编码,缺省使用 GBK。 % \pkg{xCJK2uni} 会在 \env{CJK} 环境内自动更新支持的编码。 % \end{function} % % \begin{function}[EXP]{\CJKchartouni} % \begin{syntax} % \cs{CJKchartouni} \Arg{单个CJK文字} % \end{syntax} % 将文字转换成 Unicode。例如 |\CJKchartouni{一}| 将得到 \texttt{\number\string"4E00 }。 % \end{function} % % \begin{function}[EXP]{\CJKsfdtouni} % \begin{syntax} % \cs{CJKsfdtouni} \Arg{plane} \Arg{slot} % \end{syntax} % \meta{plane} 表示由 \file{.sfd} 文件定义的子字体的编号,\meta{slot} 表示在 % 子字体中的位置,这个命令将得到该坐标位置的 Unicode。 % 如果在当前编码下,该坐标位置不合法,将展开为空并报错。 % \end{function} % % \end{documentation} % % \StopEventually{} % % \begin{implementation} % % \section{代码实现} % % \subsection{\pkg{xCJK2uni}} % % \begin{macrocode} %<*package> %<@@=CJKtu> % \end{macrocode} % % \begin{macrocode} \msg_new:nnn { xCJK2uni } { 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 } { 2020/03/06 } { } { \msg_error:nn { xCJK2uni } { l3-too-old } } % \end{macrocode} % % \begin{macrocode} \sys_if_engine_pdftex:F { \msg_new:nnn { xCJK2uni } { pdflatex } { The~xCJK2uni~package~is~only~supported~in~pdfTeX. } \msg_critical:nn { xCJK2uni } { pdflatex } } % \end{macrocode} % % \begin{macrocode} \tl_new:N \l_@@_sfd_tl \prop_new:N \c_@@_sfd_prop \seq_new:N \c_@@_encoding_seq \int_new:N \l_@@_i_min_int \int_new:N \l_@@_i_max_int \int_new:N \l_@@_ii_min_int \int_new:N \l_@@_ii_max_int \int_new:N \l_@@_gap_begin_int \int_new:N \l_@@_gap_end_int \int_new:N \l_@@_plane_int \int_set:Nn \l_@@_i_max_int { "FE } \int_set:Nn \l_@@_ii_max_int { "FE } % \end{macrocode} % % \begin{macro}{\@@_set_enc:nnnnnn} % \begin{macrocode} \cs_new_protected:Npn \@@_set_enc:nnnnnn #1#2#3#4#5#6 { \seq_gput_right:Nn \c_@@_encoding_seq {#1} \prop_gput:Nnn \c_@@_sfd_prop {#1} {#2} \int_const:cn { c_@@_ #1 _i_min_int } {#3} \int_const:cn { c_@@_ #1 _ii_min_int } {#4} \tl_if_empty:nTF {#5} { \int_const:cn { c_@@_ #1 _gap_begin_int } { \l_@@_ii_max_int + 1 } \int_const:cn { c_@@_ #1 _gap_end_int } { \use:c { c_@@_ #1 _gap_begin_int } } \int_const:cn { c_@@_ #1 _plane_int } { \l_@@_ii_max_int - (#4) + 1 } } { \int_const:cn { c_@@_ #1 _gap_begin_int } { #5 + 1 } \int_const:cn { c_@@_ #1 _gap_end_int } {#6} \int_const:cn { c_@@_ #1 _plane_int } { (#5) - (#4) + \l_@@_ii_max_int - (#6) + 2 } } \cs_if_exist_use:NTF \CJKaddEncHook { {#1} { \@@_enc_map:nn {#1} {#2} } } { \AtBeginDocument { \cs_if_exist_use:NT \CJKaddEncHook { {#1} { \@@_enc_map:nn {#1} {#2} } } } } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_enc_map:nn} % \begin{macrocode} \cs_new_protected:Npn \@@_enc_map:nn #1#2 { \int_set_eq:Nc \l_@@_i_min_int { c_@@_ #1 _i_min_int } \int_set_eq:Nc \l_@@_ii_min_int { c_@@_ #1 _ii_min_int } \int_set_eq:Nc \l_@@_gap_begin_int { c_@@_ #1 _gap_begin_int } \int_set_eq:Nc \l_@@_gap_end_int { c_@@_ #1 _gap_end_int } \int_set_eq:Nc \l_@@_plane_int { c_@@_ #1 _plane_int } \cs_if_exist:cF { CJKtu_ #1 _index_map:n } { \@@_input_sfd_map:n {#2} } \cs_set_eq:Nc \@@_index_map:n { CJKtu_ #1 _index_map:n } } \cs_new_protected:Npn \@@_input_sfd_map:n #1 { \group_begin: \ExplSyntaxOn \file_input:n { xCJK2uni-#1.def } \group_end: } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\CJKtu_index_map:n} % \begin{macrocode} \cs_new:Npn \CJKtu_index_map:n #1 { \CJKtu_unicode:n { \@@_index_map:n {#1} } } \cs_new_eq:NN \CJKtu_unicode:n \use:n \cs_new_eq:NN \@@_index_map:n \use_none:n % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\CJKtu_index_map:nn} % \begin{macrocode} \cs_new_protected:Npn \CJKtu_index_map:nn #1 { \exp_args:Ncc \@@_index_map_aux:NNn { CJKtu_ #1 _index_map:n } { c_@@_ #1 _intarray } } \cs_new_protected:Npn \@@_index_map_aux:NNn #1#2 { \cs_new:Npn #1 ##1 { \intarray_item:Nn #2 { ##1 + 1 } } \intarray_const_from_clist:Nn #2 } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\CJKtu_sfd_map:nn} % \begin{macrocode} \cs_new:Npn \CJKtu_sfd_map:nn #1#2 { \CJKtu_index_map:n { ( #1 - 1 ) * 256 + (#2) } } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\CJKtu_use_enc_map:n} % \begin{macrocode} \cs_new_protected:Npn \CJKtu_use_enc_map:n #1 { \prop_get:NnNTF \c_@@_sfd_prop {#1} \l_@@_sfd_tl { \@@_enc_map:nn {#1} { \l_@@_sfd_tl } } { \msg_error:nnx { xCJK2uni } { invalid-encoding } {#1} } } \msg_new:nnn { xCJK2uni } { invalid-encoding } { The~enconding~`#1'~is~invalid.\\ Only~\seq_use:Nnnn \c_@@_encoding_seq { ~and~ } { ,~ } { ,~and~ } ~ are~supported. } \cs_generate_variant:Nn \CJKtu_use_enc_map:n { x } % \end{macrocode} % \end{macro} % % \begin{macrocode} \@@_set_enc:nnnnnn { GB } { UGB } { "A1 } { "A1 } { } { } \@@_set_enc:nnnnnn { JIS } { UJIS } { "A1 } { "A1 } { } { } \@@_set_enc:nnnnnn { KS } { UKS } { "A1 } { "A1 } { } { } \@@_set_enc:nnnnnn { Bg5 } { UBig5 } { "A1 } { "40 } { "7E } { "A1 } \@@_set_enc:nnnnnn { Bg5+ } { UBg5plus } { "81 } { "40 } { "7E } { "80 } \@@_set_enc:nnnnnn { GBK } { UGBK } { "81 } { "40 } { "7E } { "80 } % \end{macrocode} % % \begin{macro}[int]{\CJKtu_char_to_unicode:n} % \begin{macrocode} \group_begin: \char_set_catcode_active:n { "7F } \cs_new:Npn \CJKtu_char_to_unicode:n #1 { \int_compare:nNnTF { \tl_count:n {#1} } = 2 { \CJKtu_byte:NN #1 } { \tl_if_head_eq_meaning:nNTF {#1} ^^7f { \@@_byte:wNwnw #1 } { \@@_encoding_error: } } } \cs_new:Npn \@@_byte:wNwnw ^^7f #1 ^^7f #2 ^^7f { \CJKtu_byte_map:nn { `#1 } {#2} } \cs_new:Npn \@@_active_byte:Nwnw #1 ^^7f #2 ^^7f { \CJKtu_byte_map:nn { `#1 } {#2} } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\CJKtu_bookmarks_hook:} % \begin{macrocode} \cs_new_protected:Npn \CJKtu_bookmarks_hook: { \cs_set_eq:NN ^^7f \@@_active_byte:Nwnw \cs_set_eq:NN \CJK@XX \CJKtu_byte:NN \cs_set_eq:NN \CJKchar \@@_byte:wnn \cs_set_eq:NN \CCTchar \CJKtu_byte:nn \cs_set_eq:NN \@CCTSetChar \@@_CCT_byte:NNN \cs_set_eq:NN \CJKtu_unicode:n \@@_UTF_xvi_be_octal:n } \group_end: % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\CJKtu_byte:NN} % \begin{macro}{\@@_CCT_byte:NNN} % \begin{macrocode} \cs_new:Npn \CJKtu_byte:NN #1#2 { \CJKtu_byte:nn { `#1 } { `#2 } } \cs_new:Npn \@@_CCT_byte:NNN #1#2#3 { \CJKtu_byte:nn { `#1 } { `#3 } } % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro}{\@@_byte:wnn} % \begin{macrocode} \cs_new:Npn \@@_byte:wnn #1# { \CJKtu_byte:nn } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\CJKtu_byte:nn} % \begin{macrocode} \cs_new:Npn \CJKtu_byte:nn #1#2 { \int_compare:nTF { \l_@@_i_min_int <= #1 <= \l_@@_i_max_int } { \int_compare:nTF { \l_@@_ii_min_int <= #2 < \l_@@_gap_begin_int } { \CJKtu_byte_map:nn {#1} {#2} } { \int_compare:nTF { \l_@@_gap_end_int <= #2 <= \l_@@_ii_max_int } { \CJKtu_byte_map:nn {#1} {#2} } { \@@_encoding_error: } } } { \@@_encoding_error: } } \cs_new:Npn \@@_encoding_error: { \msg_expandable_error:nn { xCJK2uni } { encoding-error } } \msg_new:nnn { xCJK2uni } { encoding-error } { Wrong~encoding~scheme. } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\CJKtu_byte_map:nn} % \begin{macrocode} \cs_new:Npn \CJKtu_byte_map:nn #1#2 { \exp_args:Nf \CJKtu_index_map:n { \int_eval:n { ( #1 - \l_@@_i_min_int ) * \l_@@_plane_int + (#2) - \l_@@_ii_min_int \int_compare:nNnF {#2} < \l_@@_gap_begin_int { + \l_@@_gap_begin_int - \l_@@_gap_end_int } } } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_UTF_xvi_be_octal:n} % \begin{macrocode} \cs_new:Npn \@@_UTF_xvi_be_octal:n #1 { \exp_args:Nf \@@_UTF_xvi_be_octal_aux:n { \int_eval:n {#1} } } \cs_new:Npn \@@_UTF_xvi_be_octal_aux:n #1 { \@@_UTF_xvi_be_octal:nn { \int_div_truncate:nn {#1} { 256 } } { \int_mod:nn {#1} { 256 } } } \cs_new:Npn \@@_UTF_xvi_be_octal:nn #1#2 { \HyPsd@DecimalToOctalFirst {#1} \HyPsd@DecimalToOctalSecond {#2} } % \end{macrocode} % \end{macro} % % \begin{macrocode} \cs_if_exist_use:NTF \hypersetup { { unicode , CJKbookmarks = false } } { \PassOptionsToPackage { unicode , CJKbookmarks = false } { hyperref } } \msg_new:nnn { xCJK2uni } { UTF-8-encoding } { It~is~not~necessary~to~load~xCJK2uni~in~UTF-8~encoding. } \tl_if_exist:NF \pdfstringdefPreHook { \tl_new:N \pdfstringdefPreHook } \@ifpackageloaded { CJKutf8 } { \msg_warning:nn { xCJK2uni } { UTF-8-encoding } } { \cs_new_eq:NN \CJKtu@bookmarks@hook \CJKtu_bookmarks_hook: \tl_gput_right:Nn \pdfstringdefPreHook { \CJKtu@bookmarks@hook } \AtBeginDocument { \@ifpackageloaded { CJKutf8 } { \cs_gset_eq:NN \CJKtu@bookmarks@hook \scan_stop: \msg_warning:nn { xCJK2uni } { UTF-8-encoding } } { \cs_if_exist_use:NT \hypersetup { { CJKbookmarks = false } } } } } % \end{macrocode} % % \begin{macro}{\useCJKencmap,\CJKchartouni,\CJKsfdtouni} % \begin{macrocode} \cs_new_eq:NN \useCJKencmap \CJKtu_use_enc_map:x \cs_new_eq:NN \CJKchartouni \CJKtu_char_to_unicode:n \cs_new_eq:NN \CJKsfdtouni \CJKtu_sfd_map:nn % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_initial:N} % \begin{macrocode} \cs_new_protected:Npn \@@_initial:N #1 { \tl_if_exist:NTF #1 { \prop_get:NxNTF \c_@@_sfd_prop {#1} \l_@@_sfd_tl { \@@_enc_map:nn {#1} { \l_@@_sfd_tl } } { \CJKtu_use_enc_map:n { GBK } } } { \CJKtu_use_enc_map:n { GBK } } } \prg_generate_conditional_variant:Nnn \prop_get:NnN { Nx } { TF } % \end{macrocode} % \end{macro} % % \begin{macrocode} \group_begin: \exp_args:NNc \group_end: \@@_initial:N { CJK @ @ @ enc } % \end{macrocode} % % \begin{macrocode} % % \end{macrocode} % % \subsection{\pkg{xCJK2uni-make}} % % \begin{macrocode} %<*make> % \end{macrocode} % % \begin{macrocode} \msg_new:nnn { xCJK2uni } { file-not-found } { SFD file~`#2'~for~encoding~`#1'~not~found.\\ xCJK2uni~will~not~work! } % \end{macrocode} % % \begin{macrocode} \ior_new:N \g_@@_sfd_ior \str_new:N \g_@@_path_str \sys_if_engine_luatex:TF { \str_gset:Nx \g_@@_path_str { \lua_now:e { kpse.set_program_name("luatex") ~ local ~ sfd = kpse.find_file("UGBK.sfd", "subfont~definition~files") ~ if ~ sfd ~ then ~ tex.write(sfd) ~ end } } } { \sys_get_shell:nnNTF { kpsewhich ~ UGBK.sfd } { } \l_tmpa_str { \str_gset_eq:NN \g_@@_path_str \l_tmpa_str } { \msg_fatal:nnnn { xCJK2uni } { file-not-found } { GBK } { UGBK.sfd } } } % \end{macrocode} % % \begin{macrocode} \tl_if_blank:oTF { \g_@@_path_str } { \msg_fatal:nnnn { xCJK2uni } { file-not-found } { GBK } { UGBK.sfd } } { \exp_args:No \file_parse_full_name:nNNN { \g_@@_path_str } \l_tmpa_str \l_tmpb_str \l_tmpb_str \str_gset_eq:NN \g_@@_path_str \l_tmpa_str } % \end{macrocode} % % \begin{macrocode} \str_const:Nx \c_@@_indent_str { \c_catcode_other_space_tl \c_catcode_other_space_tl } \iow_new:N \g_@@_sfd_map_iow \iow_new:N \g_@@_sfd_cmap_iow \seq_new:N \l_@@_sfd_plane_seq \seq_new:N \l_@@_sfd_line_seq \tl_new:N \l_@@_sfd_plane_tl \tl_new:N \l_@@_cmap_block_tl \int_new:N \l_@@_sfd_index_int % \end{macrocode} % % \begin{variable}{\c_@@_sfd_map_prop} % \begin{macrocode} \prop_const_from_keyval:Nn \c_@@_sfd_map_prop { GB = { 10 } { UGB } , JIS = { 40 } { UJIS } , KS = { 60 } { UKS } , Bg5 = { 00 } { UBig5 } , Bg5+ = { 09 } { UBg5plus } , GBK = { 19 } { UGBK } } % \end{macrocode} % \end{variable} % % \begin{macro}{\@@_write_file:nnn} % \begin{macrocode} \cs_new_protected:Npn \@@_write_file:nnn #1#2#3 { \group_begin: \seq_put_right:No \l_file_search_path_seq { \g_@@_path_str } \ior_open:NnTF \g_@@_sfd_ior { #3.sfd } { \group_end: \seq_clear:N \l_@@_sfd_plane_seq \@@_write_sfd_map_header:n {#1} \ior_str_map_inline:Nn \g_@@_sfd_ior { \str_if_eq:nnT { ##1 } { 00 ~ 0x0000_0x00FF } { \ior_map_break: } } \ior_str_map_inline:Nn \g_@@_sfd_ior { \tl_if_blank:nT { ##1 } { \ior_map_break: } \@@_read_sfd_line:nn { ##1 } {#2} } \@@_write_sfd_map_trailer:n {#1} \@@_write_cmap_file:n {#2} \iow_close:N \g_@@_sfd_cmap_iow \ior_close:N \g_@@_sfd_ior \seq_clear:N \l_@@_sfd_plane_seq \seq_clear:N \l_@@_sfd_line_seq } { \group_end: \msg_critical:nnxx { xCJK2uni } { file-not-found } {#1} { #3.sfd } } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_read_sfd_line:n,\@@_read_sfd_line:nn} % \begin{macrocode} \cs_new_protected:Npx \@@_read_sfd_line:nn #1 { \exp_not:N \@@_read_sfd_line:nwn #1 \c_backslash_str \exp_not:N \q_nil \exp_not:N \q_stop } \use:e { \cs_new_protected:Npn \exp_not:N \@@_read_sfd_line:nwn #1 0 \token_to_str:N x #2 \c_backslash_str #3 \exp_not:N \q_stop { \exp_not:N \@@_read_sfd_line:nnnn {#1} { 0 \token_to_str:N x } {#2} } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_read_sfd_line:nnnnn} % \begin{macrocode} \cs_new_protected:Npn \@@_read_sfd_line:nnnn #1#2#3#4 { \tl_if_blank:nF {#1} { \seq_if_empty:NF \l_@@_sfd_plane_seq { \@@_write_cmap_file:n {#4} } \tl_set:Nx \l_@@_sfd_plane_tl { \tl_trim_spaces:n {#1} } \@@_write_plane_map:n { \l_@@_sfd_plane_tl } } \seq_set_split:Nnn \l_@@_sfd_line_seq {#2} {#3} \seq_concat:NNN \l_@@_sfd_plane_seq \l_@@_sfd_plane_seq \l_@@_sfd_line_seq \iow_now:Nx \g_@@_sfd_map_iow { \c_@@_indent_str \c_@@_indent_str " \seq_use:Nn \l_@@_sfd_line_seq { ~ , ~ " } ~ , } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_write_cmap_file:n} % \begin{macrocode} \cs_new_protected:Npn \@@_write_cmap_file:n #1 { \tl_clear:N \l_@@_cmap_block_tl \int_zero:N \l_@@_sfd_index_int \iow_open:Nn \g_@@_sfd_cmap_iow { c #1 \l_@@_sfd_plane_tl .cmap } \@@_write_cmap_header:nn { C #1 } { \l_@@_sfd_plane_tl } \iow_now:Nx \g_@@_sfd_cmap_iow { \iow_newline: 1~begincodespacerange \iow_newline: \c_@@_indent_str < 00 > ~ < \int_to_Hex:n { \seq_count:N \l_@@_sfd_plane_seq - 1 } > \iow_newline: endcodespacerange } \seq_map_function:NN \l_@@_sfd_plane_seq \@@_write_cmap_body:n \tl_if_empty:NF \l_@@_cmap_block_tl { \iow_now:Nx \g_@@_sfd_cmap_iow { \iow_newline: \int_mod:nn { \l_@@_sfd_index_int } { 100 } ~ beginbfchar \iow_newline: \l_@@_cmap_block_tl endbfchar } } \@@_write_cmap_trailer: \seq_clear:N \l_@@_sfd_plane_seq } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_write_cmap_body:n} % \begin{macrocode} \cs_new_protected:Npn \@@_write_cmap_body:n #1 { \int_case:nnTF { \l_@@_sfd_index_int } { { 99 } { } { 199 } { } } { \iow_now:Nx \g_@@_sfd_cmap_iow { \iow_newline: 100 ~ beginbfchar \iow_newline: \l_@@_cmap_block_tl < \int_to_Hex:n { \l_@@_sfd_index_int } > ~ <#1> \iow_newline: endbfchar } \tl_clear:N \l_@@_cmap_block_tl } { \tl_put_right:Nx \l_@@_cmap_block_tl { < \int_compare:nNnF \l_@@_sfd_index_int > { 15 } { 0 } \int_to_Hex:n { \l_@@_sfd_index_int } > ~ <#1> \iow_newline: } } \int_incr:N \l_@@_sfd_index_int } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_write_sfd_map_header:n} % \begin{macrocode} \group_begin: \char_set_catcode_other:N \% \cs_new_protected:Npn \@@_write_sfd_map_header:n #1 { \iow_now:Nx \g_@@_sfd_map_iow { %<*#1> \iow_newline: \exp_not:N \CJKtu_index_map:nn { ~ #1 ~ } \iow_newline: \c_@@_indent_str \c_left_brace_str } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_write_sfd_map_trailer:n} % \begin{macrocode} \cs_new_protected:Npn \@@_write_sfd_map_trailer:n #1 { \iow_now:Nx \g_@@_sfd_map_iow { \c_@@_indent_str \c_right_brace_str \iow_newline: % } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_write_plane_map:n} % \begin{macrocode} \cs_new_protected:Npn \@@_write_plane_map:n #1 { \iow_now:Nx \g_@@_sfd_map_iow { %% ~ <#1> } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_write_cmap_header:nn} % \begin{macrocode} \cs_new_protected:Npn \@@_write_cmap_header:nn #1#2 { \iow_now:Nx \g_@@_sfd_cmap_iow { %!PS-Adobe-3.0~Resource-CMap \iow_newline: %%DocumentNeededResources:~ProcSet~(CIDInit) \iow_newline: %%IncludeResource:~ProcSet~(CIDInit) \iow_newline: %%BeginResource:~CMap~(TeX-#1-#2-0) \iow_newline: %%Title:~(TeX-#1-#2-0~TeX~#1-#2~0) \iow_newline: %%Version:~1.000 \iow_newline: %%EndComments \iow_newline: \iow_newline: /CIDInit~/ProcSet~findresource~begin \iow_newline: \iow_newline: 12~dict~begin \iow_newline: \iow_newline: begincmap \iow_newline: \iow_newline: /CIDSystemInfo~3~dict~dup~begin \iow_newline: \c_@@_indent_str /Registry~(TeX)~def \iow_newline: \c_@@_indent_str /Ordering~(#1-#2)~def \iow_newline: \c_@@_indent_str /Supplement~0~def \iow_newline: end~def \iow_newline: \iow_newline: /CMapName~/TeX-#1-#2-0~def \iow_newline: /CMapVersion~1.000~def \iow_newline: /CMapType~2~def \iow_newline: \iow_newline: /WMode~0~def } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_write_cmap_trailer:} % \begin{macrocode} \cs_new_protected:Npx \@@_write_cmap_trailer: { \iow_now:Nn \g_@@_sfd_cmap_iow { \iow_newline: endcmap \iow_newline: CMapName~currentdict~/CMap~defineresource~pop \iow_newline: end \iow_newline: end \iow_newline: \iow_newline: %%EndResource \iow_newline: %%EOF } } \group_end: % \end{macrocode} % \end{macro} % % \begin{macrocode} \iow_open:Nn \g_@@_sfd_map_iow { xCJK2uni-sfd.def } \prop_map_inline:Nn \c_@@_sfd_map_prop { \@@_write_file:nnn {#1} #2 } \iow_close:N \g_@@_sfd_map_iow % \end{macrocode} % % \begin{macrocode} \cs_if_exist_use:NF \CJKtuend { \tex_end:D } % \end{macrocode} % % \begin{macrocode} % % \end{macrocode} % % \end{implementation} % % \Finale % \endinput