% \iffalse meta-comment
% !TEX program  = XeLaTeX
%<*internal>
\iffalse
%</internal>
%<*readme>
Introduction
------------
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.

It may be distributed and/or modified under the conditions of the
LaTeX Project Public License (LPPL), either version 1.3c of this license or
(at your option) any later version. 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 work 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 (this file).

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.
    It requires two steps of expansion.

  \CJKsfdtouni{<plane>}{<slot>}
    Convert the .sfd coordinate to its Unicode.
    It requires two steps of expansion.

You can read the package manual (in Chinese) for more detailed explanations.

Author
------
Qing Lee
Email: sobenlee@gmail.com

If you are interested in the process of development you may observe

    http://code.google.com/p/ctex-kit/

Installation
------------
The package is supplied in dtx format and as a pre-extracted zip file,
xCJK2uni.tds.zip. The later is most convenient for most users: simply
unzip this in your local texmf directory and run texhash to update the
database of file locations. If you want to unpack the dtx yourself,
running "luatex xCJK2uni.dtx" will extract the package whereas
"xelatex xCJK2uni.dtx" will typeset the documentation.

The package requires LaTeX3 support as provided in the l3kernel.
It is available on CTAN as ready-to-install zip files.
Suitable versions are available in the latest version of MiKTeX and TeX Live
(updating the relevant packages online may be necessary).

To compile the documentation without error, you will need the xeCJK package
and some specific Chinese Simplified fonts.
%</readme>
%<*internal>
\fi
\begingroup
  \edef\tempa{\fmtname}
  \edef\tempb{plain}
\expandafter\endgroup
\ifx\tempa\tempb
\csname fi\endcsname
%</internal>
%<*install>

\input l3docstrip.tex
\keepsilent
\askforoverwritefalse
\preamble

   Copyright (C) 2013-2014 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.3
   of this license or (at your option) any later version.
   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.
\endpostamble

\declarepostamble\emptypostamble
\endpostamble

\generate
  {
    \usedir{source/latex/xcjk2uni}
    \file{xCJK2uni.ins}      {\from{\jobname.dtx}{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.txt}        {\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>
%
%<*driver|package|make|def>
%<*!(make|def)>
\NeedsTeXFormat{LaTeX2e}
\RequirePackage{expl3}
%</!(make|def)>
%<make>\input expl3-generic %
\GetIdInfo$Id: xCJK2uni.dtx 691 2014-06-20 09:20:07Z sobenlee $
  {Convert CJK character to Unicode.}
%<*driver>
\ProvidesExplFile{\ExplFileName.\ExplFileExtension}
%</driver>
%<package>\ProvidesExplPackage{\ExplFileName}
%<make>\ExplSyntaxOn
%<make>\cs_if_exist:NF \ProvidesExplFile
%<make>  {
%<make>    \group_begin:
%<make>      \cs_set_nopar: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}
  {\ExplFileDate}{0.4}{\ExplFileDescription}
%<*driver>
\ExplSyntaxOff
%</driver>
%</driver|package|make|def>
%
%<*driver>
\documentclass[full,a4paper]{l3doc}
\usepackage{xeCJK}
\usepackage{indentfirst}
\usepackage{geometry}
\hypersetup{pdfstartview=FitH}
\geometry{includemp,hmargin={0mm,15mm},vmargin=15mm,footskip=7mm}
\linespread{1.1}
\setmainfont{TeX Gyre Pagella}
\setsansfont{CMU Sans Serif}
\setmonofont[
  UprightFont=* Light, BoldFont=* Bold,
  SlantedFont=* Light Oblique]{CMU Typewriter Text}
\setCJKmainfont[BoldFont=Adobe Heiti Std,ItalicFont=Adobe Kaiti Std]{Adobe Song Std}
\setCJKmonofont{Adobe Kaiti Std}
\xeCJKsetup{PunctStyle=kaiming}
\def\MacroFont{\linespread{1}\small\normalfont\ttfamily}
\ExplSyntaxOn
\DeclareDocumentCommand \package { o m }
  {
    \href
      {
        http://mirrors.ctan.org/help/Catalogue/entries/
        \IfNoValueTF {#1} { \tl_expandable_lowercase:n {#2} } {#1} .html
      }
      { \pkg {#2} }
  }
\ExplSyntaxOff
\def\TeX{\hologo{TeX}}
\def\LaTeX{\hologo{LaTeX}}
\def\pdfTeX{\hologo{pdfTeX}}
\def\pdfLaTeX{\hologo{pdfLaTeX}}
\def\orvar{\textup{\textbar}}
\def\indexname{代码索引}
\IndexPrologue{%
  \section*{\indexname}
  \markboth{\indexname}{\indexname}
  斜体的数字表示对应项说明所在的页码，下划线的数字表示定义所在的代码行号，而直立体的
  数字表示对应项使用时所在的行号。}
\begin{document}
  \DocInput{\jobname.dtx}
  \newgeometry{margin=15mm,footskip=7mm}
  \PrintIndex
\end{document}
%</driver>
% \fi
%
% \CheckSum{615}
% \GetFileInfo{\jobname.dtx}
%
% \title{\bfseries\pkg{xCJK2uni} 宏包}
% \author{李清\\ \path{sobenlee@gmail.com}}
% \date{\filedate\qquad\fileversion}
% \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\orvar{}Bg5+\orvar{}GB\orvar{}GBK\orvar{}JIS\orvar{}KS}
%   \end{syntax}
%   设置当前的编码环境。以上是 \pkg{xCJK2uni} 支持的文字编码，缺省使用 GBK。
%   \pkg{xCJK2uni} 会在 \env{CJK} 环境内自动更新支持的编码。
% \end{function}
%
% \begin{function}[EXP]{\CJKchartouni}
%   \begin{syntax}
%     \cs{CJKchartouni} \Arg{单个CJK文字}
%   \end{syntax}
%   将文字转换成 $16$ 进制形式的 Unicode。例如 |\CJKchartouni{一}| 将得到 |4E00|。
%   将它展开两次就可以得到结果。
% \end{function}
%
% \begin{function}[EXP]{\CJKsfdtouni}
%   \begin{syntax}
%     \cs{CJKsfdtouni} \Arg{plane} \Arg{slot}
%   \end{syntax}
%   \meta{plane} 表示由 \texttt{.sfd} 文件定义的子字体的编号，\meta{slot} 表示在
%   子字体中的位置，这个命令将得到该坐标位置的 Unicode。将它展开两次就可以得到结果。
%   如果在当前编码下，该坐标位置不合法，将展开为空。
% \end{function}
%
% \end{documentation}
%
% \StopEventually{}
%
% \begin{implementation}
%
% \section{代码实现}
%
% \subsection{\pkg{xCJK2uni}}
%
%    \begin{macrocode}
%<*package>
%<@@=CJKtu>
%    \end{macrocode}
%
%    \begin{macrocode}
\pdftex_if_engine: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}[internal]{\@@_set_enc:nnnnnn}
%    \begin{macrocode}
\cs_new_protected_nopar:Npn \@@_set_enc:nnnnnn #1#2#3#4#5#6
  {
    \seq_put_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 + \c_one }
        \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) + \c_one }
      }
      {
        \int_const:cn { c_@@_ #1 _gap_begin_int } { #5 + \c_one }
        \int_const:cn { c_@@_ #1 _gap_end_int } {#6}
        \int_const:cn { c_@@_ #1 _plane_int }
          { (#5) - (#4) + \l_@@_ii_max_int - (#6) + \c_two }
      }
    \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}[internal]{\@@_enc_map:nn}
%    \begin{macrocode}
\cs_new_protected_nopar: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 _sfd_map:nn }
      { \group_begin: \file_input:n { xCJK2uni-#2.def } \group_end: }
    \cs_set_eq:Nc \CJKtu_sfd_map:nn { CJKtu_ #1 _sfd_map:nn }
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[internal]{\@@_use_enc_map:n}
%    \begin{macrocode}
\cs_new_protected_nopar:Npn \@@_use_enc_map:n #1
  {
    \prop_get:NxNTF \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 \prop_get:NnNTF { Nx }
%    \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}[internal]{\@@_sfd_to_unicode:nn}
%    \begin{macrocode}
\cs_new_nopar:Npn \@@_sfd_to_unicode:nn #1#2
  {
    \tex_romannumeral:D -`0 \exp_last_unbraced:Nf
    \@@_get_unicode:w \CJKtu_sfd_map:nn {#1} {#2} \s__stop
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[internal]{\@@_get_unicode:w}
%    \begin{macrocode}
\cs_new_nopar:Npn \@@_get_unicode:w #1 \s__stop
  { \tl_if_empty:nF {#1} { \@@_get_unicode_aux:w #1 \q_stop } }
\cs_new_nopar:Npn \@@_get_unicode_aux:w #1 \or: #2 \q_stop
  { \or: #2 \exp_stop_f: #1 }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[internal]{\@@_char_to_unicode:n}
%    \begin{macrocode}
\group_begin:
\char_set_catcode_active:n { "7F }
\cs_new_nopar:Npn \@@_char_to_unicode:n #1
  {
    \tex_romannumeral:D -`0
    \int_compare:nNnTF { \tl_count:n {#1} } = \c_two
      { \CJKtu_byte:NN #1 }
      {
        \tl_if_head_eq_meaning:nNTF {#1} ^^7f
          { \@@_byte:wNwnw #1 }
          { \@@_encoding_error: }
      }
  }
\cs_new_nopar:Npn \@@_byte:wNwnw ^^7f #1 ^^7f #2 ^^7f
  { \CJKtu_byte_map:nn { `#1 } {#2} }
\cs_new_nopar:Npn \@@_byte:Nwnw #1 ^^7f #2 ^^7f
  { \CJKtu_byte_map:nn { `#1 } {#2} }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[internal]{\CJKtu_bookmarks_hook:}
%    \begin{macrocode}
\cs_new_protected_nopar:Npn \CJKtu_bookmarks_hook:
  {
    \cs_set_eq:NN ^^7f \@@_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 \@@_get_unicode:n \@@_UTF_xvi_be:n
  }
\group_end:
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[internal]{\CJKtu_byte:NN,\@@_CCT_byte:NNN}
%    \begin{macrocode}
\cs_new_nopar:Npn \CJKtu_byte:NN #1#2
  { \CJKtu_byte:nn { `#1 } { `#2 } }
\cs_new_nopar:Npn \@@_CCT_byte:NNN #1#2#3
  { \CJKtu_byte:nn { `#1 } { `#3 } }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[internal]{\@@_byte:wnn}
%    \begin{macrocode}
\cs_new_nopar:Npn \@@_byte:wnn #1# { \CJKtu_byte:nn }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[internal]{\CJKtu_byte:nn}
%    \begin{macrocode}
\cs_new_nopar: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_nopar:Npn \@@_encoding_error:
  { \exp_stop_f: \__msg_expandable_error:n { Wrong~encoding~scheme. } }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[internal]{\CJKtu_byte_map:nn}
%    \begin{macrocode}
\cs_new_nopar:Npn \CJKtu_byte_map:nn #1#2
  {
    \exp_args:Nf \@@_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}[internal]{\@@_index_map:n}
%    \begin{macrocode}
\cs_new_nopar:Npn \@@_index_map:n #1
  {
    \@@_get_unicode:n
      {
        \CJKtu_sfd_map:nn
          { \int_div_truncate:nn {#1} { \c_two_hundred_fifty_six } + \c_one }
          { \int_mod:nn {#1} { \c_two_hundred_fifty_six } }
      }
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[internal]{\@@_get_unicode:n}
%    \begin{macrocode}
\cs_new_nopar:Npn \@@_get_unicode:n #1
  { \exp_last_unbraced:Nf \@@_get_unicode:w #1 \s__stop }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[internal]{\@@_UTF_xvi_be:n}
%    \begin{macrocode}
\cs_new_nopar:Npn \@@_UTF_xvi_be:n #1
  { \exp_args:Nf \@@_UTF_xvi_aux:n { \int_eval:n { "#1 } } }
\cs_new_nopar:Npn \@@_UTF_xvi_aux:n #1
  {
    \HyPsd@DecimalToOctalFirst
      { \int_div_truncate:nn {#1} { \c_two_hundred_fifty_six } }
    \HyPsd@DecimalToOctalSecond
      { \int_mod:nn {#1} { \c_two_hundred_fifty_six } }
  }
%    \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 \@@_use_enc_map:n
\cs_new_eq:NN \CJKchartouni \@@_char_to_unicode:n
\cs_new_eq:NN \CJKsfdtouni  \@@_sfd_to_unicode:nn
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[internal]{\@@_initial:N}
%    \begin{macrocode}
\cs_new_protected_nopar: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 } }
          { \@@_use_enc_map:n { GBK } }
      }
      { \@@_use_enc_map:n { GBK } }
  }
%    \end{macrocode}
% \end{macro}
%
%    \begin{macrocode}
\exp_args:Nc \@@_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
\tl_new:N \g_@@_path_str
\luatex_if_engine:TF
  {
    \tl_gset:Nx \g_@@_path_str
      {
        \luatex_directlua:D
          {
            kpse.set_program_name("luatex") ~
            local ~ sfd = kpse.find_file("UGBK.sfd", "subfont~definition~files") ~
            if ~ sfd ~ then ~
              tex.write(sfd) ~
            end
          }
      }
  }
  {
    \ior_open:NnTF \g_@@_sfd_ior { |kpsewhich ~ UGBK.sfd }
      {
        \ior_get_str:NN \g_@@_sfd_ior \g_@@_path_str
        \ior_close:N \g_@@_sfd_ior
      }
      { \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 } }
  {
    \seq_set_split:NnV \l_tmpa_seq { / } \g_@@_path_str
    \seq_pop_right:NN \l_tmpa_seq \g_@@_path_str
    \tl_gset:Nx \g_@@_path_str { \seq_use:Nn \l_tmpa_seq { / } }
  }
%    \end{macrocode}
%
%    \begin{macrocode}
\tl_const:Nx \c_@@_hash_str { \iow_char:N \# }
\tl_const:Nx \c_@@_lbrace_str { \iow_char:N \{ }
\tl_const:Nx \c_@@_rbrace_str { \iow_char:N \} }
\tl_const:Nx \c_@@_backslash_str { \iow_char:N \\ }
\tl_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{macro}[internal]{\c_@@_sfd_map_prop}
%    \begin{macrocode}
\prop_new:N \c_@@_sfd_map_prop
\prop_gput:Nnn \c_@@_sfd_map_prop { GB   } { { 10 } { UGB } }
\prop_gput:Nnn \c_@@_sfd_map_prop { JIS  } { { 40 } { UJIS } }
\prop_gput:Nnn \c_@@_sfd_map_prop { KS   } { { 60 } { UKS } }
\prop_gput:Nnn \c_@@_sfd_map_prop { Bg5  } { { 00 } { UBig5 } }
\prop_gput:Nnn \c_@@_sfd_map_prop { Bg5+ } { { 09 } { UBg5plus } }
\prop_gput:Nnn \c_@@_sfd_map_prop { GBK  } { { 19 } { UGBK } }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[internal]{\@@_write_file:nnn}
%    \begin{macrocode}
\cs_new_protected_nopar:Npn \@@_write_file:nnn #1#2#3
  {
    \group_begin:
    \file_path_include:n { \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:nTF {##1}
              {
                \ior_map_break:n
                  {
                    \@@_write_sfd_map_trailer:n {#1}
                    \@@_write_cmap_file:n {#2}
                  }
              }
              { \@@_read_sfd_line:nnn {##1} {#1} {#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}[internal]{\@@_read_sfd_line:n,\@@_read_sfd_line:nn}
%    \begin{macrocode}
\group_begin:
\char_set_lccode:nn { \c_zero } { `\\ }
\char_set_lccode:nn { \c_one }  { `\x }
\char_set_catcode_other:n { \c_zero }
\char_set_catcode_other:n { \c_one }
\tl_to_lowercase:n
  {
    \group_end:
    \cs_new_protected_nopar:Npn \@@_read_sfd_line:nnn #1#2#3
      { \@@_read_sfd_line:nwnn #1 ^^00 \q_nil \q_stop {#2} {#3} }
    \cs_new_protected_nopar:Npn \@@_read_sfd_line:nwnn
      #1 0^^01 #2 ^^00 #3 \q_stop #4#5
      { \@@_read_sfd_line:nnnnn {#1} { 0^^01 } {#2} {#4} {#5} }
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[internal]{\@@_read_sfd_line:nnnnn}
%    \begin{macrocode}
\cs_new_protected_nopar:Npn \@@_read_sfd_line:nnnnn #1#2#3#4#5
  {
    \tl_if_blank:nF {#1}
      {
        \seq_if_empty:NF \l_@@_sfd_plane_seq
          {
            \iow_now:Nx \g_@@_sfd_map_iow
              {
                \c_@@_indent_str \c_@@_indent_str
                \token_to_str:N \fi: \iow_newline:
                \c_@@_indent_str \c_@@_rbrace_str
              }
            \@@_write_cmap_file:n {#5}
          }
        \@@_write_plane_map:nn {#1} {#4}
        \tl_set:Nx \l_@@_sfd_plane_tl { \tl_trim_spaces:n {#1} }
      }
    \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 \c_@@_indent_str
        \seq_use:Nn \l_@@_sfd_line_seq { \or: }
        \token_to_str:N \or:
      }
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[internal]{\@@_write_plane_map:nn}
%    \begin{macrocode}
\cs_new_protected_nopar:Npn \@@_write_plane_map:nn #1#2
  {
    \iow_now:Nx \g_@@_sfd_map_iow
      {
        \cs_new_nopar:cpn { ~ @@_ #2 _sfd_map_ \int_eval:n {#1} :n ~ } ~
        \c_@@_hash_str 1 \iow_newline:
        \c_@@_indent_str \c_@@_lbrace_str \iow_newline:
        \c_@@_indent_str \c_@@_indent_str
        \exp_not:N \if_case:w \etex_numexpr:D
          \c_@@_hash_str 1 ~ \token_to_str:N \scan_stop:
      }
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[internal]{\@@_write_cmap_file:n}
%    \begin{macrocode}
\cs_new_protected_nopar: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 - \c_one }
        > \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 } { \c_one_hundred } ~
            beginbfchar \iow_newline:
            \l_@@_cmap_block_tl
            endbfchar
          }
      }
    \@@_write_cmap_trailer:
    \seq_clear:N \l_@@_sfd_plane_seq
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[internal]{\@@_write_cmap_body:n}
%    \begin{macrocode}
\cs_new_protected_nopar: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 > \c_fifteen { 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}[internal]{\@@_write_sfd_map_header:n}
%    \begin{macrocode}
\group_begin:
\char_set_catcode_other:N \%
\cs_new_protected_nopar:Npn \@@_write_sfd_map_header:n #1
  {
    \iow_now:Nx \g_@@_sfd_map_iow
      {
        %<*#1> \iow_newline:
        \cs_new_nopar:cpn { ~ CJKtu_#1_sfd_map:nn ~ } ~ \c_@@_hash_str 1
        \iow_newline: \c_@@_indent_str \c_@@_lbrace_str \iow_newline:
        \c_@@_indent_str \c_@@_indent_str
        \token_to_str:N \cs_if_exist_use:cF
        \iow_newline: \c_@@_indent_str \c_@@_indent_str \c_@@_indent_str
          { ~ @@_#1_sfd_map_ ~ \exp_not:N \int_eval:n { \c_@@_hash_str 1 } ~ :n ~}
        \iow_newline: \c_@@_indent_str \c_@@_indent_str \c_@@_indent_str
          { ~ \exp_not:N \use_none:n } \iow_newline:
        \c_@@_indent_str \c_@@_rbrace_str
      }
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[internal]{\@@_write_sfd_map_trailer:n}
%    \begin{macrocode}
\cs_new_protected_nopar:Npn \@@_write_sfd_map_trailer:n #1
  {
    \iow_now:Nx \g_@@_sfd_map_iow
      {
        \c_@@_indent_str \c_@@_indent_str
        \token_to_str:N \fi: \iow_newline:
        \c_@@_indent_str \c_@@_rbrace_str \iow_newline:
        %</#1>
      }
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[internal]{\@@_write_cmap_header:nn}
%    \begin{macrocode}
\cs_new_protected_nopar: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}[internal]{\@@_write_cmap_trailer:}
%    \begin{macrocode}
\cs_new_protected_nopar: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
