% \iffalse meta-comment
% !TEX program  = XeLaTeX
%<*internal>
\iffalse
%</internal>
%<*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{<encoding>}

Set the current encoding. The default encoding is GBK.

    \CJKchartouni{<character>}

Convert a single CJK character to its Unicode.

    \CJKsfdtouni{<plane>}{<slot>}

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 <sobenlee@gmail.com>
    ----------------------------------------------------------------------

    This work may be distributed and/or modified under the
    conditions of the LaTeX Project Public License, either
    version 1.3c of this license or (at your option) any later
    version. This version of this license is in
       http://www.latex-project.org/lppl/lppl-1-3c.txt
    and the latest version of this license is in
       http://www.latex-project.org/lppl.txt
    and version 1.3 or later is part of all distributions of
    LaTeX version 2005/12/01 or later.

    This work has the LPPL maintenance status "maintained".

    The Current Maintainer of this work is Qing Lee.

    This package consists of the file  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).
%</readme>
%<*internal>
\fi
\begingroup
  \def\temp{LaTeX2e}
\expandafter\endgroup\ifx\temp\fmtname\else
\csname fi\endcsname
%</internal>
%<*install>

\input ctxdocstrip %

\preamble

    Copyright (C) 2013-2014, 2016, 2018-2020 by Qing Lee <sobenlee@gmail.com>
--------------------------------------------------------------------------

    This work may be distributed and/or modified under the
    conditions of the LaTeX Project Public License, either
    version 1.3c of this license or (at your option) any later
    version. This version of this license is in
       http://www.latex-project.org/lppl/lppl-1-3c.txt
    and the latest version of this license is in
       http://www.latex-project.org/lppl.txt
    and version 1.3 or later is part of all distributions of
    LaTeX version 2005/12/01 or later.

    This work has the LPPL maintenance status "maintained".

    The Current Maintainer of this work is Qing Lee.

--------------------------------------------------------------------------

\endpreamble
\postamble

    This package consists of the file  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
  {
%</install>
%<*internal>
    \usedir{source/latex/xcjk2uni}
    \file{xCJK2uni.ins}      {\from{\jobname.dtx}{install}}
%</internal>
%<*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
%</install>
%<*internal>
\fi
%</internal>
%<package>\NeedsTeXFormat{LaTeX2e}
%<package>\RequirePackage{expl3}
%<make>\input expl3-generic %
%<+package|make|def>\GetIdInfo$Id: xCJK2uni.dtx daef005 2020-05-01 21:09:45 +0800 Qing Lee <sobenlee@gmail.com> $
%<package|make|def>  {Convert CJK character to Unicode.}
%<*driver>
\def\ctxaux#1#2#3{\def\ctxversion{v#2}}\ctxaux
%</driver>
%<package>\ProvidesExplPackage{\ExplFileName}
%<make>\ExplSyntaxOn
%<make>\cs_if_exist:NF \ProvidesExplFile
%<make>  {
%<make>    \group_begin:
%<make>      \cs_set:Npn \ProvidesExplFile #1#2#3#4
%<make>        { \iow_log:x { File:~#1~#2~v#3~#4 } }
%<make>    \exp_after:wN \group_end:
%<make>  }
%<make>\ProvidesExplFile{xCJK2uni-make.tex}
%<Bg5>\ProvidesExplFile{xCJK2uni-UBig5.def}
%<Bg5+>\ProvidesExplFile{xCJK2uni-UBg5plus.def}
%<GB>\ProvidesExplFile{xCJK2uni-UGB.def}
%<GBK>\ProvidesExplFile{xCJK2uni-UGBK.def}
%<JIS>\ProvidesExplFile{xCJK2uni-UJIS.def}
%<KS>\ProvidesExplFile{xCJK2uni-UKS.def}
%<*driver|package|make|def>
  {\ExplFileDate}{1.0}{\ExplFileDescription}
%</driver|package|make|def>
%<*driver>
\documentclass{ctxdoc}
\begin{document}
  \DocInput{\jobname.dtx}
  \IndexLayout
  \PrintIndex
\end{document}
%</driver>
% \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}
%</package>
%    \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:
        %</#1>
      }
  }
%    \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}
%</make>
%    \end{macrocode}
%
% \end{implementation}
%
% \Finale
%
\endinput
