% ^^A -*- japanese-latex -*-
% \iffalse meta-comment
%
% This is file 'pxrubrica.dtx'.
% 
% Copyright (c) 2012-2023 Takayuki YATO (aka. "ZR")
%   GitHub:   https://github.com/zr-tex8r
%   Twitter:  @zr_tex8r
%
% This package is distributed under the MIT License.
%
% \fi
% \CheckSum{0}
%
% \iffalse
%
%    \begin{macrocode}
%<!driver>\NeedsTeXFormat{LaTeX2e}
%<!driver>\ProvidesPackage{pxrubrica}
%<*driver>
\ProvidesFile{pxrubrica.dtx}
%</driver>
  [2023/03/01 v1.3e PX Japanese-style ruby]
%<*driver>
\documentclass[uplatex]{jsarticle}
\usepackage{doc}
\addtolength{\textwidth}{-1in}
\addtolength{\evensidemargin}{1in}
\addtolength{\oddsidemargin}{1in}
\addtolength{\marginparwidth}{1in}
\setlength\marginparpush{0pt}
% \OnlyDescription
\DisableCrossrefs
\setcounter{StandardModuleDepth}{1}
\GetFileInfo{pxrubrica.dtx}
\CodelineNumbered
\DeclareRobustCommand\jmeta[1]{%
  \ensuremath\langle\mbox{}%
  {\rmfamily#1}\mbox{}%
  \ensuremath\rangle
}
\newcommand*{\vb}{\symbol{`\|}}
\newcommand*{\PKN}[1]{\textsf{#1}}
\newcommand*{\pad}{\hspace{0pt plus 10pt}\linebreak[0]}
\newcommand*{\Means}{：\ }
\newcommand*{\Note}{\par\noindent ※\ }
\providecommand*{\pTeX}{p\TeX}
\providecommand*{\upTeX}{u\pTeX}
\providecommand*{\pdfTeX}{pdf\/\TeX}
\providecommand*{\XeTeX}{XeTeX}
\providecommand*{\LuaTeX}{Lua\TeX}
\inhibitxspcode`／=0
\begin{document}
  \DocInput{pxrubrica.dtx}
\end{document}
%</driver>
%    \end{macrocode}
%
% \fi
%
% \title{\PKN{pxrubrica} パッケージ}
% \author{八登 崇之\quad(Takayuki YATO; aka ``ZR'')}
% \date{\fileversion \quad[\filedate]}
% \maketitle
%
% \begin{abstract}
% JIS規格「JIS X~4051」およびW3C技術ノート「日本語組版処理の要件」
% で述べられているような、
% 日本において一般的な様式に従ってルビおよび圏点を付ける機能を提供する。 
% \end{abstract}
%
% \MakeShortVerb{\|}
%
% \setcounter{tocdepth}{3}
% \tableofcontents
%
%^^A------------------------------------
% \section{パッケージ読込}
%
% |\usepackage| 命令を用いて読み込む。
% オプションは存在しない。
%\begin{quote}\begin{verbatim}
%\usepackage{pxrubrica}
%\end{verbatim}\end{quote}
%
%^^A------------------------------------
% \section{ルビ機能}
%
% \subsection{用語集}
% 
% 本パッケージで独自の意味をもつ単語を挙げる。
% \begin{itemize}
% \item 突出： ルビ文字出力の端が親文字よりも外側に出ること。
% \item 進入： ルビ文字出力が親文字に隣接する文字の領域
%   （水平方向に見た場合）に配置されること。
% \item 和文ルビ： 親文字が和文文字であることを想定して処理されるルビ。
% \item 欧文ルビ： 親文字が欧文文字であることを想定して処理されるルビ。
% \item グループ： ユーザにより指定された、親文字列・ルビ文字列の処理単位。
% \item クラスタ： 入力文字列中の |{ }| で囲った部分のこと。
%   \footnote{本来の{\LaTeX}の用語では「グループ」と呼ぶが、ここでは
%     「グループ」が別の意味をもつので別の用語を当てた。}
% \item 《文字》： 均等割りにおいて不可分となる単位のこと。
%   本来の意味での文字の他、クラスタも《文字》と扱われる。
% \item ブロック： 複数の親文字・ルビ文字の集まりで、大域的な配置決定の
%   処理の中で内部の相対位置が固定されているもの。
% \end{itemize}
%
% 次の用語については、『日本語組版の要件』%
%   \footnote{|http://www.w3.org/TR/jlreq/ja/|}%
% に従う。
% \begin{quote}
% ルビ、親文字、中付き、肩付き、モノルビ、グループルビ、熟語ルビ、圏点
% \end{quote}
%
% \subsection{ルビ用命令}
%
% \begin{itemize}
% \item |\ruby[|\jmeta{オプション}|]{|\jmeta{親文字}^^A
% |}{|\jmeta{ルビ文字}|}|
% 
% 和文ルビの命令。
% すなわち、和文文字列の上側（横組）／右側（縦組）にルビを付す
% （オプションで逆側にもできる）。
% 
% ここで、\jmeta{オプション}は以下の形式をもつ。
% \begin{quote}
% \jmeta{前進入設定}\jmeta{前補助設定}^^A
% \jmeta{モード}\jmeta{後補助設定}\jmeta{後進入設定}
% \end{quote}
% \jmeta{前補助設定}・\jmeta{モード}・\jmeta{後補助設定}は
% 複数指定可能で、排他な指定が併存した場合は
% 後のものが有効になる。
% また、どの要素も省略可能で、その場合は |\rubysetup| で指定された
% 既定値が用いられる。
% ただし、構文上曖昧な指定を行った場合の結果は保証されない。
% 例えば、「前進入無し」のみ指定する場合は \texttt{\vb} では
% なく \texttt{\vb-} とする必要がある。
%
% \jmeta{前進入設定}は以下の値の何れか。
% \begin{quote}
%   \begin{tabular}[t]{ll}
%     \texttt{\vb\vb} & 前突出禁止\\
%     \texttt{\vb} & 前進入無し\\
%   \end{tabular}\qquad
%   \begin{tabular}[t]{ll}
%     \texttt{<} & 前進入大\\
%     \texttt{(} & 前進入小
%   \end{tabular}
% \end{quote}
%
% \jmeta{前補助設定}は以下の値の何れか（複数指定可）。
% \begin{quote}
%   \begin{tabular}[t]{ll}
%     \texttt{:} & 和欧文間空白挿入 \\
%     \texttt{.} & 空白挿入なし
%   \end{tabular}\qquad
%   \begin{tabular}[t]{ll}
%     \texttt{*} & 行分割禁止 \\
%     \texttt{!} & 段落頭で進入許可
%   \end{tabular}
% \end{quote}
%
% \begin{itemize}
% \item 空白挿入量の既定値は和文間空白である。
% \item |*| 無指定の場合の行分割の可否は {p\LaTeX} の標準の
%   動作に従う。
% \item |!| 無指定の場合、段落冒頭では\jmeta{前進入設定}の設定に
%   関わらず進入が抑止される。
% \item ゴースト処理が有効の場合はここの設定は無視される。
% \end{itemize}
%
% \jmeta{モード}は以下の値の何れか（複数指定可）。
% \begin{quote}
%   \newcommand*\fro[1]{{\scriptsize($<$\,\textit{#1})}}
%   \begin{tabular}[t]{l@{ }ll}
%     \texttt{-} & &（無指定）\\
%     \texttt{c} & \fro{center}    & 中付き\\
%     \texttt{h} & \fro{head}      & 肩付き\\
%     \texttt{H} &                 & 拡張肩付き\\
%     \texttt{m} & \fro{mono}      & モノルビ\\
%     \texttt{g} & \fro{group}     & グループルビ\\
%     \texttt{j} & \fro{jukugo}    & 熟語ルビ\\
%     \texttt{M} &                 & 自動切替モノルビ\\
%     \texttt{J} &                 & 自動切替熟語ルビ
%   \end{tabular}\qquad
%   \begin{tabular}[t]{l@{ }ll}
%     \texttt{P} & \fro{primary}    & 上側配置\\
%     \texttt{S} & \fro{secondary}  & 下側配置\\
%     \texttt{e} & \fro{even-space} & 親文字均等割り有効 \\
%     \texttt{E} &                  & 親文字均等割り無効 \\
%     \texttt{f} & \fro{full-size}  & 小書き文字変換有効 \\
%     \texttt{F} &                  & 小書き文字変換無効 
%   \end{tabular}
% \end{quote}
%
% \begin{itemize}
% \item 肩付き（|h|）の場合、ルビが短い場合にのみ、ルビ文字列と親文字列
%   の頭を揃えて配置される。
%   拡張肩付き（|H|）の場合、常に頭を揃えて配置される。
% \item |P| は親文字列の上側（横組）／右側（縦組）、
%   |S| は親文字列の下側（横組）／左側（縦組）にルビを付す指定。
% \item |e| 指定時は、ルビが長い場合に親文字列をルビの長さに合わせて
%   均等割りで配置する。
%   |E| 指定時は、空きを入れずに中央揃えで配置する。
%   なお、ルビが短い場合のルビ文字列の均等割りは常に有効である。
% \item |f| 指定時は、ルビ文字列中の（|{ }| の外にある）小書き仮名
%   （ぁ\,ぃ\,ぅ\,ぇ\,ぉ\,っ\,ゃ\,ゅ\,ょ\,ゎ、
%   およびその片仮名）を対応の非小書き仮名
%   に変換する。
%   |F| 指定はこの機能を無効にする。
% \item |M| および |J| の指定は
%   「グループルビとモノ・熟語ルビの間で自動的に切り替える」
%   設定である。
%   具体的には、ルビのグループが1つしかない場合は |g|、
%   複数ある場合は |m| および |j| と等価になる。
% \end{itemize}
%
% \jmeta{後補助設定}は以下の値の何れか（複数指定可）。
% \begin{quote}
%   \begin{tabular}[t]{ll}
%     \texttt{:} & 和欧文間空白挿入 \\
%     \texttt{.} & 空白挿入なし
%   \end{tabular}\qquad
%   \begin{tabular}[t]{ll}
%     \texttt{*} & 行分割禁止 \\
%     \texttt{!} & 段落末で進入許可
%   \end{tabular}
% \end{quote}
%
% \begin{itemize}
% \item 空白挿入量の既定値は和文間空白である。
% \item |*| 無指定の場合の行分割の可否は {p\LaTeX} の
%   標準の動作に従うのが原則だが、直後にあるものが文字でない場合、
%   正しく動作しない（禁則が破れる）可能性がある。
%   従って、不適切な行分割が起こりうる場合は適宜 |*| を指定する
%   必要がある（なお、段落末尾で |*| を指定してはならない）。
% \item |!| 無指定の場合、段落末尾では進入が抑止される。
% \item ゴースト処理が有効の場合はここの設定は無視される。
% \end{itemize}
%
% \jmeta{後進入設定}は以下の値。
% \begin{quote}
%   \begin{tabular}[t]{ll}
%     \texttt{\vb\vb} & 後突出禁止\\
%     \texttt{\vb} & 後進入無し\\
%   \end{tabular}\qquad
%   \begin{tabular}[t]{ll}
%     \texttt{>} & 後進入大\\
%     \texttt{)} & 後進入小
%   \end{tabular}
% \end{quote}
%
% \item |\jruby[|\jmeta{オプション}|]{|\jmeta{親文字}^^A
% |}{|\jmeta{ルビ文字}|}|
%
% |\ruby| 命令の別名。
% |\ruby| という命令名は他のパッケージとの衝突の可能性が
% 高いので、{\LaTeX}文書の本文開始時（|\begin{document}|）に
% 未定義である場合にのみ定義される。
% これに対して |\jruby| は常に定義される。
% なお、|\ruby| 以外の命令（|\jruby| を含む）が定義済であった
% （命令名が衝突した）場合にはエラーとなる。
% 
% \item |\aruby[|\jmeta{オプション}|]{|\jmeta{親文字}^^A
% |}{|\jmeta{ルビ文字}|}|
% 
% 欧文ルビの命令。
% すなわち、欧文文字列の上側（横組）／右側（縦組）にルビを付す。
%
% 欧文ルビは和文ルビと比べて以下の点が異なる。
% \begin{itemize}
% \item 常にグループルビと扱われる。
%   （|m|、|g|、|j| の指定は無効。）
% \item 親文字列の均等割りは常に無効である。
%   （|e| 指定は無効。）
% \item ルビ付き文字と前後の文字との間の空き調整や行分割可否は
%   両者がともに欧文であるという想定で行われる。
%   従って、既定では空き調整量はゼロ、行分割は禁止となる。
% \item 空き調整を和欧文間空白（|:|）にした場合は、
%   |*| が指定されるあるいは自動の禁則処理が働くのでない限り、
%   行分割が許可される。
% \end{itemize}
% 
% \item |\truby[|\jmeta{オプション}|]{|\jmeta{親文字}^^A
% |}{|\jmeta{上側ルビ文字}|}{|\jmeta{下側ルビ文字}|}|
% 
% 和文両側ルビの命令。
% 横組の場合、親文字列の上側と下側にルビを付す。
% 縦組の場合、親文字列の右側と左側にルビを付す。
%
% 両側ルビで熟語ルビを使うことはできない。
% すなわち、\jmeta{オプション}中で |j|、|J| は指定できない。
%
% \Note 1.1版以前では常にグループルビの扱いであった。
% 旧版との互換のため、両側ルビの場合には自動切替モノルビ（|M|）を
% 既定値とする。
% \footnote{つまり、旧来の使用ではグループルビと扱われるため、
%   ルビのグループは1つにしているはずで、これは新版でもそのまま
%   グループルビと扱われる。
%   一方で、モノルビを使いたい場合はグループを複数にするはずで、
%   この時は自動的にモノルビになる。
%   なので結局、基底モード（\texttt{g}、\texttt{m}）を指定する
%   必要は無いことになる。}
%
% \item |\atruby[|\jmeta{オプション}|]{|\jmeta{親文字}^^A
% |}{|\jmeta{上側ルビ文字}|}{|\jmeta{下側ルビ文字}|}|
% 
% 欧文両側ルビの命令。
% 欧文ルビであることを除き |\truby| と同じ。
%
% \end{itemize}
%
% \subsection{ルビ命令の入力文字列の入力規則}
%
% ルビの処理では入力文字列（親文字列・ルビ文字列）を
% 文字毎に分解する必要がある。
% このため、ルビ命令の入力文字列は一定の規則に従って
% 書かれる必要がある。
%
% ルビ命令の入力文字列には以下のものを含めることができる。
%
% \begin{itemize}
% \item \texttt{\vb}\Means グループの区切りを表す。
%   \begin{itemize}
%   \item 現在の版では、親文字列でグループ区切りを利用する機能はない。
%     \footnote{将来の機能拡張において、親文字列が複数グループをもつような
%       使用法が想定されている。}%
%     従って、親文字列中に \texttt{\vb} があると常にエラーになる。
%   \item ルビ文字列中では、一つのグループが一つの親文字に対応する
%     範囲を表す（モノルビ・熟語ルビの場合）。
%   \end{itemize}
%
% \item 通常文字\Means {\LaTeX}の命令や特殊文字や欧文空白
%   や \texttt{\vb} でない、欧文または和文の文字を指す。
%   これは一つの《文字》と見なされる。
%   \begin{itemize}
%   \item 和文ルビ命令の親文字列に欧文文字を含めた場合、
%     その文字は組版上“和文文字のように”振舞う。
%   \end{itemize}
%
% \item クラスタ\Means すなわち、|{ }| に囲まれたテキスト。
%   全体が一つの《文字》と見なされる。
%   \begin{itemize}
%   \item クラスタの中では任意の{\LaTeX}の“インライン\mbox{”}%
%     \footnote{「強制改行や改段落を含まない」ということ。
%       {\LaTeX}の用語では「LRモード」と呼ぶ。}%
%     の命令が使える。
%\begin{quote}\begin{verbatim}
%\ruby[j]{{\CID{7652}}飾区}{かつ|し{\color{red}{か}}|く}
%\end{verbatim}\end{quote}
%   \item クラスタ中の \texttt{\vb} は通常文字として扱われる。
%   \end{itemize}
%
%   \Note 例外的に、欧文ルビの親文字列は、あたかもそれ全体が
%   一つのクラスタであるように振舞う。
%   つまり、任意の“インライン”の命令が使えて、
%   全体で一つの欧文文字であるのと同様に振舞う。
%
% \end{itemize}
%
% \subsection{ルビ文字列のグループの指定}
%
% ルビ文字列の \texttt{\vb} はグループの区切りを表す。
% 例えば、ルビ文字列
%\begin{quote}\begin{verbatim}
%じゆく|ご
%\end{verbatim}\end{quote}
% は2つのグループからなり、最初のものは3文字、後のものは
% 1文字からなる。
%
% 長さを合わせるために均等割りを行う場合、その分割の単位は
% 《文字》（通常文字またはクラスタ）となる。
% 例えば
%\begin{quote}\begin{verbatim}
%ベクタ{\<（ー）\<}
%\end{verbatim}\end{quote}
% は1つのグループからなり、それは4つの《文字》からなる。
%
% グループや《文字》の指定はルビの付き方に影響する。
% \begin{itemize}
% \item モノルビ・熟語ルビでは親文字列の1つの《文字》にルビ文字列の
%   1つのグループが対応する。
%   例えば、
%\begin{quote}\begin{verbatim}
%\ruby[m]{熟語}{じゆく|ご}
%\end{verbatim}\end{quote}
%   は、「熟+じゆく」「語+ご」の2つのブロックからなる。
% \item （単純）グループルビではルビ文字列のグループも1つに限られ、
%   親文字とルビ文字の唯一のグループが対応する。
%   例えば、
%\begin{quote}\begin{verbatim}
%\ruby[g]{五月雨}{さみだれ}
%\end{verbatim}\end{quote}
%   は、「五月雨+さみだれ」の1つのブロックからなる。
% \end{itemize}
%
% \subsection{ゴースト処理}
%
% 「和文ゴースト処理」とは以下のようなものである：
% \begin{quote}
%   和文ルビの親文字列出力の前後に全角空白文字を挿入する
%   （ただしその空きを打ち消すように負の空きを同時に入れる）
%   ことで、親文字列全体が、その外側から見たときに、
%   全角空白文字（大抵のJFMではこれは漢字と同じ扱いになる）
%   と同様に扱われるようにする。
%   例えば、前に欧文文字がある場合には自動的に和欧文間空白が
%   挿入される。
% \end{quote}
% 
% 「欧文ゴースト処理」も対象が欧文であることと除いて同じである。
% （こちらは、「複合語記号（compound word mark）」というゼロ幅
% 不可視の欧文文字を用いる。
% ルビ付文字列全体が単一欧文文字のように扱われる。）
% なお、「ゴースト（ghost）」というのはOmegaの用語で、
% 「不可視であるが（何らかの性質において）特定の可視の文字と
% 同等の役割をもつオブジェクト」のことである。
%
% ゴースト処理を有効にすると次のようなメリットがある。
%
% \begin{itemize}
% \item 和欧文間空白が自動的に挿入される。
% \item 行分割禁止（禁則処理）が常に正しく機能する。
% \item 特殊な状況（例えば段落末）でも異常動作を起こしにくい。
% \item （実装が単純化され、バグ混入の余地が少なくなる。）
% \end{itemize}
%
% ただし、次のような重要なデメリットがある。
%
% \begin{itemize}
% \item {p\TeX}エンジンの仕様上の制約により、ルビ出力の
%   進入と共存できない。
%   （従って共存するような設定を試みるとエラーになる。）
% \end{itemize}
%
% このため、既定ではゴースト処理は無効になっている。
% 有効にするには、|\rubyusejghost|（和文）
% ／|\rubyuseaghost|（欧文）を実行する。
%
% なお、\jmeta{前補助設定}／\jmeta{後補助設定}で指定される機能は、
% ゴースト処理が有効の場合には無効化される。
% これらの機能の目的が自動処理が失敗するのを補充するためだからである。
%
% \subsection{パラメタ設定命令}
%
% 基本的設定。
%
% \begin{itemize}
%
% \item |\rubysetup{|\jmeta{オプション}|}|
%
% オプションの既定値設定。
% ［既定 = \texttt{\vb cjPeF\vb}］
% \begin{itemize}
% \item これ自体の既定値は
%   「突出許可、進入無し、中付き、熟語ルビ、上側配置、
%   親文字均等割り有効、小書き文字変換無効」である。
% \item \jmeta{前補助設定}／\jmeta{後補助設定}の既定値は変更
%   できない。
%   |\rubysetup| でこれらのオプション文字を指定しても
%   無視される。
% \item |\rubysetup| での設定は累積する。
%   例えば、初期状態から、|\rubysetup{hmf}| と |\rubysetup{<->}| を
%   実行した場合、既定値設定は |<hmPef>| となる。
% \item この設定に関わらず、両側ルビでは「自動切替モノルビ（|M|）」
%   が既定として指定される。
% \end{itemize}
%
% \item |\rubyfontsetup{|\jmeta{命令}|}|
%
% ルビ用のフォント切替命令を設定する。
% 例えば、ルビは必ず明朝体で出力したいという場合は、
% 以下の命令を実行すればよい。
%\begin{quote}\begin{verbatim}
%\rubyfontsetup{\mcfamily}
%\end{verbatim}\end{quote}
%
% \item |\rubybigintrusion{|\jmeta{実数}|}|
%
% 「大」の進入量（ルビ全角単位）。
% ［既定 = 1］
%
% \item |\rubysmallintrusion{|\jmeta{実数}|}|
%
% 「小」の進入量（ルビ全角単位）。
% ［既定 = 0.5］
%
% \item |\rubymaxmargin{|\jmeta{実数}|}|
%
% ルビ文字列の方が短い場合の、ルビ文字列の端の親文字列の端
% からの距離の上限値（親文字全角単位）。
% ［既定 = 0.75］
%
% \item |\rubyintergap{|\jmeta{実数}|}|
%
% ルビと親文字の間の空き（親文字全角単位）。
% ［既定 = 0］
%
% \item |\rubyusejghost|／|\rubynousejghost|
%
% 和文ゴースト処理を行う／行わない。
% ［既定 = 行わない］
%
% \item |\rubyuseaghost|／|\rubynouseaghost|
%
% 欧文ゴースト処理を行う／行わない。
% ［既定 = 行わない］
%
% \end{itemize}
%
% 詳細設定。
% 通常はこれらの既定値を変える必要はないだろう。
%
% \begin{itemize}
% 
% \item |\rubysafemode|／|\rubynosafemode|
%
% 安全モードを有効／無効にする。
% ［既定 = 無効］
% \begin{itemize}
% \item 本パッケージがサポートするエンジンは
%   (u){\pTeX}、{\XeTeX}、{\LuaTeX}である。
%   「安全モード」とは、これらのエンジンを必要とする一部の機能
%   \footnote{安全モードでは、強制的にグループルビに切り替わる。
%     また、親文字・ルビの両方の均等割り付け、および、
%     小書き文字自動変換が無効になる。}%
%   を無効化したモードである。
%   つまり、安全モードに切り替えることで、“サポート対象”でない
%   エンジン（{\pdfTeX}等）でも本パッケージの一部の機能が
%   使える可能性がある。
% \item 使用中のエンジンが{\pdfTeX}である場合、既定で安全モード
%   が有効になる。
% \end{itemize}
%
% \item |\rubysizeratio{|\jmeta{実数}|}|
%
% ルビサイズの親文字サイズに対する割合。
% ［既定 = 0.5］
%
% \item |\rubystretchprop{|\meta{X}|}{|\meta{Y}|}{|\meta{Z}|}|
%
% ルビ用均等割りの比率の指定。
% ［既定 = 1, 2, 1］
%
% \item |\rubystretchprophead{|\meta{Y}|}{|\meta{Z}|}|
%
% 前突出禁止時の均等割りの比率の指定。
% ［既定 = 1, 1］
%
% \item |\rubystretchpropend{|\meta{X}|}{|\meta{Y}|}|
%
% 後突出禁止時の均等割りの比率の指定。
% ［既定 = 1, 1］
%
% \item |\rubyyheightratio{|\jmeta{実数}|}|
%
% 横組和文の高さの縦幅に対する割合。
% ［既定 = 0.88］
%
% \item |\rubytheightratio{|\jmeta{実数}|}|
%
% 縦組和文の「高さ」の「縦幅」に対する割合
% （{p\TeX}の縦組では「縦」と「横」が実際の逆になる）。
% ［既定 = 0.5］
%
% \end{itemize}
%
%^^A------------------------------------
% \section{圏点機能}
%
% \subsection{圏点用命令}
%
% \begin{itemize}
% \item |\kenten[|\jmeta{オプション}|]{|\jmeta{親文字}|}|
%
% 和文文字列の上側（横組）／右側（縦組）に圏点を付す
% （オプションで逆側にもできる）。
%
% \jmeta{オプション}は複数指定可能で、排他な指定が併存した場合は
% 後のものが有効になる。
% また、省略された指定については |\kentensetup| で指定された
% 既定値が用いられる。
%
% オプションに指定できる値は以下の通り。
% \begin{quote}
%   \newcommand*\fro[1]{{\scriptsize($<$\,\textit{#1})}}
%   \begin{tabular}[t]{l@{ }ll}
%     \texttt{p} & \fro{primary}   & 主マーク\\
%     \texttt{s} & \fro{seconday}  & 副マーク\\
%     \texttt{f} & \fro{full}      & 全文字付加有効\\
%     \texttt{F} &                 & 全文字付加無効
%   \end{tabular}\qquad
%   \begin{tabular}[t]{l@{ }ll}
%     \texttt{P} & \fro{primary}    & 上側配置\\
%     \texttt{S} & \fro{secondary}  & 下側配置
%   \end{tabular}
% \end{quote}
%
% \begin{itemize}
% \item |p|、|s| は付加する圏点の種類を表す。
%   横組では主マーク（|p|）は黒中点、副マーク（|s|）は黒ゴマ点が
%   用いられ、縦組では逆に主マークが黒ゴマ点、副マークが黒中点となる。
%   ただし設定命令により圏点の種類は変更できる。
% \item |P| は親文字列の上側（横組）／右側（縦組）、
%   |S| は親文字列の下側（横組）／左側（縦組）に圏点を付す指定。
% \item |f| 指定時は、親文字列に含まれる“通常文字”の全てに圏点を付加する。
%   |F| 指定時は、約物である“通常文字”には圏点を付加しない。
% \end{itemize}
%
% \end{itemize}
%
% \subsection{圏点命令の親文字列の入力規則}
%
% 圏点付加の処理では親文字列を文字毎に分解する必要がある。
% このため、圏点命令の親文字列は一定の規則に従って
% 書かれる必要がある。
%
% 圏点命令の親文字列には以下のものを含めることができる。
%
% \begin{itemize}
% \item 通常文字\Means {\LaTeX}の命令や特殊文字や欧文空白でない、
%   欧文または和文の文字を指す。
%   通常文字には一つの圏点が付加される。
%   \begin{itemize}
%   \item |F| オプションを指定した場合、約物（句読点等）の文字には
%     圏点が付加されない。
%   \item 欧文文字に圏点を付けた場合、その文字は組版上
%     “和文文字のように”振舞う。
%   \end{itemize}
% \item {\LaTeX}の命令および欧文空白\Means これらには
%   圏点が付加されない。
%   \begin{itemize}
%   \item 主に |\,| や |\quad| のような空白用の命令の使用を
%     意図している。
%   \item |\hspace{1zw}| のような引数を取る命令をそのまま書くことは
%     できない。
%     この場合は、以降に示す何れかの書式を利用する必要がある。
%     \footnote{全角空白（\verb|\hspace{1zw}|）や和欧文間空白
%       （\verb|\hspace{\kanjiskip}|）を出力する専用のマクロを用意して
%       おくと便利かもしれない。}
%   \end{itemize}
% \item クラスタ\Means すなわち、|{ }| に囲まれた任意のテキスト。
%   ルビ命令のクラスタと同様に、一つの《文字》として扱われ、
%   全体に対して一つの圏点が付加される。
%   \begin{itemize}
%   \item \PKN{japanese-otf}パッケージの |\CID| 命令のような、
%     「特殊な和文文字を出力する命令」の使用を意図している。
%   \end{itemize}
% \item |\kspan{|\jmeta{テキスト}|}|\Means これは、
%   出力されるテキストの幅に応じた個数の圏点が付加される。
%   \begin{itemize}
%   \item 例えば、“くの字点”に圏点を付す場合に使える。
%   \item あるいは、（少々手抜きであるが
%     \footnote{本来は、\verb|\textgt| の中で改めて \verb|\kenten|
%       を使うべきである。}%
%     ）|\kenten{この\kspan{\textgt{文字}}だ}| みたいな使い方も
%     考えられる。
%   \end{itemize}
% \item |\kspan*{|\jmeta{テキスト}|}|\Means これは
%   圏点を付さずにテキストをそのまま出力する。
% \item ルビ命令（|\ruby| 等）\Means 例えば
%\begin{quote}\begin{verbatim}
%\kenten{これが\ruby[|j|]{圏点}{けん|てん}です}。
%\end{verbatim}\end{quote}
%   のように、ルビ命令はそのまま書くことができる。
%   \begin{itemize}
%   \item |\kentenrubycombination| の設定によっては、ルビと圏点の両方が
%     付加される。
%   \item 実装上の制限
%     \footnote{圏点命令は常にゴースト処理を伴うため、先述の
%     「ゴースト処理と進入は共存しない」という制限に引っかかるのである。}%
%     のため、圏点命令の先頭にルビ命令がある場合、
%     ルビの前側の進入が無効になる。
%     同様に、圏点命令の末尾にルビ命令がある場合、
%     ルビの後側の進入が無効になる。
%   \item 圏点命令中のルビの処理は通常の場合と比べて“複雑”であるため、
%     自動的な禁則処理が働かない可能性が高い。
%     従って、必要に応じて補助設定で分割禁止（|*|）を指定する必要がある。
%   \item 逆にルビ命令の入力に圏点命令をそのまま書くことはできない。
%\begin{quote}\begin{verbatim}
%\ruby[|j|]{\kenten{圏点}}{けん|てん}% 不可
%\end{verbatim}\end{quote}
%     |{ }| で囲った《文字》の中では使えるが、この場合は同時付加とは
%     見なされず、独立に動作することになる。
%   \end{itemize}
% \end{itemize}
%
% \subsection{ゴースト処理}
%
% 圏点出力ではルビと異なり進入の処理が不要である。
% このため、現状では、圏点命令については
% \textgt{常に}和文ゴースト処理を適用する。
%
% \Note 非標準の和文メトリック（JFM）が使われている等の理由で、
% 和文ゴースト処理が正常に機能しない場合が存在する。
% このため、将来的に、圏点命令についても和文ゴースト処理を
% 行わない（ルビ命令と同様の補助設定を適用する）設定を
% 用意する予定である。
%
% \subsection{パラメタ設定命令}
%
% \begin{itemize}
%
% \item |\kentensetup{|\jmeta{オプション}|}|
%
% オプションの既定値設定。
% ［既定 = \texttt{pPF}］
%
% \item |\kentenmarkinyoko{|\jmeta{名前またはテキスト}|}|
%
% 横組時の主マーク（|p| 指定時）として使われる圏点を指定する。
% ［既定 = |bullet*|］
%
% パッケージで予め用意されている圏点種別については名前で指定できる。
% \begin{quote}
%   \newcommand*\Us[1]{\symbol{"#1}}
%   \newcommand*\Ucomp{{\small \<（合成）\<}}
%   \newcommand*\U[1]{\texttt{#1}}
%   \begin{tabular}[t]{ll@{ }ll}
%     \texttt{bullet*}   & {・}      & \Ucomp   & 黒中点\\
%     \texttt{bullet}    & {・}      & \U{2022*}& 黒中点\\
%     \texttt{Bullet}    & \Us{25E6} & \U{25E6*}& 白中点\\
%     \texttt{sesame*}   & \Us{FE45} & \Ucomp   & 黒ゴマ点\\
%     \texttt{sesame}    & \Us{FE45} & \U{FE45*}& 黒ゴマ点\\
%     \texttt{Sesame}    & \Us{FE46} & \U{FE46*}& 白ゴマ点
%   \end{tabular}\qquad
%   \begin{tabular}[t]{ll@{ }ll}
%     \texttt{triangle}  & \Us{25B2} & \U{25B2} & 黒三角\\
%     \texttt{Triangle}  & \Us{25B3} & \U{25B3} & 白三角\\
%     \texttt{circle}    & \Us{25CF} & \U{25CF} & 黒丸\\
%     \texttt{Circle}    & \Us{25CB} & \U{25CB} & 白丸\\
%     \texttt{bullseye}  & \Us{25CE} & \U{25CE} & 二重丸\\
%     \texttt{fisheye}   & \Us{25C9} & \U{25C9*}& 蛇の目点
%   \end{tabular}
% \end{quote}
% \begin{itemize}
% \item これらの圏点種別のうち、
%   |bullet*| は中黒“{・}”（U+30FB）、
%   |sesame*| は読点“{、}”（U+3001）の
%   字形を加工したものを利用する。
%   これらはどんな日本語フォントでもサポートされているので、
%   確実に使用できる。
% \item それ以外の圏点種別は、記載の文字コードをもつ
%   Unicode文字を出力する。
%   使用するフォントによっては、字形を持っていないため何も出力されない、
%   あるいは字形が全角幅でないため正常に出力されない、
%   という可能性がある。
% \item 文字コード値に |*| を付けたものは、その文字が
%   JIS~X~0208にないことを表す。
%   {\pLaTeX}でこれらの圏点種別を利用するためには
%   \PKN{japanese-otf}パッケージを読み込む必要がある。
% \end{itemize}
%
% あるいは、名前の代わりに任意の{\LaTeX}のテキストを書くことができる。
% \footnote{ただし、引数の先頭の文字がASCII英字である場合は
%   名前の指定と見なされるため、テキストとして扱いたい場合は
%   適宜 \verb|{ }| を補う等の措置が必要である。}%
%\begin{quote}\begin{verbatim}
%\kentenmarkinyoko{※}
%\end{verbatim}\end{quote}
%
% \item |\kentensubmarkinyoko{|\jmeta{名前またはテキスト}|}|
%
% 横組時の副マーク（|s| 指定時）として使われる圏点を指定する。
% ［既定 = |sesame*|］
%
% \item |\kentenmarkintate{|\jmeta{名前またはテキスト}|}|
%
% 縦組時の主マーク（|p| 指定時）として使われる圏点を指定する。
% ［既定 = |sesame*|］
%
% \item |\kentensubmarkintate{|\jmeta{名前またはテキスト}|}|
%
% 縦組時の副マーク（|s| 指定時）として使われる圏点を指定する。
% ［既定 = |bullet*|］
%
% \item |\kentenfontsetup{|\jmeta{命令}|}|
%
% 圏点用のフォント切替命令を設定する。
%
% \item |\kentenintergap{|\jmeta{実数}|}|
%
% 圏点と親文字の間の空き（親文字全角単位）。
% ［既定 = 0］
%
% \item |\kentensizeratio{|\jmeta{実数}|}|
%
% 圏点サイズの親文字サイズに対する割合。
% ［既定 = 0.5］
%
% \end{itemize}
%
% 圏点とルビの同時付加に関する設定。
%
% \begin{itemize}
%
% \item |\kentenrubycombination{|\jmeta{値}|}|
% 圏点命令の親文字中でルビ命令が使われた時の挙動を指定する。
% ［既定 = |both|］
% \begin{itemize}
% \item |ruby|： ルビのみを出力する。
% \item |both|： ルビの外側に圏点を出力する。
% \end{itemize}
%
% \item |\kentenrubyintergap{|\jmeta{実数}|}|
%
% 圏点とルビが同じ側に付いた時の間の空き（親文字全角単位）。
% ［既定 = 0］
%
% \end{itemize}
%
%^^A------------------------------------
%\iffalse
% \section{将来の拡張機能\<（未実装）}
%
% （この節では、まだ実装されていないが、
% 実現できればよいと考えている機能について述べる。）
%
% 「行分割の有無により親文字とルビ文字の相対位置が変化する」
% ような処理は、{\TeX}での実現は非常に難しい。
% これを{$\varepsilon$-p\TeX}の拡張機能を用いて何とか
% 実現したい。
%
% \begin{itemize}
%
% \item 可動グループルビ機能\Means
%   例えば、
%\begin{quote}\begin{verbatim}
%\ruby[g]{我思う|故に|我有り}{コギト・|エルゴ・|スム}
%\end{verbatim}\end{quote}
%   のようにグループルビで複数グループを指定すると、
%   通常は「我思う故に我有り+コギト・エルゴ・スム」の1ブロックに
%   なるが、グループの区切りで行分割可能となり、例えば最初のグループ
%   の後で行分割された場合は、自動的に
%   「我思う+コギト・」と「故に我有り+エルゴ・スム」の2ブロックでの
%   組版に変化する。
% \item 行頭・行末での突出の自動補正\Means
%   行頭（行末）に配置されたルビ付き文字列では、自動的に
%   前（後）突出を禁止する。
% \item 熟語ルビの途中での行分割の許可\Means
%   例えば、
%\begin{quote}\begin{verbatim}
%\ruby[j]{熟語}{じゆく|ご}
%\end{verbatim}\end{quote}
%   の場合、結果はグループルビ処理の「熟語+じゆくご」
%   となるが、途中での行分割が可能で、その場合、
%   「熟+じゆく」「語+ご」の2ブロックで出力される。
%
% \end{itemize}
%
% \subsection{拡張機能設定の命令}
%
% \begin{itemize}
%
% \item |\rubyuseextra{|\jmeta{整数}|}|
% 
% 拡張機能の実装方法。
% ［既定 = 0］
% \begin{itemize}
% \item 0： 拡張機能を無効にする。
% \item 1： まだよくわからないなにか（未実装）。
% \end{itemize}
% 
% \item |\rubyadjustatlineedge|／|\rubynoadjustatlineedge|
%
% 行頭・行末での突出の自動補正を行う／行わない。
% ［既定 = 行わない］
% 
% \item |\rubybreakjukugo|／|\rubynobreakjukugo|
%
% モノルビ処理にならない熟語ルビで中間の行分割を許す／許さない。
% ［既定 = 許さない］
%
% \end{itemize}
%\fi
%^^A========================================================
% \StopEventually
% \newpage
% \setlength{\parindent}{0pt}
% \newcommand*{\cs}[1]{\texttt{\symbol{`\\}#1}}
%
%^^A------------------------------------
% \section{実装（ルビ関連）}
%
% \subsection{前提パッケージ}
%
% \PKN{keyval}を使う予定（まだ使っていない）。
%    \begin{macrocode}
\RequirePackage{keyval}
%    \end{macrocode}
%
% \subsection{エラーメッセージ}
%
% \begin{macro}{\pxrr@error}
% \begin{macro}{\pxrr@warn}
% エラー出力命令。
%    \begin{macrocode}
\def\pxrr@pkgname{pxrubrica}
\def\pxrr@error{%
  \PackageError\pxrr@pkgname
}
\def\pxrr@warn{%
  \PackageWarning\pxrr@pkgname
}
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\ifpxrr@fatal@error}
% 致命的エラーが発生したか。
% スイッチ。
%    \begin{macrocode}
\newif\ifpxrr@fatal@error
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@fatal@error}
% 致命的エラーのフラグを立てて、エラーを表示する。
%    \begin{macrocode}
\def\pxrr@fatal@error{%
  \pxrr@fatal@errortrue
  \pxrr@error
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@eh@fatal}
% 致命的エラーのヘルプ。
%    \begin{macrocode}
\def\pxrr@eh@fatal{%
  The whole ruby input was ignored.\MessageBreak
  \@ehc
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@fatal@not@supported}
% 未実装の機能を呼び出した場合。
%    \begin{macrocode}
\def\pxrr@fatal@not@supported#1{%
  \pxrr@fatal@error{Not yet supported: #1}%
  \pxrr@eh@fatal
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@err@inv@value}
% 引数に無効な値が指定された場合。
%    \begin{macrocode}
\def\pxrr@err@inv@value#1{%
  \pxrr@error{Invalud value (#1)}%
  \@ehc
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@fatal@unx@letter}
% オプション中に不測の文字が現れた場合。
%    \begin{macrocode}
\def\pxrr@fatal@unx@letter#1{%
  \pxrr@fatal@error{Unexpected letter '#1' found}%
  \pxrr@eh@fatal
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@warn@bad@athead}
% モノルビ以外、あるいは横組みで肩付き指定が行われた場合。
% 強制的に中付きに変更される。
%    \begin{macrocode}
\def\pxrr@warn@bad@athead{%
  \pxrr@warn{Position 'h' not allowed here}%
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@warn@must@group}
% 欧文ルビでグループルビ以外の指定が行われた場合。
% 強制的にグループルビに変更される。
%    \begin{macrocode}
\def\pxrr@warn@must@group{%
  \pxrr@warn{Only group ruby is allowed here}%
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@warn@bad@jukugo}
% 両側ルビで熟語ルビの指定が行われた場合。
% 強制的に選択的モノルビ（|M|）に変更される。
%    \begin{macrocode}
\def\pxrr@warn@bad@jukugo{%
  \pxrr@warn{Jukugo ruby is not allowed here}%
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@fatal@bad@intr}
% ゴースト処理が有効で進入有りを設定した場合。
% （致命的エラー）。
%    \begin{macrocode}
\def\pxrr@fatal@bad@intr{%
  \pxrr@fatal@error{%
    Intrusion disallowed when ghost is enabled%
  }\pxrr@eh@fatal
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@fatal@bad@no@protr}
% 前と後の両方で突出禁止を設定した場合。
% （致命的エラー）。
%    \begin{macrocode}
\def\pxrr@fatal@bad@no@protr{%
  \pxrr@fatal@error{%
    Protrusion must be allowed for either end%
  }\pxrr@eh@fatal
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@fatal@bad@length}
% 親文字列とルビ文字列でグループの個数が食い違う場合。
% （モノルビ・熟語ルビの場合、親文字のグループ数は実際には
% 《文字》数のこと。）
%    \begin{macrocode}
\def\pxrr@fatal@bad@length#1#2{%
  \pxrr@fatal@error{%
    Group count mismatch between the ruby and\MessageBreak
    the body (#1 <> #2)%
  }\pxrr@eh@fatal
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@fatal@bad@mono}
% モノルビ・熟語ルビの親文字列が2つ以上のグループを持つ場合。
%    \begin{macrocode}
\def\pxrr@fatal@bad@mono{%
  \pxrr@fatal@error{%
    Mono-ruby body must have a single group%
  }\pxrr@eh@fatal
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@fatal@bad@switching}
% 選択的ルビの親文字列が2つ以上のグループを持つ場合。
%    \begin{macrocode}
\def\pxrr@fatal@bad@switching{%
  \pxrr@fatal@error{%
    The body of Switching-ruby (M/J) must\MessageBreak
    have a single group%
  }\pxrr@eh@fatal
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@fatal@bad@movable}
% 欧文ルビ（必ずグループルビとなる）で
% ルビ文字列が2つ以上のグループを持つ場合。
%    \begin{macrocode}
\def\pxrr@fatal@bad@movable{%
  \pxrr@fatal@error{%
    Movable group ruby is not allowed here%
  }\pxrr@eh@fatal
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@fatal@na@movable}
% グループルビでルビ文字列が2つ以上のグループを持つ
% （つまり可動グループルビである）が、拡張機能が無効であるため
% 実現できない場合。
%    \begin{macrocode}
\def\pxrr@fatal@na@movable{%
  \pxrr@fatal@error{%
    Feature of movable group ruby is disabled%
  }\pxrr@eh@fatal
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@warn@load@order}
% Unicode {\TeX}用の日本語組版パッケージ（Lua{\TeX}-ja等）は
% このパッケージより前に読み込むべきだが、後で読み込まれている
% ことが判明した場合。
%    \begin{macrocode}
\def\pxrr@warn@load@order#1{%
  \pxrr@warn{%
    This package should be loaded after '#1'%
  }%
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@interror}
% 内部エラー。
% これが出てはいけない。{\small\texttt{:-)}}
%    \begin{macrocode}
\def\pxrr@interror#1{%
  \pxrr@fatal@error{INTERNAL ERROR (#1)}%
  \pxrr@eh@fatal
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\ifpxrrDebug}
% デバッグモード指定。
%    \begin{macrocode}
\newif\ifpxrrDebug
%    \end{macrocode}
% \end{macro}
%
% \subsection{パラメタ}
%
% \subsubsection{全般設定}
%
% \begin{macro}{\pxrr@ruby@font}
% ルビ用フォント切替命令。
%    \begin{macrocode}
\let\pxrr@ruby@font\@empty
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@big@intr}
% \begin{macro}{\pxrr@small@intr}
% 「大」と「小」の進入量
% （|\rubybigintrusion|／|\rubysmallintrusion|）。
% 実数値マクロ（数字列に展開される）。
%    \begin{macrocode}
\def\pxrr@big@intr{1}
\def\pxrr@small@intr{0.5}
%    \end{macrocode}
% \end{macro}
% \end{macro}

% \begin{macro}{\pxrr@size@ratio}
% ルビ文字サイズ
% （|\rubysizeratio|）。
% 実数値マクロ。
%    \begin{macrocode}
\def\pxrr@size@ratio{0.5}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@sprop@x}
% \begin{macro}{\pxrr@sprop@y}
% \begin{macro}{\pxrr@sprop@z}
% 伸縮配置比率
% （|\rubystretchprop|）。
% 実数値マクロ。
%    \begin{macrocode}
\def\pxrr@sprop@x{1}
\def\pxrr@sprop@y{2}
\def\pxrr@sprop@z{1}
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\pxrr@sprop@hy}
% \begin{macro}{\pxrr@sprop@hz}
% 伸縮配置比率
% （|\rubystretchprophead|）。
% 実数値マクロ。
%    \begin{macrocode}
\def\pxrr@sprop@hy{1}
\def\pxrr@sprop@hz{1}
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\pxrr@sprop@ex}
% \begin{macro}{\pxrr@sprop@ey}
% 伸縮配置比率
% （|\rubystretchpropend|）。
% 実数値マクロ。
%    \begin{macrocode}
\def\pxrr@sprop@ex{1}
\def\pxrr@sprop@ey{1}
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\pxrr@maxmargin}
% ルビ文字列の最大マージン
% （|\rubymaxmargin|）。
% 実数値マクロ。
%    \begin{macrocode}
\def\pxrr@maxmargin{0.75}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@yhtratio}
% 横組和文の高さの縦幅に対する割合
% （|\rubyyheightratio|）。
% 実数値マクロ。
%    \begin{macrocode}
\def\pxrr@yhtratio{0.88}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@thtratio}
% 縦組和文の高さの縦幅に対する割合
% （|\rubytheightratio|）。
% 実数値マクロ。
%    \begin{macrocode}
\def\pxrr@thtratio{0.5}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@extra}
% 拡張機能実装方法
% （|\rubyuseextra|）。
% 整数定数。
%    \begin{macrocode}
\chardef\pxrr@extra=0
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\ifpxrr@jghost}
% 和文ゴースト処理を行うか
% （|\ruby[no]usejghost|）。
% スイッチ。
%    \begin{macrocode}
\newif\ifpxrr@jghost \pxrr@jghostfalse
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\ifpxrr@aghost}
% 欧文ゴースト処理を行うか
% （|\ruby[no]useaghost|）。
% スイッチ。
%    \begin{macrocode}
\newif\ifpxrr@aghost \pxrr@aghostfalse
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@inter@gap}
% ルビと親文字の間の空き
% （|\rubyintergap|）。
% 実数値マクロ。
%    \begin{macrocode}
\def\pxrr@inter@gap{0}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\ifpxrr@edge@adjust}
% 行頭・行末での突出の自動補正を行うか
% （|\ruby[no]adjustatlineedge|）。
% スイッチ。
%    \begin{macrocode}
\newif\ifpxrr@edge@adjust \pxrr@edge@adjustfalse
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\ifpxrr@break@jukugo}
% 熟語ルビで中間の行分割を許すか
% （|\ruby[no]breakjukugo|）。
% スイッチ。
%    \begin{macrocode}
\newif\ifpxrr@break@jukugo \pxrr@break@jukugofalse
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\ifpxrr@safe@mode}
% 安全モードであるか。
% （|\ruby[no]safemode|）。
% スイッチ。
%    \begin{macrocode}
\newif\ifpxrr@safe@mode \pxrr@safe@modefalse
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\ifpxrr@d@bprotr}
% \begin{macro}{\ifpxrr@d@aprotr}
% 突出を許すか否か。
% |\rubysetup| の\jmeta{前設定}／\jmeta{後設定}に由来する。
% スイッチ。
%    \begin{macrocode}
\newif\ifpxrr@d@bprotr \pxrr@d@bprotrtrue
\newif\ifpxrr@d@aprotr \pxrr@d@aprotrtrue
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\pxrr@d@bintr}
% \begin{macro}{\pxrr@d@aintr}
% 進入量。
% |\rubysetup| の\jmeta{前設定}／\jmeta{後設定}に由来する。
% |\pxrr@XXX@intr| または空（進入無し）に展開されるマクロ。
%    \begin{macrocode}
\def\pxrr@d@bintr{}
\def\pxrr@d@aintr{}
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\pxrr@d@athead}
% 肩付き／中付きの設定。
% |\rubysetup| の |c|／|h|／|H| の設定。
% 0 = 中付き（|c|）；
% 1 = 肩付き（|h|）；2 = 拡張肩付き（|H|）。
% 整数定数。
%    \begin{macrocode}
\chardef\pxrr@d@athead=0
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@d@mode}
% モノルビ（|m|）・グループルビ（|g|）・熟語ルビ（|j|）
% のいずれか。
% |\rubysetup| の設定値。
% オプション文字への暗黙の（|\let| された）文字トークン。
%    \begin{macrocode}
\let\pxrr@d@mode=j
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@d@side}
% ルビを親文字の上下のどちらに付すか。
% 0 = 上側；1 = 下側。
% |\rubysetup| の |P|／|S| の設定。
% 整数定数。
%    \begin{macrocode}
\chardef\pxrr@d@side=0
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@d@evensp}
% 親文字列均等割りの設定。
% 0 = 無効；1 = 有効。
% |\rubysetup| の |e|／|E| の設定。
% 整数定数。
%    \begin{macrocode}
\chardef\pxrr@d@evensp=1
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@d@fullsize}
% 小書き文字変換の設定。
% 0 = 無効；1 = 有効。
% |\rubysetup| の |f|／|F| の設定。
% 整数定数。
%    \begin{macrocode}
\chardef\pxrr@d@fullsize=0
%    \end{macrocode}
% \end{macro}
%
% \subsubsection{呼出時パラメタ・変数}
%
% 一般的に、特定のルビ・圏点命令の呼出に固有である
% （つまりその内側にネストされたルビ・圏点命令に継承すべきでない）
% パラメタは、呼出時の値を別に保持しておくべきである。
%
% \begin{macro}{\ifpxrr@bprotr}
% \begin{macro}{\ifpxrr@aprotr}
% 突出を許すか否か。
% |\ruby| の\jmeta{前設定}／\jmeta{後設定}に由来する。
% スイッチ。
%    \begin{macrocode}
\newif\ifpxrr@bprotr \pxrr@bprotrfalse
\newif\ifpxrr@aprotr \pxrr@aprotrfalse
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\pxrr@bintr}
% \begin{macro}{\pxrr@aintr}
% 進入量。
% |\ruby| の\jmeta{前設定}／\jmeta{後設定}に由来する。
% 寸法値に展開されるマクロ。
%    \begin{macrocode}
\def\pxrr@bintr{}
\def\pxrr@aintr{}
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\pxrr@bscomp}
% \begin{macro}{\pxrr@ascomp}
% 空き補正設定。
% |\ruby| の |:| 指定に由来する。
% 暗黙の文字トークン（無指定は |\relax|）。
% \Note 既定値設定（|\rubysetup|）でこれに対応するものはない。
%    \begin{macrocode}
\let\pxrr@bscomp\relax
\let\pxrr@ascomp\relax
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\ifpxrr@bnobr}
% \begin{macro}{\ifpxrr@anobr}
% ルビ付文字の直前／直後で行分割を許すか。
% |\ruby| の |*| 指定に由来する。
% スイッチ。
% \Note 既定値設定（|\rubysetup|）でこれに対応するものはない。
%    \begin{macrocode}
\newif\ifpxrr@bnobr \pxrr@bnobrfalse
\newif\ifpxrr@anobr \pxrr@anobrfalse
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\ifpxrr@bfintr}
% \begin{macro}{\ifpxrr@afintr}
% 段落冒頭／末尾で進入を許可するか。
% |\ruby| の |!| 指定に由来する。
% スイッチ。
% \Note 既定値設定（|\rubysetup|）でこれに対応するものはない。
%    \begin{macrocode}
\newif\ifpxrr@bfintr \pxrr@bfintrfalse
\newif\ifpxrr@afintr \pxrr@afintrfalse
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\pxrr@athead}
% 肩付き／中付きの設定。
% |\ruby| の |c|／|h|／|H| の設定。
% 値の意味は |\pxrr@d@athead| と同じ。
% 整数定数。
%    \begin{macrocode}
\chardef\pxrr@athead=0
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\ifpxrr@athead@iven}
% 肩付き／中付きの設定が明示的であるか。
% スイッチ。
%    \begin{macrocode}
\newif\ifpxrr@athead@given \pxrr@athead@givenfalse
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@mode}
% モノルビ（|m|）・グループルビ（|g|）・熟語ルビ（|j|）のいずれか。
% |\ruby| のオプションの設定値。
% オプション文字への暗黙文字トークン。
%    \begin{macrocode}
\let\pxrr@mode=\@undefined
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\ifpxrr@mode@given}
% 基本モードの設定が明示的であるか。
% スイッチ。
%    \begin{macrocode}
\newif\ifpxrr@mode@given \pxrr@mode@givenfalse
\newif\ifpxrr@afintr \pxrr@afintrfalse
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\ifpxrr@abody}
% ルビが |\aruby|（欧文親文字用）であるか。
% スイッチ。
%    \begin{macrocode}
\newif\ifpxrr@abody
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@side}
% ルビを親文字の上下のどちらに付すか。
% 0 = 上側；1 = 下側；2 = 両側。
% |\ruby| の |P|／|S| が 0／1 に対応し、
% |\truby| では 2 が使用される。
% 整数定数。
%    \begin{macrocode}
\chardef\pxrr@side=0
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@evensp}
% 親文字列均等割りの設定。
% 0 = 無効；1 = 有効。
% |\ruby| の |e|／|E| の設定。
% 整数定数。
%    \begin{macrocode}
\chardef\pxrr@evensp=1
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@revensp}
% ルビ文字列均等割りの設定。
% 0 = 無効；1 = 有効。
% 整数定数。
% \Note 通常は有効だが、安全モードでは無効になる。
%    \begin{macrocode}
\chardef\pxrr@revensp=1
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@fullsize}
% 小書き文字変換の設定。
% 0 = 無効；1 = 有効。
% |\ruby| の |f|／|F| の設定。
% 整数定数。
%    \begin{macrocode}
\chardef\pxrr@fullsize=1
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@c@ruby@font}
% \begin{macro}{\pxrr@c@size@ratio}
% \begin{macro}{\pxrr@c@inter@gap}
% 以下は“オプションで指定する”以外のパラメタに対応するもの。
%    \begin{macrocode}
\let\pxrr@c@ruby@font\@undefined
\let\pxrr@c@size@ratio\@undefined
\let\pxrr@c@inter@gap\@undefined
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \subsection{その他の変数}
%
% \begin{macro}{\pxrr@body@list}
% 親文字列のために使うリスト。
%    \begin{macrocode}
\let\pxrr@body@list\@undefined
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@body@count}
% |\pxrr@body@list| の長さ。
% 整数値マクロ。
%    \begin{macrocode}
\let\pxrr@body@count\@undefined
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@ruby@list}
% ルビ文字列のために使うリスト。
%    \begin{macrocode}
\let\pxrr@ruby@list\@undefined
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@ruby@count}
% |\pxrr@ruby@list| の長さ。
% 整数値マクロ。
%    \begin{macrocode}
\let\pxrr@ruby@count\@undefined
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@sruby@list}
% 2つ目のルビ文字列のために使うリスト。
%    \begin{macrocode}
\let\pxrr@sruby@list\@undefined
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@sruby@count}
% |\pxrr@sruby@list| の長さ。
% 整数値マクロ。
%    \begin{macrocode}
\let\pxrr@sruby@count\@undefined
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@whole@list}
% 親文字とルビのリストをzipしたリスト。
%    \begin{macrocode}
\let\pxrr@whole@list\@undefined
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@bspace}
% ルビが親文字から前側にはみだす長さ。
% 寸法値マクロ。
%    \begin{macrocode}
\let\pxrr@bspace\@undefined
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@aspace}
% ルビが親文字から後側にはみだす長さ。
% 寸法値マクロ。
%    \begin{macrocode}
\let\pxrr@aspace\@undefined
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@natwd}
% |\pxrr@evenspace@int| のパラメタ。
% 寸法値マクロ。
%    \begin{macrocode}
\let\pxrr@natwd\@undefined
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@all@input}
% 両側ルビの処理で使われる一時変数。
%    \begin{macrocode}
\let\pxrr@all@input\@undefined
%    \end{macrocode}
% \end{macro}
%
% \subsection{補助手続}
%
% \subsubsection{雑多な定義}
%
% \begin{macro}{\ifpxrr@ok}
% 汎用スイッチ。
%    \begin{macrocode}
\newif\ifpxrr@ok
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@cnta}
% 汎用の整数レジスタ。
%    \begin{macrocode}
\newcount\pxrr@cnta
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@cntr}
% 結果を格納する整数レジスタ。
%    \begin{macrocode}
\newcount\pxrr@cntr
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@dima}
% 汎用の寸法レジスタ。
%    \begin{macrocode}
\newdimen\pxrr@dima
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@boxa}
% \begin{macro}{\pxrr@boxb}
% 汎用のボックスレジスタ。
%    \begin{macrocode}
\newbox\pxrr@boxa
\newbox\pxrr@boxb
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\pxrr@boxr}
% 結果を格納するボックスレジスタ。
%    \begin{macrocode}
\newbox\pxrr@boxr
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@token}
% |\futurelet| 用の一時変数。
% \Note if-トークンなどの“危険”なトークンになりうるので使い回さない。
%    \begin{macrocode}
\let\pxrr@token\relax
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@zero}
% 整数定数のゼロ。
% |\z@| と異なり、「単位付寸法」の係数として使用可能。
%    \begin{macrocode}
\chardef\pxrr@zero=0
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@zeropt}
% 「|0pt|」という文字列。
% 寸法値マクロへの代入に用いる。
%    \begin{macrocode}
\def\pxrr@zeropt{0pt}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@hfilx}
% |\pxrr@hfilx{|\jmeta{実数}|}|\Means
% 「\jmeta{実数}\texttt{fil}」のグル―を置く。
%    \begin{macrocode}
\def\pxrr@hfilx#1{%
  \hskip\z@\@plus #1fil\relax
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@res}
% 結果を格納するマクロ。
%    \begin{macrocode}
\let\pxrr@res\@empty
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@ifx}
% |\pxrr@ifx{|\jmeta{引数}|}|\jmeta{真}|}{|\jmeta{偽}|}|\Means
% |\ifx|\jmeta{引数} を行うテスト。
%    \begin{macrocode}
\def\pxrr@ifx#1{%
  \ifx#1\expandafter\@firstoftwo
  \else\expandafter\@secondoftwo
  \fi
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@cond}
% |\pxrr@cond\ifXXX...\fi{|\jmeta{真}|}{|\jmeta{偽}|}|\Means
% 一般の{\TeX}のif文 |\ifXXX...| を行うテスト。
% \Note |\fi| を付けているのは、if-不均衡を避けるため。
%    \begin{macrocode}
\@gobbletwo\if\if \def\pxrr@cond#1\fi{%
  #1\expandafter\@firstoftwo
  \else\expandafter\@secondoftwo
  \fi
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@cslet}
% \begin{macro}{\pxrr@letcs}
% \begin{macro}{\pxrr@csletcs}
% |\pxrr@cslet{NAMEa}\CSb|\Means
% |\NAMEa| に |\CSb| を |\let| する。
% 
% |\pxrr@letcs\CSa{NAMEb}|\Means
% |\CSa| に |\NAMEb| を |\let| する。
% 
% |\pxrr@csletcs{NAMEa}{NAMEb}|\Means
% |\NAMEa| に |\NAMEb| を |\let| する。
%    \begin{macrocode}
\def\pxrr@cslet#1{%
  \expandafter\let\csname#1\endcsname
}
\def\pxrr@letcs#1#2{%
  \expandafter\let\expandafter#1\csname#2\endcsname
}
\def\pxrr@csletcs#1#2{%
  \expandafter\let\csname#1\expandafter\endcsname
   \csname#2\endcsname
}
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\pxrr@setok}
% |\pxrr@setok{|\jmeta{テスト}|}|\Means
% テストの結果を |\ifpxrr@ok| に返す。
%    \begin{macrocode}
\def\pxrr@setok#1{%
  #1{\pxrr@oktrue}{\pxrr@okfalse}%
}
%    \end{macrocode}
% \end{macro}
% \begin{macro}{\pxrr@appto}
% |\pxrr@appto\CS{|\jmeta{テキスト}|}|\Means
% 無引数マクロの置換テキストに追加する。
%    \begin{macrocode}
\def\pxrr@appto#1#2{%
  \expandafter\def\expandafter#1\expandafter{#1#2}%
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@nil}
% \begin{macro}{\pxrr@end}
% ユニークトークン。
%    \begin{macrocode}
\def\pxrr@nil{\noexpand\pxrr@nil}
\def\pxrr@end{\noexpand\pxrr@end}
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\pxrr@without@macro@trace}
% |\pxrr@without@macro@trace{|\jmeta{テキスト}|}|\Means
% マクロ展開のトレースを無効にした状態で\jmeta{テキスト}を実行する。
%    \begin{macrocode}
\def\pxrr@without@macro@trace#1{%
  \chardef\pxrr@tracingmacros@save=\tracingmacros
  \tracingmacros\z@
  #1%
  \tracingmacros\pxrr@tracingmacros@save
}
\chardef\pxrr@tracingmacros@save=0
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@hbox}
% \begin{macro}{\pxrr@hbox@to}
% color パッケージ対応の |\hbox| と |\hb@xt@|（= |\hbox| |to|）。
%    \begin{macrocode}
\def\pxrr@hbox#1{%
  \hbox{%
    \color@begingroup
      #1%
    \color@endgroup
  }%
}
\def\pxrr@hbox@to#1#{%
  \pxrr@hbox@to@a{#1}%
}
\def\pxrr@hbox@to@a#1#2{%
  \hbox to#1{%
    \color@begingroup
      #2%
    \color@endgroup
  }%
}
%    \end{macrocode}
% color パッケージ不使用の場合は、
% 本来の |\hbox| と |\hb@xt@| に戻しておく。
% これと同期して |\pxrr@takeout@any@protr| の動作も変更する。
%    \begin{macrocode}
\AtBeginDocument{%
  \ifx\color@begingroup\relax
    \ifx\color@endgroup\relax
      \let\pxrr@hbox\hbox
      \let\pxrr@hbox@to\hb@xt@
      \let\pxrr@takeout@any@protr\pxrr@takeout@any@protr@nocolor
    \fi
  \fi
}
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \subsubsection{数値計算}
%
% \begin{macro}{\pxrr@invscale}
% |\pxrr@invscale{|\jmeta{寸法レジスタ}|}{|\jmeta{実数}|}|\Means
% 現在の\jmeta{寸法レジスタ}の値を\jmeta{実数}で
% 除算した値に更新する。
% すなわち、\jmeta{寸法レジスタ}|=|\jmeta{実数}^^A
% \jmeta{寸法レジスタ}の逆の演算を行う。
%    \begin{macrocode}
\mathchardef\pxrr@invscale@ca=259
\def\pxrr@invscale#1#2{%
  \begingroup
    \@tempdima=#1\relax
    \@tempdimb#2\p@\relax
    \@tempcnta\@tempdima
    \multiply\@tempcnta\@cclvi
    \divide\@tempcnta\@tempdimb
    \multiply\@tempcnta\@cclvi
    \@tempcntb\p@
    \divide\@tempcntb\@tempdimb
    \advance\@tempcnta-\@tempcntb
    \advance\@tempcnta-\tw@
    \@tempdimb\@tempcnta\@ne
    \advance\@tempcnta\@tempcntb
    \advance\@tempcnta\@tempcntb
    \advance\@tempcnta\pxrr@invscale@ca
    \@tempdimc\@tempcnta\@ne
    \@whiledim\@tempdimb<\@tempdimc\do{%
      \@tempcntb\@tempdimb
      \advance\@tempcntb\@tempdimc
      \advance\@tempcntb\@ne
      \divide\@tempcntb\tw@
      \ifdim #2\@tempcntb>\@tempdima
        \advance\@tempcntb\m@ne
        \@tempdimc=\@tempcntb\@ne
      \else
        \@tempdimb=\@tempcntb\@ne
      \fi}%
    \xdef\pxrr@gtempa{\the\@tempdimb}%
  \endgroup
  #1=\pxrr@gtempa\relax
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@interpolate}
% |\pxrr@interpolate{|\jmeta{入力単位}|}|\pad^^A
% |{|\jmeta{出力単位}|}|\pad^^A
% |{|\jmeta{寸法レジスタ}|}|\pad^^A
% |{(|$\mathrm{X}_1$|,|$\mathrm{Y}_1$|)|\pad^^A
% |(|$\mathrm{X}_2$|,|$\mathrm{Y}_2$|)|$\cdots$\pad^^A
% |(|$\mathrm{X}_n$|,|$\mathrm{Y}_n$|)}|\Means
% 線形補間を行う。
% すなわち、明示値
% \[
%   f(0\,\mathrm{pt}) = 0\,\mathrm{pt},\ 
%   f(\mathrm{X}_1\,\mathrm{iu})=\mathrm{Y}_1\,\mathrm{ou},\ 
%   \ldots,\ 
%   f(\mathrm{X}_n\,\mathrm{iu})=\mathrm{Y}_n\,\mathrm{ou}
% \]
% （ただし\ 
% $(0,\mathrm{pt}< \mathrm{X}_1\,\mathrm{iu} < \cdots
% < \mathrm{X}_n\,\mathrm{iu})$；
% ここで $\mathrm{iu}$ は\jmeta{入力単位}、
% $\mathrm{ou}$ は\jmeta{出力単位}に指定されたもの）
% を線形補間して定義される関数 $f(\cdot)$ について、
% $f(\mbox{\jmeta{寸法}})$ の値を\jmeta{寸法レジスタ}に
% 代入する。
% \Note $[0\,\mathrm{pt}, \mathrm{X}_n\,\mathrm{iu}]$ の範囲外では
% 両端の2点による外挿を行う。
%    \begin{macrocode}
\def\pxrr@interpolate#1#2#3#4#5{%
  \edef\pxrr@tempa{#1}%
  \edef\pxrr@tempb{#2}%
  \def\pxrr@tempd{#3}%
  \setlength{\@tempdima}{#4}%
  \edef\pxrr@tempc{(0,0)#5(*,*)}%
  \expandafter\pxrr@interpolate@a\pxrr@tempc\@nil
}
\def\pxrr@interpolate@a(#1,#2)(#3,#4)(#5,#6){%
  \if*#5%
    \def\pxrr@tempc{\pxrr@interpolate@b{#1}{#2}{#3}{#4}}%
  \else\ifdim\@tempdima<#3\pxrr@tempa
    \def\pxrr@tempc{\pxrr@interpolate@b{#1}{#2}{#3}{#4}}%
  \else
    \def\pxrr@tempc{\pxrr@interpolate@a(#3,#4)(#5,#6)}%
  \fi\fi
  \pxrr@tempc
}
\def\pxrr@interpolate@b#1#2#3#4#5\@nil{%
  \@tempdimb=-#1\pxrr@tempa
  \advance\@tempdima\@tempdimb
  \advance\@tempdimb#3\pxrr@tempa
  \edef\pxrr@tempc{\strip@pt\@tempdimb}%
  \pxrr@invscale\@tempdima\pxrr@tempc
  \edef\pxrr@tempc{\strip@pt\@tempdima}%
  \@tempdima=#4\pxrr@tempb
  \@tempdimb=#2\pxrr@tempb
  \advance\@tempdima-\@tempdimb
  \@tempdima=\pxrr@tempc\@tempdima
  \advance\@tempdima\@tempdimb
  \pxrr@tempd=\@tempdima
}
%    \end{macrocode}
% \end{macro}
%
% \subsubsection{リスト分解}
%
% \begin{macro}{\pxrr@decompose}
% |\pxrr@decompose{|\jmeta{要素1}$\cdots$\jmeta{要素n}|}|\Means
% ここで各\jmeta{要素}は単一トークンまたはグループ
% （|{...}| で囲まれたもの）とする。
% この場合、|\pxrr@res| を以下のトークン列に定義する。
% \begin{quote}
% |\pxrr@pre{|\jmeta{要素1}|}\pxrr@inter{|\jmeta{要素2}|}|$\cdots$\\
% |\pxrr@inter{|\jmeta{要素n}|}\pxrr@post|
% \end{quote}
% そして、|\pxrr@cntr| を n に設定する。
% \Note
% \jmeta{要素}に含まれるグルーピングは完全に保存される
% （最外の |{...}| が外れたりしない）。
%    \begin{macrocode}
\def\pxrr@decompose#1{%
  \let\pxrr@res\@empty
  \pxrr@cntr=\z@
  \pxrr@decompose@loopa#1\pxrr@end
}
\def\pxrr@decompose@loopa{%
  \futurelet\pxrr@token\pxrr@decompose@loopb
}
\def\pxrr@decompose@loopb{%
  \pxrr@ifx{\pxrr@token\pxrr@end}{%
    \pxrr@appto\pxrr@res{\pxrr@post}%
  }{%
    \pxrr@setok{\pxrr@ifx{\pxrr@token\bgroup}}%
    \pxrr@decompose@loopc
  }%
}
\def\pxrr@decompose@loopc#1{%
  \ifx\pxrr@res\@empty
    \def\pxrr@res{\pxrr@pre}%
  \else
    \pxrr@appto\pxrr@res{\pxrr@inter}%
  \fi
  \ifpxrr@ok
    \pxrr@appto\pxrr@res{{{#1}}}%
  \else
    \pxrr@appto\pxrr@res{{#1}}%
  \fi
  \advance\pxrr@cntr\@ne
  \pxrr@decompose@loopa
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@decompbar}
% |\pxrr@decompbar{|\jmeta{要素1}\texttt{\vb}$\cdots$^^A
% $\cdots$\texttt{\vb}\jmeta{要素n}|}|\Means
% ただし、各\jmeta{要素}はグルーピングの外の \texttt{\vb} を
% 含まないとする。
% 入力の形式と\jmeta{要素}の構成条件が異なることを除いて、
% |\pxrr@decompose| と同じ動作をする。
%    \begin{macrocode}
\def\pxrr@decompbar#1{%
  \let\pxrr@res\@empty
  \pxrr@cntr=\z@
  \pxrr@decompbar@loopa\pxrr@nil#1|\pxrr@end|%
}
\def\pxrr@decompbar@loopa#1|{%
  \expandafter\pxrr@decompbar@loopb\expandafter{\@gobble#1}%
}
\def\pxrr@decompbar@loopb#1{%
  \pxrr@decompbar@loopc#1\relax\pxrr@nil{#1}%
}
\def\pxrr@decompbar@loopc#1#2\pxrr@nil#3{%
  \pxrr@ifx{#1\pxrr@end}{%
    \pxrr@appto\pxrr@res{\pxrr@post}%
  }{%
    \ifx\pxrr@res\@empty
      \def\pxrr@res{\pxrr@pre}%
    \else
      \pxrr@appto\pxrr@res{\pxrr@inter}%
    \fi
    \pxrr@appto\pxrr@res{{#3}}%
    \advance\pxrr@cntr\@ne
    \pxrr@decompbar@loopa\pxrr@nil
  }%
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@zip@list}
% |\pxrr@zip@list\CSa\CSb|\Means
% |\CSa| と |\CSb| が以下のように展開されるマクロとする：
% \begin{quote}\small
% |\CSa| = |\pxrr@pre{|\jmeta{X1}|}\pxrr@inter{|\jmeta{X2}|}|^^A
% $\cdots$|\pxrr@inter{|\jmeta{Xn}|}\pxrr@post|\\
% |\CSb| = |\pxrr@pre{|\jmeta{Y1}|}\pxrr@inter{|\jmeta{Y2}|}|^^A
% $\cdots$|\pxrr@inter{|\jmeta{Yn}|}\pxrr@post|
% \end{quote}
% この命令は |\pxrr@res| を以下の内容に定義する。
% \begin{quote}\small
% |\pxrr@pre{|\jmeta{X1}|}{|\jmeta{Y1}|}|^^A
% |\pxrr@inter{|\jmeta{X2}|}{|\jmeta{Y2}|}|^^A
% $\cdots$\\
% |\pxrr@inter{|\jmeta{Xn}|}{|\jmeta{Yn}|}|^^A
% |\pxrr@post|
% \end{quote}
%    \begin{macrocode}
\def\pxrr@zip@list#1#2{%
  \let\pxrr@res\@empty
  \let\pxrr@post\relax
  \let\pxrr@tempa#1\pxrr@appto\pxrr@tempa{{}}%
  \let\pxrr@tempb#2\pxrr@appto\pxrr@tempb{{}}%
  \pxrr@zip@list@loopa
}
\def\pxrr@zip@list@loopa{%
  \expandafter\pxrr@zip@list@loopb\pxrr@tempa\pxrr@end
}
\def\pxrr@zip@list@loopb#1#2#3\pxrr@end{%
  \pxrr@ifx{#1\relax}{%
    \pxrr@zip@list@exit
  }{%
    \pxrr@appto\pxrr@res{#1{#2}}%
    \def\pxrr@tempa{#3}%
    \expandafter\pxrr@zip@list@loopc\pxrr@tempb\pxrr@end
  }%
}
\def\pxrr@zip@list@loopc#1#2#3\pxrr@end{%
  \pxrr@ifx{#1\relax}{%
    \pxrr@interror{zip}%
    \pxrr@appto\pxrr@res{{}}%
    \pxrr@zip@list@exit
  }{%
    \pxrr@appto\pxrr@res{{#2}}%
    \def\pxrr@tempb{#3}%
    \pxrr@zip@list@loopa
  }%
}
\def\pxrr@zip@list@exit{%
  \pxrr@appto\pxrr@res{\pxrr@post}%
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@tzip@list}
% |\pxrr@tzip@list\CSa\CSb\CSc|\Means
% |\CSa|、|\CSb|、|\CSc| が以下のように展開されるマクロとする：
% \begin{quote}\small
% |\CSa| = |\pxrr@pre{|\jmeta{X1}|}\pxrr@inter{|\jmeta{X2}|}|^^A
% $\cdots$|\pxrr@inter{|\jmeta{Xn}|}\pxrr@post|\\
% |\CSb| = |\pxrr@pre{|\jmeta{Y1}|}\pxrr@inter{|\jmeta{Y2}|}|^^A
% $\cdots$|\pxrr@inter{|\jmeta{Yn}|}\pxrr@post|\\
% |\CSc| = |\pxrr@pre{|\jmeta{Z1}|}\pxrr@inter{|\jmeta{Z2}|}|^^A
% $\cdots$|\pxrr@inter{|\jmeta{Zn}|}\pxrr@post|
% \end{quote}
% この命令は |\pxrr@res| を以下の内容に定義する。
% \begin{quote}\small
% |\pxrr@pre{|\jmeta{X1}|}{|\jmeta{Y1}|}{|\jmeta{Z1}|}|^^A
% |\pxrr@inter{|\jmeta{X2}|}{|\jmeta{Y2}|}{|\jmeta{Z2}|}|^^A
% $\cdots$\\
% |\pxrr@inter{|\jmeta{Xn}|}{|\jmeta{Yn}|}{|\jmeta{Zn}|}|^^A
% |\pxrr@post|
% \end{quote}
%    \begin{macrocode}
\def\pxrr@tzip@list#1#2#3{%
  \let\pxrr@res\@empty
  \let\pxrr@post\relax
  \let\pxrr@tempa#1\pxrr@appto\pxrr@tempa{{}}%
  \let\pxrr@tempb#2\pxrr@appto\pxrr@tempb{{}}%
  \let\pxrr@tempc#3\pxrr@appto\pxrr@tempc{{}}%
  \pxrr@tzip@list@loopa
}
\def\pxrr@tzip@list@loopa{%
  \expandafter\pxrr@tzip@list@loopb\pxrr@tempa\pxrr@end
}
\def\pxrr@tzip@list@loopb#1#2#3\pxrr@end{%
  \pxrr@ifx{#1\relax}{%
    \pxrr@tzip@list@exit
  }{%
    \pxrr@appto\pxrr@res{#1{#2}}%
    \def\pxrr@tempa{#3}%
    \expandafter\pxrr@tzip@list@loopc\pxrr@tempb\pxrr@end
  }%
}
\def\pxrr@tzip@list@loopc#1#2#3\pxrr@end{%
  \pxrr@ifx{#1\relax}{%
    \pxrr@interror{tzip}%
    \pxrr@appto\pxrr@res{{}}%
    \pxrr@tzip@list@exit
  }{%
    \pxrr@appto\pxrr@res{{#2}}%
    \def\pxrr@tempb{#3}%
    \expandafter\pxrr@tzip@list@loopd\pxrr@tempc\pxrr@end
  }%
}
\def\pxrr@tzip@list@loopd#1#2#3\pxrr@end{%
  \pxrr@ifx{#1\relax}{%
    \pxrr@interror{tzip}%
    \pxrr@appto\pxrr@res{{}}%
    \pxrr@tzip@list@exit
  }{%
    \pxrr@appto\pxrr@res{{#2}}%
    \def\pxrr@tempc{#3}%
    \pxrr@tzip@list@loopa
  }%
}
\def\pxrr@tzip@list@exit{%
  \pxrr@appto\pxrr@res{\pxrr@post}%
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@concat@list}
% |\pxrr@concat@list\CS|\Means
% リストの要素を連結する。
% すなわち、|\CS| が
% \begin{quote}\small
% |\CSa| = |\pxrr@pre{|\jmeta{X1}|}\pxrr@inter{|\jmeta{X2}|}|^^A
% $\cdots$|\pxrr@inter{|\jmeta{Xn}|}\pxrr@post|
% \end{quote}
% の時に、|\pxrr@res| を以下の内容に定義する。
% \begin{quote}\small
% \jmeta{X1}\jmeta{X2}$\cdots$\jmeta{Xn}
% \end{quote}
%    \begin{macrocode}
\def\pxrr@concat@list#1{%
  \let\pxrr@res\@empty
  \def\pxrr@pre##1{%
    \pxrr@appto\pxrr@res{##1}%
  }%
  \let\pxrr@inter\pxrr@pre
  \let\pxrr@post\relax
  #1%
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@unite@group}
% |\pxrr@unite@group\CS|\Means
% リストの要素を連結して1要素のリストに組み直す。
% すなわち、|\CS| が
% \begin{quote}\small
% |\CS| = |\pxrr@pre{|\jmeta{X1}|}\pxrr@inter{|\jmeta{X2}|}|^^A
% $\cdots$|\pxrr@inter{|\jmeta{Xn}|}\pxrr@post|
% \end{quote}
% の時に、|\CS| を以下の内容で置き換える。
% \begin{quote}\small
% |\pxrr@pre{|\jmeta{X1}\jmeta{X2}$\cdots$\jmeta{Xn}|}\pxrr@post|
% \end{quote}
%    \begin{macrocode}
\def\pxrr@unite@group#1{%
  \expandafter\pxrr@concat@list\expandafter{#1}%
  \expandafter\pxrr@unite@group@a\pxrr@res\pxrr@end#1%
}
\def\pxrr@unite@group@a#1\pxrr@end#2{%
  \def#2{\pxrr@pre{#1}\pxrr@post}%
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@zip@single}
% |\pxrr@zip@single\CSa\CSb|\Means
% \begin{quote}\small
% |\CSa| = \jmeta{X}; |\CSb| = \jmeta{Y}
% \end{quote}
% の時に、|\pxrr@res| を以下の内容に定義する。
% \begin{quote}\small
% |\pxrr@pre{|\jmeta{X}|}{|\jmeta{Y}|}\pxrr@post|
% \end{quote}
%    \begin{macrocode}
\def\pxrr@zip@single#1#2{%
  \expandafter\pxrr@zip@single@a\expandafter#1\expandafter{#2}%
}
\def\pxrr@zip@single@a#1{%
  \expandafter\pxrr@zip@single@b\expandafter{#1}%
}
\def\pxrr@zip@single@b#1#2{%
  \def\pxrr@res{\pxrr@pre{#1}{#2}\pxrr@post}%
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@tzip@single}
% |\pxrr@tzip@single\CSa\CSb\CSc|\Means
% \begin{quote}\small
% |\CSa| = \jmeta{X}; |\CSb| = \jmeta{Y}; |\CSc| = \jmeta{Z}
% \end{quote}
% の時に、|\pxrr@res| を以下の内容に定義する。
% \begin{quote}\small
% |\pxrr@pre{|\jmeta{X}|}{|\jmeta{Y}|}{|\jmeta{Z}|}\pxrr@post|
% \end{quote}
%    \begin{macrocode}
\def\pxrr@tzip@single#1#2#3{%
  \expandafter\pxrr@tzip@single@a\expandafter#1\expandafter#2%
   \expandafter{#3}%
}
\def\pxrr@tzip@single@a#1#2{%
  \expandafter\pxrr@tzip@single@b\expandafter#1\expandafter{#2}%
}
\def\pxrr@tzip@single@b#1{%
  \expandafter\pxrr@tzip@single@c\expandafter{#1}%
}
\def\pxrr@tzip@single@c#1#2#3{%
  \def\pxrr@res{\pxrr@pre{#1}{#2}{#3}\pxrr@post}%
}
%    \end{macrocode}
% \end{macro}
%
% \subsection{エンジン依存処理}
%
% この小節のマクロ内で使われる変数。
%    \begin{macrocode}
\let\pxrr@x@tempa\@empty
\let\pxrr@x@tempb\@empty
\let\pxrr@x@gtempa\@empty
\newif\ifpxrr@x@swa
%    \end{macrocode}
%
% \begin{macro}{\pxrr@ifprimitive}
% |\pxrr@ifprimitive\CS{|\jmeta{真}|}{|\jmeta{偽}|}|\Means
% |\CS| の現在の定義が同名のプリミティブであるかをテストする。
%    \begin{macrocode}
\def\pxrr@ifprimitive#1{%
  \edef\pxrr@x@tempa{\string#1}%
  \edef\pxrr@x@tempb{\meaning#1}%
  \ifx\pxrr@x@tempa\pxrr@x@tempb \expandafter\@firstoftwo
  \else \expandafter\@secondoftwo
  \fi
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\ifpxrr@in@ptex}
% エンジンが{\pTeX}系（{\upTeX}系を含む）であるか。
% |\kansuji| のプリミティブテストで判定する。
%    \begin{macrocode}
\pxrr@ifprimitive\kansuji{%
  \pxrr@csletcs{ifpxrr@in@ptex}{iftrue}%
}{%
  \pxrr@csletcs{ifpxrr@in@ptex}{iffalse}%
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\ifpxrr@in@uptex}
% エンジンが{\upTeX}系でありかつ内部漢字コードがUnicodeであるか。
% エンジン判定は |\kchardef| のプリミティブテストで判定する。
% \Note テストするプリミティブを |\enablecjktoken| から |\kchardef| に
% 変更（|\kchardef| は実際に使っている）。
%    \begin{macrocode}
\pxrr@ifprimitive\kchardef{%
  \ifnum\ucs"3000="3000
    \pxrr@csletcs{ifpxrr@in@uptex}{iftrue}%
  \else
    \pxrr@csletcs{ifpxrr@in@uptex}{iffalse}%
  \fi
}{%
  \pxrr@csletcs{ifpxrr@in@uptex}{iffalse}%
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\ifpxrr@in@xetex}
% エンジンが{\XeTeX}系であるか。
% |\XeTeXrevision| のプリミティブテストで判定する。
%    \begin{macrocode}
\pxrr@ifprimitive\XeTeXrevision{%
  \pxrr@csletcs{ifpxrr@in@xetex}{iftrue}%
}{%
  \pxrr@csletcs{ifpxrr@in@xetex}{iffalse}%
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\ifpxrr@in@xecjk}
% \PKN{xeCJK}パッケージが使用されているか。
%    \begin{macrocode}
\@ifpackageloaded{xeCJK}{%
  \pxrr@csletcs{ifpxrr@in@xecjk}{iftrue}%
}{%
  \pxrr@csletcs{ifpxrr@in@xecjk}{iffalse}%
%    \end{macrocode}
% ここで未読込でかつプリアンブル末尾で読み込まれている場合は警告する。
%    \begin{macrocode}
  \AtBeginDocument{%
    \@ifpackageloaded{xeCJK}{%
      \pxrr@warn@load@order{xeCJK}%
    }{}%
  }%
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\ifpxrr@in@luatex}
% エンジンが{\LuaTeX}系であるか。
% |\luatexrevision| のプリミティブテストで判定する。
%    \begin{macrocode}
\pxrr@ifprimitive\luatexrevision{%
  \pxrr@csletcs{ifpxrr@in@luatex}{iftrue}%
}{%
  \pxrr@csletcs{ifpxrr@in@luatex}{iffalse}%
}
%    \end{macrocode}
% \end{macro}
%
% {\LuaTeX}エンジンの場合、本パッケージ用のLuaモジュール |pxrubtica|
% を作成しておく。
%    \begin{macrocode}
\ifpxrr@in@luatex
  \directlua{ pxrubrica = {} }
\fi
%    \end{macrocode}
%
% \begin{macro}{\ifpxrr@in@luatexja}
% \PKN{LuaTeX-ja}パッケージが使用されているか。
%    \begin{macrocode}
\@ifpackageloaded{luatexja-core}{%
  \pxrr@csletcs{ifpxrr@in@luatexja}{iftrue}%
}{%
  \pxrr@csletcs{ifpxrr@in@luatexja}{iffalse}%
  \AtBeginDocument{%
    \@ifpackageloaded{luatexja-core}{%
      \pxrr@warn@load@order{LuaTeX-ja}%
    }{}%
  }%
}
%    \end{macrocode}
% \end{macro}
%
%    \begin{macrocode}
\ifpxrr@in@xetex
\else\ifpxrr@in@luatex
\else\ifpxrr@in@ptex
\else
  \pxrr@ifprimitive\pdftexrevision{%
    \pxrr@warn{%
      The engine in use seems to be pdfTeX,\MessageBreak
      so safe mode is turned on%
    }%
    \AtEndOfPackage{%
      \rubysafemode
    }%
  }
\fi\fi\fi
%    \end{macrocode}
%
% \begin{macro}{\ifpxrr@in@unicode}
% 「和文」内部コードがUnicodeであるか。
%    \begin{macrocode}
\ifpxrr@in@xetex
  \pxrr@csletcs{ifpxrr@in@unicode}{iftrue}%
\else\ifpxrr@in@luatex
  \pxrr@csletcs{ifpxrr@in@unicode}{iftrue}%
\else\ifpxrr@in@uptex
  \pxrr@csletcs{ifpxrr@in@unicode}{iftrue}%
\else
  \pxrr@csletcs{ifpxrr@in@unicode}{iffalse}%
\fi\fi\fi
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@jc}
% 和文の「複合コード」を内部コードに変換する（展開可能）。
% 「複合コード」は
% 「\jmeta{JISコード16進4桁}|:|\jmeta{Unicode\,16進4桁}」
% の形式。
%    \begin{macrocode}
\def\pxrr@jc#1{%
  \pxrr@jc@a#1\pxrr@nil
}
\ifpxrr@in@unicode
  \def\pxrr@jc@a#1:#2\pxrr@nil{%
    "#2\space
  }
\else\ifpxrr@in@ptex
  \def\pxrr@jc@a#1:#2\pxrr@nil{%
    \jis"#1\space\space
  }
\else
  \def\pxrr@jc@a#1:#2\pxrr@nil{%
    `?\space
  }
\fi\fi
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@jchardef}
% 和文用の |\chardef|。
%    \begin{macrocode}
\ifpxrr@in@uptex
  \let\pxrr@jchardef\kchardef
\else
  \let\pxrr@jchardef\chardef
\fi
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@if@in@tate}
% |\pxrr@if@in@tate{|\jmeta{真}|}{|\jmeta{偽}|}|\Means
% 縦組であるか。
%    \begin{macrocode}
\ifpxrr@in@ptex
%    \end{macrocode}
% {p\TeX}系の場合、|\iftdir| プリミティブを利用する。
% \Note |\iftdir| が未定義のときにifが不均衡になるのを防ぐ。
% \Note 本パッケージの処理の範囲では、縦数式組方向は
% 単に「縦組でない」と判定する。
% （|\ifmdir| は数式組方向を判定するプリミティブ。）
%    \begin{macrocode}
  \begingroup \catcode`\|=0
    \gdef\pxrr@if@in@tate{%
      \pxrr@cond{\if
          |iftdir|ifmdir F|else T|fi|else F|fi
          T}\fi
    }
  \endgroup
\else\ifpxrr@in@luatexja
%    \end{macrocode}
% {\LuaTeX-ja}利用の場合、|direction| パラメタを利用する。
% \Note 縦組対応（|\ltj@curtfnt| が定義済）でない古い{\LuaTeX-ja}の
% 場合は常に横組と見なす。
%    \begin{macrocode}
  \ifx\ltj@curtfnt\@undefined
    \let\pxrr@if@in@tate\@secondoftwo
  \else
    \def\pxrr@if@in@tate{%
      \pxrr@cond\ifnum\ltjgetparameter{direction}=\thr@@\fi
    }
  \fi
\else
%    \end{macrocode}
% それ以外は常に横組と見なす。
%    \begin{macrocode}
  \let\pxrr@if@in@tate\@secondoftwo
\fi\fi
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@get@jchar@token}
% |\pxrr@get@jchar@token\CS{|\jmeta{整数}|}|\Means
% 内部文字コードが\jmeta{整数}である和文文字のトークンを得る。
% \Note |.sty|ファイルは完全にASCII文字だけにする方針のため、
% 和文文字が必要な場合はこの補助マクロや |\pxrr@jchardef| を
% 利用して複合コード値から作り出すことになる。
%
% {\pTeX}系の場合。|\kansuji| トリックを利用する。
%    \begin{macrocode}
\ifpxrr@in@ptex
  \def\pxrr@get@jchar@token#1#2{%
    \begingroup
      \kansujichar\@ne=#2\relax
      \xdef\pxrr@x@gtempa{\kansuji\@ne}%
    \endgroup
    \let#1\pxrr@x@gtempa
  }
%    \end{macrocode}
% Unicode対応{\TeX}の場合。|\lowercase| トリックを利用する。
%    \begin{macrocode}
\else\ifpxrr@in@unicode
  \def\pxrr@get@jchar@token#1#2{%
    \begingroup
      \lccode`\?=#2\relax
      \lowercase{\xdef\pxrr@x@gtempa{?}}%
    \endgroup
    \let#1\pxrr@x@gtempa
  }
%    \end{macrocode}
% それ以外ではダミー定義。
%    \begin{macrocode}
\else
  \def\pxrr@get@jchar@token#1#2{%
    \def#1{?}%
  }
\fi\fi
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@zspace}
% 全角空白文字。
% 文字そのものをファイルに含ませたくないのでchardefにする。
%    \begin{macrocode}
\pxrr@jchardef\pxrr@zspace=\pxrr@jc{2121:3000}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@jghost@char}
% 和文ゴースト処理に利用する文字。
% 字形が空であり、かつ一般の漢字と同じ挙動を示す必要がある。
% 実際のゴースト処理では字幅を相殺する処理を入れる為、
% 字幅がゼロである必要はない。
%
% ほとんどの場合、全角空白文字で構わないが、全角空白文字が
% 文字タイプ0でないJFMが使われている場合は問題になる。
%
% {\upTeX}の場合、“拡張符号空間”の文字コードを使う。
% すなわち、文字コード |"113000| の文字はDVIでは文字コード |"3000| と
% 扱われるが、“BMP外”にあるため必ず文字タイプ0になる。
%    \begin{macrocode}
\ifpxrr@in@uptex
  \kchardef\pxrr@jghost@char="113000
%    \end{macrocode}
% {\LuaTeX}-jaの場合。
% 文書先頭で“全角空白文字が使えるか”を検査して、失敗した場合は
% 「和文のU+00A0」を代わりに利用することにする。
%    \begin{macrocode}
\else\ifpxrr@in@luatexja
  \let\pxrr@jghost@char\pxrr@zspace
  \def\pxrr@jghost@check{%
    \begingroup
%      \ltjsetparameter{jaxspmode={\pxrr@zspace,3}}%
%      \ltjsetparameter{xkanjiskip=\p@}%
%      \ltjsetparameter{autoxspacing=false}%
      \setbox\z@\hbox{\char"3001\char"3000}%
%      \ltjsetparameter{autoxspacing=true}%
      \setbox\tw@\hbox{\char"3001\inhibitglue\char"3000}%
      \ifdim\wd\tw@=\wd\z@
        \global\chardef\pxrr@jghost@char@="00A0
        \gdef\pxrr@jghost@char{\ltjjachar\pxrr@jghost@char@}%
      \fi
    \endgroup
  }
  \AtBeginDocument{%
    \pxrr@jghost@check
  }
%    \end{macrocode}
% それ以外の場合は（仕方が無いので）全角空白を用いる。
%    \begin{macrocode}
\else
  \let\pxrr@jghost@char\pxrr@zspace
\fi\fi
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@x@K}
% 適当な漢字（実際は〈一〉）のトークン。
%    \begin{macrocode}
\pxrr@jchardef\pxrr@x@K=\pxrr@jc{306C:4E00}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@get@iiskip}
% |\pxrr@get@iiskip\CS|\Means
% 現在の実効の和文間空白の量を取得する。
%
% {\pTeX}系の場合。
%    \begin{macrocode}
\ifpxrr@in@ptex
  \def\pxrr@get@iiskip#1{%
%    \end{macrocode}
% 以下では |\kanjiskip| 挿入が有効であるかを検査している。
%    \begin{macrocode}
    \pxrr@x@swafalse
    \begingroup
      \inhibitxspcode\pxrr@x@K\thr@@
      \kanjiskip\p@
      \setbox\z@\hbox{\noautospacing\pxrr@x@K\pxrr@x@K}%
      \setbox\tw@\hbox{\pxrr@x@K\pxrr@x@K}%
      \ifdim\wd\tw@>\wd\z@
        \aftergroup\pxrr@x@swatrue
      \fi
    \endgroup
%    \end{macrocode}
% 以下では |\kanjiskip| 挿入が有効ならば |\kanjiskip| の値、
% 無効ならばゼロを返す。
%    \begin{macrocode}
    \edef#1{%
      \ifpxrr@x@swa \the\kanjiskip
      \else \pxrr@zeropt
      \fi
    }%
  }
%    \end{macrocode}
%
% \PKN{LuaTeX-ja}使用の場合。
%    \begin{macrocode}
\else\ifpxrr@in@luatexja
  \def\pxrr@get@iiskip#1{%
    \ifnum\ltjgetparameter{autospacing}=\@ne
      \xdef\pxrr@x@gtempa{\ltjgetparameter{kanjiskip}}%
      \ifdim\glueexpr\pxrr@x@gtempa=\maxdimen
%    \end{macrocode}
% |kanjiskip|パラメタの値が |\maxdimen| の場合、JFMのパラメタに
% より和欧文間空白の量が決定される。
% この値を読み出す公式のインタフェースは存在しないため、
% 実際の組版結果から推定する。
% （値は |\pxrr@x@gtempa| に返る。）
%    \begin{macrocode}
        \pxrr@get@interchar@glue{\pxrr@x@K\pxrr@x@K}%
        \ifdim\glueexpr\pxrr@x@gtempa=\maxdimen
%    \end{macrocode}
% 推定が失敗した場合。
% 警告を（一度だけ）出した上で、値をゼロとして扱う。
%    \begin{macrocode}
          \pxrr@warn@unknown@iiskip
          \global\let\pxrr@x@gtempa\pxrr@zeropt
        \fi
      \fi
      \let#1\pxrr@x@gtempa
    \else
      \let#1\pxrr@zeropt
    \fi
  }
%    \end{macrocode}
% 和文間空白の推定に失敗した場合の警告。
%    \begin{macrocode}
  \def\pxrr@warn@unknown@iiskip{%
    \global\let\pxrr@warn@unknown@iiskip\relax
    \pxrr@warn{Cannot find the kanjiskip value}%
  }
%    \end{macrocode}
% テキスト |#1| を組版した水平ボックスの中にある、
% “文字間グルー”の値を |\pxrr@g@tempa| に返す。
%    \begin{macrocode}
  \def\pxrr@get@interchar@glue#1{%
    \begingroup
      \setbox\z@\hbox{#1}%
%    \end{macrocode}
% Luaの補助関数は所望の値を |\skip0| に返す。
% 失敗時の検出のため、このレジスタを |\maxdimen| で初期化する。
%    \begin{macrocode}
      \skip\z@\maxdimen\relax
      \directlua{%
        pcall(pxrubrica._get_interchar_glue)
      }%
      \xdef\pxrr@x@gtempa{\the\skip\z@}%
    \endgroup
  }
  \begingroup
    \endlinechar=10 \directlua{%
      local node, tex = node, tex
      local id_glyph, id_glue = node.id("glyph"), node.id("glue")
      local id_hlist = node.id("hlist")
%    \end{macrocode}
% |_get_interchar_glue()| は |\box0| の“文字間グルー”の量を
% 取得し、|\skip0| に代入する。
% 実際には、「最初の glyph ノードの後にある最初の glue ノードを
% “文字間グルー”と判断し、その量を読み出す。
%    \begin{macrocode}
      function pxrubrica._get_interchar_glue()
        local c, n = false, tex.box[0].head
        while n do
%    \end{macrocode}
% \Note 2014年頃の{\LuaTeX-ja}では文字の部分がhlistノードになっている。
%    \begin{macrocode}
          if n.id == id_glyph or n.id == id_hlist then
            c = true
          elseif c and n.id == id_glue then
%    \end{macrocode}
% ここでの |n| が“文字間グルー”のノードである。
% \Note 0.85版以降の{\LuaTeX}では、glueノードに直接値（|n.width| 等）
% が入っている。
% それより古い版では、|glue_spec| データを介したインタフェースに
% なっている。
%    \begin{macrocode}
            if n.width then
              tex.setglue(0, n.width, n.stretch, n.shrink,
                  n.stretch_order, n.shrink_order)
            elseif n.spec then
              tex.setskip(0, node.copy(n.spec))
            end
            break
          end
          n = n.next
        end
      end
    }%
  \endgroup%
%    \end{macrocode}
%
% それ以外の場合はゼロとする。
%    \begin{macrocode}
\else
  \def\pxrr@get@iiskip#1{%
    \let#1\pxrr@zeropt
  }
\fi\fi
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@get@iaiskip}
% |\pxrr@get@iaiskip\CS|\Means
% 現在の実効の和欧文間空白の量を取得する。
%
% {\pTeX}系の場合。
%    \begin{macrocode}
\ifpxrr@in@ptex
  \def\pxrr@get@iaiskip#1{%
    \pxrr@x@swafalse
    \begingroup
      \inhibitxspcode\pxrr@x@K\thr@@ \xspcode`X=\thr@@
      \xkanjiskip\p@
      \setbox\z@\hbox{\noautoxspacing\pxrr@x@K X}%
      \setbox\tw@\hbox{\pxrr@x@K X}%
      \ifdim\wd\tw@>\wd\z@
        \aftergroup\pxrr@x@swatrue
      \fi
    \endgroup
    \edef#1{%
      \ifpxrr@x@swa \the\xkanjiskip
      \else \pxrr@zeropt
      \fi
    }%
  }
%    \end{macrocode}
%
% \PKN{LuaTeX-ja}使用の場合。
% 処理の流れは和文間空白の場合と同じ。
%    \begin{macrocode}
\else\ifpxrr@in@luatexja
  \def\pxrr@get@iaiskip#1{%
    \ifnum\ltjgetparameter{autoxspacing}=\@ne
      \xdef\pxrr@x@gtempa{\ltjgetparameter{xkanjiskip}}%
      \ifdim\glueexpr\pxrr@x@gtempa=\maxdimen
%    \end{macrocode}
% 判定用のボックスは欧文・和文の組とする。
%    \begin{macrocode}
        \pxrr@get@interchar@glue{A\pxrr@x@K}%
        \ifdim\glueexpr\pxrr@x@gtempa=\maxdimen
          \pxrr@warn@unknown@iaiskip
          \global\let\pxrr@x@gtempa\pxrr@zeropt
        \fi
      \fi
      \let#1\pxrr@x@gtempa
    \else
      \let#1\pxrr@zeropt
    \fi
  }
%    \end{macrocode}
% 和欧文間空白の推定に失敗した場合の警告。
%    \begin{macrocode}
  \def\pxrr@warn@unknown@iaiskip{%
    \global\let\pxrr@warn@unknown@iaiskip\relax
    \pxrr@warn{Cannot find the xkanjiskip value}%
  }
%    \end{macrocode}
%
% それ以外の場合は実際の組版結果から判断する。
%    \begin{macrocode}
\else
  \def\pxrr@get@iaiskip#1{%
    \begingroup
      \setbox\z@\hbox{M\pxrr@x@K}%
      \setbox\tw@\hbox{M\vrule\@width\z@\relax\pxrr@x@K}%
      \@tempdima\wd\z@ \advance\@tempdima-\wd\tw@
      \@tempdimb\@tempdima \divide\@tempdimb\thr@@
      \xdef\pxrr@x@gtempa{\the\@tempdima\space minus \the\@tempdimb}%
    \endgroup
    \let#1=\pxrr@x@gtempa
  }%
\fi\fi
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@get@zwidth}
% |\pxrr@get@zwidth\CS|\Means
% 現在の和文フォントの全角幅を取得する。
%
% {\pTeX}の場合、|1zw| でよい。
%    \begin{macrocode}
\ifpxrr@in@ptex
  \def\pxrr@get@zwidth#1{%
    \@tempdima=1zw\relax
    \edef#1{\the\@tempdima}%
  }
%    \end{macrocode}
%
% |\zw| が定義されている場合は |1\zw| とする。
%    \begin{macrocode}
\else\if\ifx\zw\@undefined T\else F\fi F% if defined
  \def\pxrr@get@zwidth#1{%
    \@tempdima=1\zw\relax
    \edef#1{\the\@tempdima}%
  }
%    \end{macrocode}
%
% |\jsZw| が定義されている場合は |1\jsZw| とする。
%    \begin{macrocode}
\else\if\ifx\jsZw\@undefined T\else F\fi F% if defined
  \def\pxrr@get@zwidth#1{%
    \@tempdima=1\jsZw\relax
    \edef#1{\the\@tempdima}%
  }
%    \end{macrocode}
%
% それ以外で、|\pxrr@x@K| が有効な場合は実際の組版結果から判断する。
%    \begin{macrocode}
\else\ifnum\pxrr@x@K>\@cclv
  \def\pxrr@get@zwidth#1{%
    \setbox\tw@\hbox{\pxrr@x@K}%
    \@tempdima\wd\tw@
    \ifdim\@tempdima>\z@\else \@tempdima\f@size\p@ \fi
    \edef#1{\the\@tempdima}%
  }
%    \end{macrocode}
%
% それ以外の場合は要求サイズと等しいとする。
%    \begin{macrocode}
\else
  \def\pxrr@get@zwidth#1{%
    \@tempdima\f@size\p@\relax
    \edef#1{\the\@tempdima}%
  }
\fi\fi\fi\fi
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@get@prebreakpenalty}
% |\pxrr@get@prebreakpenalty\CS{|\jmeta{文字コード}|}|\Means
% 文字の後禁則ペナルティ値を整数レジスタに代入する。
%
% {\pTeX}の場合、|\prebreakpenalty| を使う。
%    \begin{macrocode}
\ifpxrr@in@ptex
  \def\pxrr@get@prebreakpenalty#1#2{%
    #1=\prebreakpenalty#2\relax
  }
%    \end{macrocode}
%
% \PKN{LuaTeX-ja}使用時は、prebreakpenalty プロパティを読み出す。
%    \begin{macrocode}
\else\ifpxrr@in@luatexja
  \def\pxrr@get@prebreakpenalty#1#2{%
    #1=\ltjgetparameter{prebreakpenalty}{#2}\relax
  }
%    \end{macrocode}
%
% それ以外の場合はゼロとして扱う。
%    \begin{macrocode}
\else
  \def\pxrr@get@prebreakpenalty#1#2{%
    #1=\z@
  }
\fi\fi
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@get@postbreakpenalty}
% |\pxrr@get@postbreakpenalty\CS{|\jmeta{文字コード}|}|\Means
% 文字の前禁則ペナルティ値を整数レジスタに代入する。
%
% {\pTeX}の場合、|\postbreakpenalty| を使う。
%    \begin{macrocode}
\ifpxrr@in@ptex
  \def\pxrr@get@postbreakpenalty#1#2{%
    #1=\postbreakpenalty#2\relax
  }
%    \end{macrocode}
%
% \PKN{LuaTeX-ja}使用時は、postbreakpenalty プロパティを読み出す。
%    \begin{macrocode}
\else\ifpxrr@in@luatexja
  \def\pxrr@get@postbreakpenalty#1#2{%
    #1=\ltjgetparameter{postbreakpenalty}{#2}\relax
  }
%    \end{macrocode}
%
% それ以外の場合はゼロとして扱う。
%    \begin{macrocode}
\else
  \def\pxrr@get@postbreakpenalty#1#2{%
    #1=\z@
  }
\fi\fi
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@check@punct@char}
% |\pxrr@check@punct@char{|\jmeta{文字コード}|}{|\jmeta{和文フラグ}|}|\Means
% 指定の文字コードの文字が“約物であるか”を調べて、
% 結果を |\ifpxrr@ok| に返す。
% \jmeta{和文フラグ}は“対象が{\pTeX}の和文である”場合に1、
% それ以外は0。
%
% {\pTeX}の場合、欧文なら |\xspcode|、和文なら |\inhibitxspcode| の
% 値を見て、それが3以外なら約物と見なす。
%    \begin{macrocode}
\ifpxrr@in@ptex
  \def\pxrr@check@punct@char#1#2{%
    \pxrr@okfalse
    \ifcase#2\relax
      \ifnum\xspcode#1=\thr@@\else
        \pxrr@oktrue
      \fi
    \else
      \ifnum\inhibitxspcode#1=\thr@@\else
        \pxrr@oktrue
      \fi
    \fi
  }
%    \end{macrocode}
%
% \PKN{LuaTeX-ja}使用時も基本的に{\pTeX}と同じロジックを使う。
% ただし\PKN{LuaTeX-ja}では「文字トークンの和文と欧文の区別」という
% 概念が存在しないため、\jmeta{和文フラグ}は必ず0となる。
% そして、|\xspcode|／|\inhibitxspcode| に相当するパラメタとしては、
% 欧文用のalxspmodeと和文用のjaxspmodeが一応あるが、
% 実際には和文と欧文の区別はなくこの両者は同義になっている。
% 従って、「jaxspmodeが3以外か」を調べることにする。
%    \begin{macrocode}
\else\ifpxrr@in@luatexja
  \def\pxrr@check@punct@char#1#2{%
    \ifnum\ltjgetparameter{jaxspmode}{#1}=\thr@@
      \pxrr@okfalse
    \else
      \pxrr@oktrue
    \fi
  }
%    \end{macrocode}
%
% それ以外の場合は常に偽として扱う。
%    \begin{macrocode}
\else
  \def\pxrr@check@punct@char#1#2{%
    \pxrr@okfalse
  }
\fi\fi
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@force@nonpunct@achar}
% |\pxrr@force@nonpunct@achar{|\jmeta{文字コード}|}|\Means
% 指定の文字コードの欧文文字を“約物でない”ものと扱う。
% “約物である”の意味は |\pxrr@check@punct@char| の場合と同じ。
%
% {\pTeX}の場合。
%    \begin{macrocode}
\ifpxrr@in@ptex
  \def\pxrr@force@nonpunct@achar#1{%
    \global\xspcode#1=\thr@@
  }
%    \end{macrocode}
% \PKN{LuaTeX-ja}使用の場合。
%    \begin{macrocode}
\else\ifpxrr@in@luatexja
  \def\pxrr@force@nonpunct@achar#1{%
    \ltjglobalsetparameter{jaxspmode={#1,3}}%
  }
%    \end{macrocode}
% それ以外の場合は何もしない。
%    \begin{macrocode}
\else
  \def\pxrr@force@nonpunct@achar#1{}
\fi\fi
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@inhibitglue}
% |\inhibitglue| が定義されているなら実行する。
%    \begin{macrocode}
\ifx\inhibitglue\@undefined
  \let\pxrr@inhibitglue\relax
\else
  \let\pxrr@inhibitglue\inhibitglue
\fi
%    \end{macrocode}
% \end{macro}
%
% \subsection{パラメタ設定公開命令}
%
% \begin{macro}{\ifpxrr@in@setup}
% |\pxrr@parse@option| が |\rubysetup| の中で呼ばれたか。
% 真の場合は警告処理を行わない。
%    \begin{macrocode}
\newif\ifpxrr@in@setup \pxrr@in@setupfalse
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\rubysetup}
% |\pxrr@parse@option| で解析した後、設定値を全般設定に
% コピーする。
%    \begin{macrocode}
\newcommand*\rubysetup[1]{%
  \pxrr@in@setuptrue
  \pxrr@fatal@errorfalse
  \pxrr@parse@option{#1}%
  \ifpxrr@fatal@error\else
    \pxrr@csletcs{ifpxrr@d@bprotr}{ifpxrr@bprotr}%
    \pxrr@csletcs{ifpxrr@d@aprotr}{ifpxrr@aprotr}%
    \let\pxrr@d@bintr\pxrr@bintr@
    \let\pxrr@d@aintr\pxrr@aintr@
    \let\pxrr@d@athead\pxrr@athead
    \let\pxrr@d@mode\pxrr@mode
    \let\pxrr@d@side\pxrr@side
    \let\pxrr@d@evensp\pxrr@evensp
    \let\pxrr@d@fullsize\pxrr@fullsize
  \fi
%    \end{macrocode}
% |\ifpxrr@in@setup| を偽に戻す。
% ただし |\ifpxrr@fatal@error| は書き換えられたままであることに注意。
%    \begin{macrocode}
  \pxrr@in@setupfalse
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\rubyfontsetup}
% 対応するパラメタを設定する。
%    \begin{macrocode}
\newcommand*\rubyfontsetup{}
\def\rubyfontsetup#{%
  \def\pxrr@ruby@font
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\rubybigintrusion}
% \begin{macro}{\rubysmallintrusion}
% \begin{macro}{\rubymaxmargin}
% \begin{macro}{\rubyintergap}
% \begin{macro}{\rubysizeratio}
% 対応するパラメタを設定する。
%    \begin{macrocode}
\newcommand*\rubybigintrusion[1]{%
  \edef\pxrr@big@intr{#1}%
}
\newcommand*\rubysmallintrusion[1]{%
  \edef\pxrr@small@intr{#1}%
}
\newcommand*\rubymaxmargin[1]{%
  \edef\pxrr@maxmargin{#1}%
}
\newcommand*\rubyintergap[1]{%
  \edef\pxrr@inter@gap{#1}%
}
\newcommand*\rubysizeratio[1]{%
  \edef\pxrr@size@ratio{#1}%
}
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\rubyusejghost}
% \begin{macro}{\rubynousejghost}
% 対応するスイッチを設定する。
%    \begin{macrocode}
\newcommand*\rubyusejghost{%
  \pxrr@jghosttrue
}
\newcommand*\rubynousejghost{%
  \pxrr@jghostfalse
}
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\rubyuseaghost}
% \begin{macro}{\rubynouseaghost}
% 対応するスイッチを設定する。
%    \begin{macrocode}
\newcommand*\rubyuseaghost{%
  \pxrr@aghosttrue
  \pxrr@setup@aghost
}
\newcommand*\rubynouseaghost{%
  \pxrr@aghostfalse
}
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\rubyadjustatlineedge}
% \begin{macro}{\rubynoadjustatlineedge}
% 対応するスイッチを設定する。
%    \begin{macrocode}
\newcommand*\rubyadjustatlineedge{%
  \pxrr@edge@adjusttrue
}
\newcommand*\rubynoadjustatlineedge{%
  \pxrr@edge@adjustfalse
}
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\rubybreakjukugo}
% \begin{macro}{\rubynobreakjukugo}
% 対応するスイッチを設定する。
%    \begin{macrocode}
\newcommand*\rubybreakjukugo{%
  \pxrr@break@jukugotrue
}
\newcommand*\rubynobreakjukugo{%
  \pxrr@break@jukugofalse
}
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\rubysafemode}
% \begin{macro}{\rubynosafemode}
% 対応するスイッチを設定する。
%    \begin{macrocode}
\newcommand*\rubysafemode{%
  \pxrr@safe@modetrue
}
\newcommand*\rubynosafemode{%
  \pxrr@safe@modefalse
}
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\rubystretchprop}
% \begin{macro}{\rubystretchprophead}
% \begin{macro}{\rubystretchpropend}
% 対応するパラメタを設定する。
%    \begin{macrocode}
\newcommand*\rubystretchprop[3]{%
  \edef\pxrr@sprop@x{#1}%
  \edef\pxrr@sprop@y{#2}%
  \edef\pxrr@sprop@z{#3}%
}
\newcommand*\rubystretchprophead[2]{%
  \edef\pxrr@sprop@hy{#1}%
  \edef\pxrr@sprop@hz{#2}%
}
\newcommand*\rubystretchpropend[2]{%
  \edef\pxrr@sprop@ex{#1}%
  \edef\pxrr@sprop@ey{#2}%
}
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\rubyuseextra}
% 残念ながら今のところは使用不可。
%    \begin{macrocode}
\newcommand*\rubyuseextra[1]{%
  \pxrr@cnta=#1\relax
  \ifnum\pxrr@cnta=\z@
    \chardef\pxrr@extra\pxrr@cnta
  \else
    \pxrr@err@inv@value{\the\pxrr@cnta}%
  \fi
}
%    \end{macrocode}
% \end{macro}
%
% \subsection{ルビオプション解析}
% 
% \begin{macro}{\pxrr@bintr@}
% \begin{macro}{\pxrr@aintr@}
% オプション解析中にのみ使われ、進入の値を |\pxrr@d@?intr|
% と同じ形式で保持する。
% （|\pxrr@?intr| は形式が異なることに注意。）
%    \begin{macrocode}
\let\pxrr@bintr@\@empty
\let\pxrr@aintr@\@empty
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\pxrr@doublebar}
% |\pxrr@parse@option| 中で使用される。
%    \begin{macrocode}
\def\pxrr@doublebar{||}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@parse@option}
% |\pxrr@parse@option{|\jmeta{オプション}|}|\Means
% \jmeta{オプション}を解析し、|\pxrr@athead| や\ 
% |\pxrr@mode| 等のパラメタを設定する。
%    \begin{macrocode}
\def\pxrr@parse@option#1{%
%    \end{macrocode}
% 入力が「\texttt{\vb\vb}」の場合は、「\texttt{\vb-\vb}」
% に置き換える。
%    \begin{macrocode}
  \edef\pxrr@tempa{#1}%
  \ifx\pxrr@tempa\pxrr@doublebar
    \def\pxrr@tempa{|-|}%
  \fi
%    \end{macrocode}
% 各パラメタの値を全般設定のもので初期化する。
%    \begin{macrocode}
  \pxrr@csletcs{ifpxrr@bprotr}{ifpxrr@d@bprotr}%
  \pxrr@csletcs{ifpxrr@aprotr}{ifpxrr@d@aprotr}%
  \let\pxrr@bintr@\pxrr@d@bintr
  \let\pxrr@aintr@\pxrr@d@aintr
  \let\pxrr@athead\pxrr@d@athead
  \let\pxrr@mode\pxrr@d@mode
  \let\pxrr@side\pxrr@d@side
  \let\pxrr@evensp\pxrr@d@evensp
  \let\pxrr@fullsize\pxrr@d@fullsize
%    \end{macrocode}
% 以下のパラメタの既定値は固定されている。
%    \begin{macrocode}
  \let\pxrr@bscomp\relax
  \let\pxrr@ascomp\relax
  \pxrr@bnobrfalse
  \pxrr@anobrfalse
  \pxrr@bfintrfalse
  \pxrr@afintrfalse
%    \end{macrocode}
% 明示フラグを偽にする。
%    \begin{macrocode}
  \pxrr@mode@givenfalse
  \pxrr@athead@givenfalse
%    \end{macrocode}
% 両側ルビの場合、基本モード既定値が |M| に固定される。
%    \begin{macrocode}
  \ifpxrr@truby
    \let\pxrr@mode=M%
  \fi
%    \end{macrocode}
% 有限状態機械を開始させる。
% 入力の末尾に |@| を加えている。
% |\pxrr@end| はエラー時の脱出に用いる。
%    \begin{macrocode}
  \def\pxrr@po@FS{bi}%
  \expandafter\pxrr@parse@option@loop\pxrr@tempa @\pxrr@end
}
%    \end{macrocode}
%
% 有限状態機械のループ。
%    \begin{macrocode}
\def\pxrr@parse@option@loop#1{%
\ifpxrrDebug
\typeout{\pxrr@po@FS/#1[\@nameuse{pxrr@po@C@#1}]}%
\fi
  \csname pxrr@po@PR@#1\endcsname
  \expandafter\ifx\csname pxrr@po@C@#1\endcsname\relax
    \let\pxrr@po@FS\relax
  \else
    \pxrr@letcs\pxrr@po@FS
     {pxrr@po@TR@\pxrr@po@FS @\@nameuse{pxrr@po@C@#1}}%
  \fi
\ifpxrrDebug
\typeout{->\pxrr@po@FS}%
\fi
  \pxrr@ifx{\pxrr@po@FS\relax}{%
    \pxrr@fatal@unx@letter{#1}%
    \pxrr@parse@option@exit
  }{%
    \pxrr@parse@option@loop
  }%
}
%    \end{macrocode}
%
% 後処理。
%    \begin{macrocode}
\def\pxrr@parse@option@exit#1\pxrr@end{%
%    \end{macrocode}
% 既定値設定（|\rubysetup|）である場合何もしない。
%    \begin{macrocode}
  \ifpxrr@in@setup\else
%    \end{macrocode}
% 両側ルビ命令の場合は、|\pxrr@side| の値を変更する。
%    \begin{macrocode}
    \ifpxrr@truby
      \chardef\pxrr@side\tw@
    \fi
%    \end{macrocode}
% 整合性検査を行う。
%    \begin{macrocode}
    \pxrr@check@option
%    \end{macrocode}
% |\pxrr@?intr| の値を設定する。
%    \begin{macrocode}
    \@tempdima=\pxrr@ruby@zw\relax
    \@tempdimb=\pxrr@or@zero\pxrr@bintr@\@tempdima
    \edef\pxrr@bintr{\the\@tempdimb}%
    \@tempdimb=\pxrr@or@zero\pxrr@aintr@\@tempdima
    \edef\pxrr@aintr{\the\@tempdimb}%
  \fi
}
%    \end{macrocode}
%
% \begin{macro}{\pxrr@or@zero}
% |\pxrr@or@zero\pxrr@?intr@| とすると、|\pxrr@?intr@| が
% 空の時に代わりにゼロと扱う。
%    \begin{macrocode}
\def\pxrr@or@zero#1{%
  \ifx#1\@empty \pxrr@zero
  \else #1%
  \fi
}
%    \end{macrocode}
% \end{macro}
% 
% 以下はオプション解析の有限状態機械の定義。
%
% 記号のクラスの設定。
%    \begin{macrocode}
\def\pxrr@po@C@@{F}
\@namedef{pxrr@po@C@|}{V}
\@namedef{pxrr@po@C@:}{S}
\@namedef{pxrr@po@C@.}{S}
\@namedef{pxrr@po@C@*}{S}
\@namedef{pxrr@po@C@!}{S}
\@namedef{pxrr@po@C@<}{B}
\@namedef{pxrr@po@C@(}{B}
\@namedef{pxrr@po@C@>}{A}
\@namedef{pxrr@po@C@)}{A}
\@namedef{pxrr@po@C@-}{M}
\def\pxrr@po@C@c{M}
\def\pxrr@po@C@h{M}
\def\pxrr@po@C@H{M}
\def\pxrr@po@C@m{M}
\def\pxrr@po@C@g{M}
\def\pxrr@po@C@j{M}
\def\pxrr@po@C@M{M}
\def\pxrr@po@C@J{M}
\def\pxrr@po@C@P{M}
\def\pxrr@po@C@S{M}
\def\pxrr@po@C@e{M}
\def\pxrr@po@C@E{M}
\def\pxrr@po@C@f{M}
\def\pxrr@po@C@F{M}
%    \end{macrocode}
% 
% 機能プロセス。
%    \begin{macrocode}
\def\pxrr@po@PR@@{%
  \pxrr@parse@option@exit
}
\@namedef{pxrr@po@PR@|}{%
  \csname pxrr@po@PRbar@\pxrr@po@FS\endcsname
}
\def\pxrr@po@PRbar@bi{%
  \def\pxrr@bintr@{}\pxrr@bprotrtrue
}
\def\pxrr@po@PRbar@bb{%
  \pxrr@bprotrfalse
}
\def\pxrr@po@PRbar@bs{%
  \def\pxrr@aintr@{}\pxrr@aprotrtrue
}
\let\pxrr@po@PRbar@mi\pxrr@po@PRbar@bs
\let\pxrr@po@PRbar@as\pxrr@po@PRbar@bs
\let\pxrr@po@PRbar@ai\pxrr@po@PRbar@bs
\def\pxrr@po@PRbar@ab{%
  \pxrr@aprotrfalse
}
\@namedef{pxrr@po@PR@:}{%
  \csname pxrr@po@PRcolon@\pxrr@po@FS\endcsname
}
\def\pxrr@po@PRcolon@bi{%
  \let\pxrr@bscomp=:\relax
}
\let\pxrr@po@PRcolon@bb\pxrr@po@PRcolon@bi
\let\pxrr@po@PRcolon@bs\pxrr@po@PRcolon@bi
\def\pxrr@po@PRcolon@mi{%
  \let\pxrr@ascomp=:\relax
}
\let\pxrr@po@PRcolon@as\pxrr@po@PRcolon@mi
\@namedef{pxrr@po@PR@.}{%
  \csname pxrr@po@PRdot@\pxrr@po@FS\endcsname
}
\def\pxrr@po@PRdot@bi{%
  \let\pxrr@bscomp=.\relax
}
\let\pxrr@po@PRdot@bb\pxrr@po@PRdot@bi
\let\pxrr@po@PRdot@bs\pxrr@po@PRdot@bi
\def\pxrr@po@PRdot@mi{%
  \let\pxrr@ascomp=.\relax
}
\let\pxrr@po@PRdot@as\pxrr@po@PRdot@mi
\@namedef{pxrr@po@PR@*}{%
  \csname pxrr@po@PRstar@\pxrr@po@FS\endcsname
}
\def\pxrr@po@PRstar@bi{%
  \pxrr@bnobrtrue
}
\let\pxrr@po@PRstar@bb\pxrr@po@PRstar@bi
\let\pxrr@po@PRstar@bs\pxrr@po@PRstar@bi
\def\pxrr@po@PRstar@mi{%
  \pxrr@anobrtrue
}
\let\pxrr@po@PRstar@as\pxrr@po@PRstar@mi
\@namedef{pxrr@po@PR@!}{%
  \csname pxrr@po@PRbang@\pxrr@po@FS\endcsname
}
\def\pxrr@po@PRbang@bi{%
  \pxrr@bfintrtrue
}
\let\pxrr@po@PRbang@bb\pxrr@po@PRbang@bi
\let\pxrr@po@PRbang@bs\pxrr@po@PRbang@bi
\def\pxrr@po@PRbang@mi{%
  \pxrr@afintrtrue
}
\let\pxrr@po@PRbang@as\pxrr@po@PRbang@mi
\@namedef{pxrr@po@PR@<}{%
  \def\pxrr@bintr@{\pxrr@big@intr}\pxrr@bprotrtrue
}
\@namedef{pxrr@po@PR@(}{%
  \def\pxrr@bintr@{\pxrr@small@intr}\pxrr@bprotrtrue
}
\@namedef{pxrr@po@PR@>}{%
  \def\pxrr@aintr@{\pxrr@big@intr}\pxrr@aprotrtrue
}
\@namedef{pxrr@po@PR@)}{%
  \def\pxrr@aintr@{\pxrr@small@intr}\pxrr@aprotrtrue
}
\def\pxrr@po@PR@c{%
  \chardef\pxrr@athead\z@
  \pxrr@athead@giventrue
}
\def\pxrr@po@PR@h{%
  \chardef\pxrr@athead\@ne
  \pxrr@athead@giventrue
}
\def\pxrr@po@PR@H{%
  \chardef\pxrr@athead\tw@
  \pxrr@athead@giventrue
}
\def\pxrr@po@PR@m{%
  \let\pxrr@mode=m%
  \pxrr@mode@giventrue
}
\def\pxrr@po@PR@g{%
  \let\pxrr@mode=g%
  \pxrr@mode@giventrue
}
\def\pxrr@po@PR@j{%
  \let\pxrr@mode=j%
  \pxrr@mode@giventrue
}
\def\pxrr@po@PR@M{%
  \let\pxrr@mode=M%
  \pxrr@mode@giventrue
}
\def\pxrr@po@PR@J{%
  \let\pxrr@mode=J%
  \pxrr@mode@giventrue
}
\def\pxrr@po@PR@P{%
  \chardef\pxrr@side\z@
}
\def\pxrr@po@PR@S{%
  \chardef\pxrr@side\@ne
}
\def\pxrr@po@PR@E{%
  \chardef\pxrr@evensp\z@
}
\def\pxrr@po@PR@e{%
  \chardef\pxrr@evensp\@ne
}
\def\pxrr@po@PR@F{%
  \chardef\pxrr@fullsize\z@
}
\def\pxrr@po@PR@f{%
  \chardef\pxrr@fullsize\@ne
}
%    \end{macrocode}
% 
% 遷移表。
%    \begin{macrocode}
\def\pxrr@po@TR@bi@F{fi}
\def\pxrr@po@TR@bb@F{fi}
\def\pxrr@po@TR@bs@F{fi}
\def\pxrr@po@TR@mi@F{fi}
\def\pxrr@po@TR@as@F{fi}
\def\pxrr@po@TR@ai@F{fi}
\def\pxrr@po@TR@ab@F{fi}
\def\pxrr@po@TR@fi@F{fi}
\def\pxrr@po@TR@bi@V{bb}
\def\pxrr@po@TR@bb@V{bs}
\def\pxrr@po@TR@bs@V{ab}
\def\pxrr@po@TR@mi@V{ab}
\def\pxrr@po@TR@as@V{ab}
\def\pxrr@po@TR@ai@V{ab}
\def\pxrr@po@TR@ab@V{fi}
\def\pxrr@po@TR@bi@S{bs}
\def\pxrr@po@TR@bb@S{bs}
\def\pxrr@po@TR@bs@S{bs}
\def\pxrr@po@TR@mi@S{as}
\def\pxrr@po@TR@as@S{as}
\def\pxrr@po@TR@bi@B{bs}
\def\pxrr@po@TR@bi@M{mi}
\def\pxrr@po@TR@bb@M{mi}
\def\pxrr@po@TR@bs@M{mi}
\def\pxrr@po@TR@mi@M{mi}
\def\pxrr@po@TR@bi@A{fi}
\def\pxrr@po@TR@bb@A{fi}
\def\pxrr@po@TR@bs@A{fi}
\def\pxrr@po@TR@mi@A{fi}
\def\pxrr@po@TR@as@A{fi}
\def\pxrr@po@TR@ai@A{fi}
%    \end{macrocode}
% \end{macro}
%
% \subsection{オプション整合性検査}
%
% \begin{macro}{\pxrr@mode@grand}
% 基本モードの“大分類”。
% モノ（|m|）・熟語（|j|）・グループ（|g|）の何れか。
% つまり“選択的”設定の |M|・|J| を |m|・|j| に寄せる。
% \Note 完全展開可能であるが、“先頭完全展開可能”でないことに注意。
%    \begin{macrocode}
\def\pxrr@mode@grand{%
  \if      m\pxrr@mode m%
  \else\if M\pxrr@mode m%
  \else\if j\pxrr@mode j%
  \else\if J\pxrr@mode j%
  \else\if g\pxrr@mode g%
  \else ?%
  \fi\fi\fi\fi\fi
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@check@option}
% |\pxrr@parse@option| の結果であるオプション設定値の整合性を検査し、
% 必要に応じて、致命的エラーを出したり、警告を出して適切な値に
% 変更したりする。
%    \begin{macrocode}
\def\pxrr@check@option{%
%    \end{macrocode}
% 前と後の両方で突出が禁止された場合は致命的エラーとする。
%    \begin{macrocode}
  \ifpxrr@bprotr\else
    \ifpxrr@aprotr\else
      \pxrr@fatal@bad@no@protr
    \fi
  \fi
%    \end{macrocode}
% ゴースト処理有効で進入有りの場合は致命的エラーとする。
%    \begin{macrocode}
  \pxrr@oktrue
  \ifx\pxrr@bintr@\@empty\else
    \pxrr@okfalse
  \fi
  \ifx\pxrr@aintr@\@empty\else
    \pxrr@okfalse
  \fi
  \ifpxrr@ghost\else
    \pxrr@oktrue
  \fi
  \ifpxrr@ok\else
    \pxrr@fatal@bad@intr
  \fi
%    \end{macrocode}
% 欧文ルビではモノルビ（|m|）・熟語ルビ（|j|）は指定不可なので、
% グループルビに変更する。
% この時に明示指定である場合は警告を出す。
%    \begin{macrocode}
  \if g\pxrr@mode\else
    \ifpxrr@abody
      \let\pxrr@mode=g\relax
      \ifpxrr@mode@given
        \pxrr@warn@must@group
      \fi
    \fi
  \fi
%    \end{macrocode}
% 両側ルビでは熟語ルビ（|j|）は指定不可なので、
% グループルビに変更する。
% この時に明示指定である場合は警告を出す。
%    \begin{macrocode}
  \if \pxrr@mode@grand j%
    \ifnum\pxrr@side=\tw@
      \let\pxrr@mode=g\relax
      \ifpxrr@mode@given
        \pxrr@warn@bad@jukugo
      \fi
    \fi
  \fi
%    \end{macrocode}
% 肩付き指定（|h|）に関する検査。
%    \begin{macrocode}
  \ifnum\pxrr@athead>\z@
%    \end{macrocode}
% 横組みでは不可なので中付きに変更する。
%    \begin{macrocode}
    \pxrr@if@in@tate{}{%else
      \chardef\pxrr@athead\z@
    }%
%    \end{macrocode}
% グループルビでは不可なので中付きに変更する。
%    \begin{macrocode}
    \if g\pxrr@mode
      \chardef\pxrr@athead\z@
    \fi
%    \end{macrocode}
% 以上の2つの場合について、明示指定であれば警告を出す。
%    \begin{macrocode}
    \ifnum\pxrr@athead=\z@
      \ifpxrr@athead@given
        \pxrr@warn@bad@athead
      \fi
    \fi
  \fi
%    \end{macrocode}
% 親文字列均等割り抑止（|E|）の再設定（エラー・警告なし）。
%
% 欧文ルビの場合は、均等割りを常に無効にする。
%    \begin{macrocode}
  \ifpxrr@abody
    \chardef\pxrr@evensp\z@
  \fi
%    \end{macrocode}
% グループルビ以外では、均等割りを有効にする。
% （この場合、親文字列は一文字毎に分解されるので、意味はもたない。
% 均等割り抑止の方が特殊な処理なので、通常の処理に合わせる。）
%    \begin{macrocode}
  \if g\pxrr@mode\else
    \chardef\pxrr@evensp\@ne
  \fi
%    \end{macrocode}
% 圏点ルビ同時付加の場合の調整。
%    \begin{macrocode}
    \ifpxrr@combo
      \pxrr@ck@check@option
    \fi
}
%    \end{macrocode}
% \end{macro}
%
% \subsection{フォントサイズ}
%
% \begin{macro}{\pxrr@ruby@fsize}
% ルビ文字の公称サイズ。
% 寸法値マクロ。
% ルビ命令呼出時に |\f@size|（親文字の公称サイズ）
% の |\pxrr@size@ratio| 倍に設定される。
%    \begin{macrocode}
\let\pxrr@ruby@fsize\pxrr@zeropt
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@body@zw}
% \begin{macro}{\pxrr@ruby@zw}
% それぞれ、親文字とルビ文字の全角幅（実際の1\,zwの寸法）。
% 寸法値マクロ。
% {p\TeX}では和文と欧文のバランスを整えるために和文を縮小する
% ことが多く、その場合「全角幅」は「公称サイズ」より小さくなる。
% なお、このパッケージでは漢字の幅が1\,zwであることを想定する。
% これらもルビ命令呼出時に正しい値に設定される。
%    \begin{macrocode}
\let\pxrr@body@zw\pxrr@zeropt
\let\pxrr@ruby@zw\pxrr@zeropt
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\pxrr@ruby@raise}
% ルビ文字に対する垂直方向の移動量。
%    \begin{macrocode}
\let\pxrr@ruby@raise\pxrr@zeropt
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@ruby@lower}
% ルビ文字に対する垂直方向の移動量（下側ルビ）。
%    \begin{macrocode}
\let\pxrr@ruby@lower\pxrr@zeropt
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@htratio}
% 現在の組方向により、|\pxrr@yhtratio| と |\pxrr@thtratio| のいずれか
% 一方に設定される。
%    \begin{macrocode}
\def\pxrr@htratio{0}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@iiskip}
% \begin{macro}{\pxrr@iaiskip}
% 和文間空白および和欧文間空白の量。
%    \begin{macrocode}
\let\pxrr@iiskip\pxrr@zeropt
\let\pxrr@iaiskip\pxrr@zeropt
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\pxrr@assign@fsize}
% 上記の変数（マクロ）を設定する。
%    \begin{macrocode}
\def\pxrr@assign@fsize{%
  \@tempdima=\f@size\p@
  \@tempdima\pxrr@c@size@ratio\@tempdima
  \edef\pxrr@ruby@fsize{\the\@tempdima}%
  \pxrr@get@zwidth\pxrr@body@zw
  \begingroup
    \pxrr@use@ruby@font
    \pxrr@get@zwidth\pxrr@ruby@zw
    \global\let\pxrr@gtempa\pxrr@ruby@zw
  \endgroup
  \let\pxrr@ruby@zw\pxrr@gtempa
  \pxrr@get@iiskip\pxrr@iiskip
  \pxrr@get@iaiskip\pxrr@iaiskip
%    \end{macrocode}
% |\pxrr@htratio| の値を設定する。
%    \begin{macrocode}
  \pxrr@if@in@tate{%
    \let\pxrr@htratio\pxrr@thtratio
  }{%
    \let\pxrr@htratio\pxrr@yhtratio
  }%
%    \end{macrocode}
% |\pxrr@ruby@raise| の値を計算する。
%    \begin{macrocode}
  \@tempdima\pxrr@body@zw\relax
  \@tempdima\pxrr@htratio\@tempdima
  \@tempdimb\pxrr@ruby@zw\relax
  \advance\@tempdimb-\pxrr@htratio\@tempdimb
  \advance\@tempdima\@tempdimb
  \@tempdimb\pxrr@body@zw\relax
  \advance\@tempdima\pxrr@c@inter@gap\@tempdimb
  \edef\pxrr@ruby@raise{\the\@tempdima}%
%    \end{macrocode}
% |\pxrr@ruby@lower| の値を計算する。
%    \begin{macrocode}
  \@tempdima\pxrr@body@zw\relax
  \advance\@tempdima-\pxrr@htratio\@tempdima
  \@tempdimb\pxrr@ruby@zw\relax
  \@tempdimb\pxrr@htratio\@tempdimb
  \advance\@tempdima\@tempdimb
  \@tempdimb\pxrr@body@zw\relax
  \advance\@tempdima\pxrr@c@inter@gap\@tempdimb
  \edef\pxrr@ruby@lower{\the\@tempdima}%
%    \end{macrocode}
% 圏点ルビ同時付加の設定。
%    \begin{macrocode}
  \ifpxrr@combo
    \pxrr@ck@assign@fsize
  \fi
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@use@ruby@font}
% ルビ用のフォントに切り替える。
%    \begin{macrocode}
\def\pxrr@use@ruby@font{%
  \pxrr@without@macro@trace{%
    \let\rubyfontsize\pxrr@ruby@fsize
    \fontsize{\pxrr@ruby@fsize}{\z@}\selectfont
    \pxrr@c@ruby@font
  }%
}
%    \end{macrocode}
% \end{macro}
%
% \subsection{ルビ用均等割り}
%
% \begin{macro}{\pxrr@locate@inner}
% \begin{macro}{\pxrr@locate@head}
% \begin{macro}{\pxrr@locate@end}
% ルビ配置パターン（行頭／行中／行末）を表す定数。
%    \begin{macrocode}
\chardef\pxrr@locate@inner=1
\chardef\pxrr@locate@head=0
\chardef\pxrr@locate@end=2
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\pxrr@evenspace}
% \begin{macro}{\pxrr@evenspace@int}
% \begin{macro}{\pxrr@makebox@res}
% |\pxrr@evenspace{|\jmeta{パターン}|}\CS{|\jmeta{フォント}|}|^^A
% |{|\jmeta{幅}|}{|\jmeta{テキスト}|}|\Means
% \jmeta{テキスト}を指定の\jmeta{幅}に対する
% \jmeta{パターン}（行頭／行中／行末）の
% 「行中ルビ用均等割り」で配置し、
% 結果をボックスレジスタ |\CS| に代入する。
% 均等割りの要素分割は |\pxrr@decompose| を用いて行われるので、
% 要素数が |\pxrr@cntr| に返る。
% また、先頭と末尾の空きの量をそれぞれ\ 
% |\pxrr@bspace| と |\pxrr@aspace| に代入する。
%
% |\pxrr@evenspace@int{|\jmeta{パターン}|}\CS{|\jmeta{フォント}|}|^^A
% |{|\jmeta{幅}|}|\Means
% |\pxrr@evenspace| の実行を、
% \begin{quote}
% |\pxrr@res| と |\pxrr@cntr| にテキストの |\pxrr@decompose| の結果が
% 入っていて、テキストの自然長がマクロ |\pxrr@natwd| に
% 入っている
% \end{quote}
% という状態で、途中から開始する。
%    \begin{macrocode}
\def\pxrr@evenspace#1#2#3#4#5{%
%    \end{macrocode}
% \jmeta{テキスト}の自然長を計測し、|\pxrr@natwd| に格納する。
%    \begin{macrocode}
  \setbox#2\pxrr@hbox{#5}\@tempdima\wd#2%
  \edef\pxrr@natwd{\the\@tempdima}%
%    \end{macrocode}
% \jmeta{テキスト}をリスト解析する
% （|\pxrr@cntr| に要素数が入る）。
% |\pxrr@evenspace@int| に引き継ぐ。
%    \begin{macrocode}
  \pxrr@decompose{#5}%
  \pxrr@evenspace@int{#1}{#2}{#3}{#4}%
}
%    \end{macrocode}
% ここから実行を開始することもある。
%    \begin{macrocode}
\def\pxrr@evenspace@int#1#2#3#4{%
%    \end{macrocode}
% 比率パラメタの設定。
%    \begin{macrocode}
  \pxrr@save@listproc
  \ifcase#1%
    \pxrr@evenspace@param\pxrr@zero\pxrr@sprop@hy\pxrr@sprop@hz
  \or
    \pxrr@evenspace@param\pxrr@sprop@x\pxrr@sprop@y\pxrr@sprop@z
  \or
    \pxrr@evenspace@param\pxrr@sprop@ex\pxrr@sprop@ey\pxrr@zero
  \fi
%    \end{macrocode}
% 挿入される |fil| の係数を求め、これがゼロの場合
% （この時 $\mbox{X}=\mbox{Z}=0$ である）は、
% アンダーフル防止のため、$\mbox{X}=\mbox{Z}=1$
% に変更する。
%    \begin{macrocode}
  \pxrr@dima=\pxrr@cntr\p@
  \advance\pxrr@dima-\p@
  \pxrr@dima=\pxrr@sprop@y@\pxrr@dima
  \advance\pxrr@dima\pxrr@sprop@x@\p@
  \advance\pxrr@dima\pxrr@sprop@z@\p@
  \ifdim\pxrr@dima>\z@\else
    \ifnum#1>\z@
      \let\pxrr@sprop@x@\@ne
      \advance\pxrr@dima\p@
    \fi
    \ifnum#1<\tw@
      \let\pxrr@sprop@z@\@ne
      \advance\pxrr@dima\p@
    \fi
  \fi
  \edef\pxrr@tempa{\strip@pt\pxrr@dima}%
\ifpxrrDebug
\typeout{\number\pxrr@sprop@x@:\number\pxrr@sprop@z@:\pxrr@tempa}%
\fi
%    \end{macrocode}
% |\pxrr@pre/inter/post| にグル―を設定して、
% |\pxrr@res| を組版する。
% なお、|\setbox...| を一旦マクロ |\pxrr@makebox@res| に定義
% しているのは、後で |\pxrr@adjust@margin| で再度呼び出せるように
% するため。
%    \begin{macrocode}
  \def\pxrr@pre##1{\pxrr@hfilx\pxrr@sprop@x@ ##1}%
  \def\pxrr@inter##1{\pxrr@hfilx\pxrr@sprop@y@ ##1}%
  \def\pxrr@post{\pxrr@hfilx\pxrr@sprop@z@}%
  \def\pxrr@makebox@res{%
    \setbox#2=\pxrr@hbox@to#4{#3\pxrr@res}%
  }%
  \pxrr@makebox@res
%    \end{macrocode}
% 前後の空白の量を求める。
%    \begin{macrocode}
  \pxrr@dima\wd#2%
  \advance\pxrr@dima-\pxrr@natwd\relax
  \pxrr@invscale\pxrr@dima\pxrr@tempa
  \@tempdima\pxrr@sprop@x@\pxrr@dima
  \edef\pxrr@bspace{\the\@tempdima}%
  \@tempdima\pxrr@sprop@z@\pxrr@dima
  \edef\pxrr@aspace{\the\@tempdima}%
  \pxrr@restore@listproc
\ifpxrrDebug
\typeout{\pxrr@bspace:\pxrr@aspace}%
\fi
}
\def\pxrr@evenspace@param#1#2#3{%
  \let\pxrr@sprop@x@#1%
  \let\pxrr@sprop@y@#2%
  \let\pxrr@sprop@z@#3%
}
\let\pxrr@makebox@res\@undefined
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\pxrr@adjust@margin}
% |\pxrr@adjust@margin|\Means
% |\pxrr@evenspace(@int)| を呼び出した直後に呼ぶ必要がある。
% 先頭と末尾の各々について、空きの量が |\pxrr@maxmargin|
% により決まる上限値を超える場合に、空きを上限値に抑える
% ように再調整する。
%    \begin{macrocode}
\def\pxrr@adjust@margin{%
  \pxrr@save@listproc
  \@tempdima\pxrr@body@zw\relax
  \@tempdima\pxrr@maxmargin\@tempdima
%    \end{macrocode}
% 再調整が必要かを |\if@tempswa| に記録する。
% 1文字しかない場合は調整不能だから検査を飛ばす。
%    \begin{macrocode}
  \@tempswafalse
  \def\pxrr@pre##1{\pxrr@hfilx\pxrr@sprop@x@ ##1}%
  \def\pxrr@inter##1{\pxrr@hfilx\pxrr@sprop@y@ ##1}%
  \def\pxrr@post{\pxrr@hfilx\pxrr@sprop@z@}%
  \ifnum\pxrr@cntr>\@ne
    \ifdim\pxrr@bspace>\@tempdima
      \edef\pxrr@bspace{\the\@tempdima}%
      \def\pxrr@pre##1{\hskip\pxrr@bspace\relax ##1}%
      \@tempswatrue
    \fi
    \ifdim\pxrr@aspace>\@tempdima
      \edef\pxrr@aspace{\the\@tempdima}%
      \def\pxrr@post{\hskip\pxrr@aspace\relax}%
      \@tempswatrue
    \fi
  \fi
%    \end{macrocode}
% 必要に応じて再調整を行う。
%    \begin{macrocode}
  \if@tempswa
    \pxrr@makebox@res
  \fi
  \pxrr@restore@listproc
\ifpxrrDebug
\typeout{\pxrr@bspace:\pxrr@aspace}%
\fi
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@save@listproc}
% |\pxrr@pre/inter/post| の定義を退避する。
% \Note
% 退避のネストはできない。
%    \begin{macrocode}
\def\pxrr@save@listproc{%
  \let\pxrr@pre@save\pxrr@pre
  \let\pxrr@inter@save\pxrr@inter
  \let\pxrr@post@save\pxrr@post
}
\let\pxrr@pre@save\@undefined
\let\pxrr@inter@save\@undefined
\let\pxrr@post@save\@undefined
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@restore@listproc}
% |\pxrr@pre/inter/post| の定義を復帰する。
%    \begin{macrocode}
\def\pxrr@restore@listproc{%
  \let\pxrr@pre\pxrr@pre@save
  \let\pxrr@inter\pxrr@inter@save
  \let\pxrr@post\pxrr@post@save
}
%    \end{macrocode}
% \end{macro}
%
% \subsection{小書き仮名の変換}
%
% \begin{macro}{\pxrr@trans@res}
% |\pxrr@transform@kana| 内で変換結果を保持するマクロ。
%    \begin{macrocode}
\let\pxrr@trans@res\@empty
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@transform@kana}
% |\pxrr@transform@kana\CS|\Means
% マクロ |\CS| の展開テキストの中でグループに含まれない小書き仮名を
% 対応する非小書き仮名に変換し、|\CS| を上書きする。
%    \begin{macrocode}
\def\pxrr@transform@kana#1{%
  \let\pxrr@trans@res\@empty
  \def\pxrr@transform@kana@end\pxrr@end{%
    \let#1\pxrr@trans@res
  }%
  \expandafter\pxrr@transform@kana@loop@a#1\pxrr@end
}
\def\pxrr@transform@kana@loop@a{%
  \futurelet\pxrr@token\pxrr@transform@kana@loop@b
}
\def\pxrr@transform@kana@loop@b{%
  \ifx\pxrr@token\pxrr@end
    \let\pxrr@tempb\pxrr@transform@kana@end
  \else\ifx\pxrr@token\bgroup
    \let\pxrr@tempb\pxrr@transform@kana@loop@c
  \else\ifx\pxrr@token\@sptoken
    \let\pxrr@tempb\pxrr@transform@kana@loop@d
  \else
    \let\pxrr@tempb\pxrr@transform@kana@loop@e
  \fi\fi\fi
  \pxrr@tempb
}
\def\pxrr@transform@kana@loop@c#1{%
  \pxrr@appto\pxrr@trans@res{{#1}}%
  \pxrr@transform@kana@loop@a
}
\expandafter\def\expandafter\pxrr@transform@kana@loop@d\space{%
  \pxrr@appto\pxrr@trans@res{ }%
  \pxrr@transform@kana@loop@a
}
\def\pxrr@transform@kana@loop@e#1{%
  \expandafter\pxrr@transform@kana@loop@f\string#1\pxrr@nil#1%
}
\def\pxrr@transform@kana@loop@f#1#2\pxrr@nil#3{%
  \@tempswafalse
  \ifnum`#1>\@cclv
    \begingroup\expandafter\expandafter\expandafter\endgroup
    \expandafter\ifx\csname pxrr@nonsmall/#3\endcsname\relax\else
      \@tempswatrue
    \fi
  \fi
  \if@tempswa
    \edef\pxrr@tempa{%
      \noexpand\pxrr@appto\noexpand\pxrr@trans@res
       {\csname pxrr@nonsmall/#3\endcsname}%
    }%
    \pxrr@tempa
  \else
    \pxrr@appto\pxrr@trans@res{#3}%
  \fi
  \pxrr@transform@kana@loop@a
}
\def\pxrr@assign@nonsmall#1/#2\pxrr@nil{%
  \pxrr@get@jchar@token\pxrr@tempa{\pxrr@jc{#1}}%
  \pxrr@get@jchar@token\pxrr@tempb{\pxrr@jc{#2}}%
  \expandafter\edef\csname pxrr@nonsmall/\pxrr@tempa\endcsname
   {\pxrr@tempb}%
}
\@tfor\pxrr@tempc:=%
    {2421:3041/2422:3042}{2423:3043/2424:3044}%
    {2425:3045/2426:3046}{2427:3047/2428:3048}%
    {2429:3049/242A:304A}{2443:3063/2444:3064}%
    {2463:3083/2464:3084}{2465:3085/2466:3086}%
    {2467:3087/2468:3088}{246E:308E/246F:308F}%
    {2521:30A1/2522:30A2}{2523:30A3/2524:30A4}%
    {2525:30A5/2526:30A6}{2527:30A7/2528:30A8}%
    {2529:30A9/252A:30AA}{2543:30C3/2544:30C4}%
    {2563:30E3/2564:30E4}{2565:30E5/2566:30E6}%
    {2567:30E7/2568:30E8}{256E:30EE/256F:30EF}%
  \do{%
  \expandafter\pxrr@assign@nonsmall\pxrr@tempc\pxrr@nil
}
%    \end{macrocode}
% \end{macro}
%
% \subsection{ブロック毎の組版}
%
% \begin{macro}{\ifpxrr@protr}
% ルビ文字列の突出があるか。
% スイッチ。
%    \begin{macrocode}
\newif\ifpxrr@protr
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\ifpxrr@any@protr}
% 複数ブロックの処理で、いずれかのブロックにルビ文字列の突出があるか。
% スイッチ。
%    \begin{macrocode}
\newif\ifpxrr@any@protr
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@locate@temp}
% |\pxrr@compose@*side@block@do| で使われる一時変数。
% 整数定数。
%    \begin{macrocode}
\let\pxrr@locate@temp\relax
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@epsilon}
% ルビ文字列と親文字列の自然長の差がこの値以下の場合は、
% 差はないものとみなす（演算誤差対策）。
%    \begin{macrocode}
\def\pxrr@epsilon{0.01pt}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@compose@block}
% |\pxrr@compose@block{|\jmeta{パターン}|}{|^^A
% \jmeta{親文字ブロック}|}{|\jmeta{ルビ文字ブロック}|}|\Means
% 1つのブロックの組版処理。
% \jmeta{パターン}は |\pxrr@evenspace| と同じ意味。
% 突出があるかを |\ifpxrr@protr| に返し、前と後の突出の量を
% それぞれ |\pxrr@bspace| と |\pxrr@aspace| に返す。
%    \begin{macrocode}
\def\pxrr@compose@block#1#2#3{%
%    \end{macrocode}
% 本体の前に加工処理を介入させる。
% \Note |\pxrr@compose@block@pre| は2つのルビ引数を取る。
% |\pxrr@compose@block@do| に本体マクロを |\let| する。
%    \begin{macrocode}
  \let\pxrr@compose@block@do\pxrr@compose@oneside@block@do
  \pxrr@compose@block@pre{#1}{#2}{#3}{}%
}
%    \end{macrocode}
% こちらが本体。
%    \begin{macrocode}
% #4は空
\def\pxrr@compose@oneside@block@do#1#2#3#4{%
  \setbox\pxrr@boxa\pxrr@hbox{#2}%
  \edef\pxrr@ck@body@natwd{\the\wd\pxrr@boxa}%
  \let\pxrr@ck@locate\pxrr@locate@inner
  \setbox\pxrr@boxr\pxrr@hbox{%
    \pxrr@use@ruby@font
    #3%
  }%
  \@tempdima\wd\pxrr@boxr
  \advance\@tempdima-\wd\pxrr@boxa
  \ifdim\pxrr@epsilon<\@tempdima
%    \end{macrocode}
% ルビ文字列の方が長い場合。
% 親文字列をルビ文字列の長さに合わせて均等割りで組み直す。
% |\pxrr@?space| は |\pxrr@evenspace@int| が返す値のままでよい。
% 「拡張肩付き」指定の場合、前側の突出を抑止する。
%    \begin{macrocode}
    \pxrr@protrtrue
    \let\pxrr@locate@temp#1%
    \ifnum\pxrr@athead>\@ne
      \ifnum\pxrr@locate@temp=\pxrr@locate@inner
        \let\pxrr@locate@temp\pxrr@locate@head
      \fi
    \fi
    \let\pxrr@ck@locate\pxrr@locate@temp
    \pxrr@decompose{#2}%
    \edef\pxrr@natwd{\the\wd\pxrr@boxa}%
    \pxrr@evenspace@int\pxrr@locate@temp\pxrr@boxa\relax
     {\wd\pxrr@boxr}%
  \else\ifdim-\pxrr@epsilon>\@tempdima
%    \end{macrocode}
% ルビ文字列の方が短い場合。
% ルビ文字列を親文字列の長さに合わせて均等割りで組み直す。
% この場合、|\pxrr@maxmargin| を考慮する必要がある。
% ただし肩付きルビの場合は組み直しを行わない。
% |\pxrr@?space| はゼロに設定する。
%    \begin{macrocode}
    \pxrr@protrfalse
    \ifnum\pxrr@athead=\z@
      \pxrr@decompose{#3}%
      \edef\pxrr@natwd{\the\wd\pxrr@boxr}%
      \pxrr@evenspace@int{#1}\pxrr@boxr
       \pxrr@use@ruby@font{\wd\pxrr@boxa}%
      \pxrr@adjust@margin
    \fi
    \let\pxrr@bspace\pxrr@zeropt
    \let\pxrr@aspace\pxrr@zeropt
  \else
%    \end{macrocode}
% 両者の長さが等しい（とみなす）場合。
% 突出フラグは常に偽にする（実際にはルビの方が僅かだけ長いかも
% 知れないが）。
%    \begin{macrocode}
    \pxrr@protrfalse
    \let\pxrr@bspace\pxrr@zeropt
    \let\pxrr@aspace\pxrr@zeropt
  \fi\fi
%    \end{macrocode}
% 実際に組版を行う。
%    \begin{macrocode}
  \setbox\z@\hbox{%
    \ifnum\pxrr@side=\z@
      \raise\pxrr@ruby@raise\box\pxrr@boxr
    \else
      \lower\pxrr@ruby@lower\box\pxrr@boxr
    \fi
  }%
  \ifnum \ifpxrr@combo\pxrr@ck@ruby@combo\else\z@\fi >\z@
    \pxrr@ck@compose{#2}%
  \fi
  \ht\z@\z@ \dp\z@\z@
  \@tempdima\wd\z@
  \setbox\pxrr@boxr\hbox{%
    \box\z@
    \kern-\@tempdima
    \box\pxrr@boxa
  }%
%    \end{macrocode}
% |\ifpxrr@any@protr| を設定する。
%    \begin{macrocode}
  \ifpxrr@protr
    \pxrr@any@protrtrue
  \fi
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@compose@twoside@block}
% 両側ルビ用のブロック構成。
%    \begin{macrocode}
\def\pxrr@compose@twoside@block{%
  \let\pxrr@compose@block@do\pxrr@compose@twoside@block@do
  \pxrr@compose@block@pre
}
\def\pxrr@compose@twoside@block@do#1#2#3#4{%
%    \end{macrocode}
% |\pxrr@boxa| に親文字、|\pxrr@boxr| に上側ルビ、
% |\pxrr@boxb| に下側ルビの出力を保持する。
%    \begin{macrocode}
  \setbox\pxrr@boxa\pxrr@hbox{#2}%
  \edef\pxrr@ck@body@natwd{\the\wd\pxrr@boxa}%
  \let\pxrr@ck@locate\pxrr@locate@inner
  \setbox\pxrr@boxr\pxrr@hbox{%
    \pxrr@use@ruby@font
    #3%
  }%
  \setbox\pxrr@boxb\pxrr@hbox{%
    \pxrr@use@ruby@font
    #4%
  }%
%    \end{macrocode}
% 「何れかのルビが親文字列より長いか」を検査する。
%    \begin{macrocode}
  \@tempswafalse
  \@tempdima\wd\pxrr@boxr
  \advance\@tempdima-\wd\pxrr@boxa
  \ifdim\pxrr@epsilon<\@tempdima \@tempswatrue \fi
  \@tempdima\wd\pxrr@boxb
  \advance\@tempdima-\wd\pxrr@boxa
  \ifdim\pxrr@epsilon<\@tempdima \@tempswatrue \fi
%    \end{macrocode}
% 親文字より長いルビが存在する場合。
% 長い方のルビ文字列の長さに合わせて、親文字列と
% 他方のルビ文字列を組み直す。
% （実際の処理は |\pxrr@compose@twoside@block@sub| で行う。）
%    \begin{macrocode}
  \if@tempswa
    \pxrr@protrtrue
%    \end{macrocode}
% 「拡張肩付き」指定の場合、前側の突出を抑止する。
%    \begin{macrocode}
    \let\pxrr@locate@temp#1%
    \ifnum\pxrr@athead>\@ne
      \ifnum\pxrr@locate@temp=\pxrr@locate@inner
        \let\pxrr@locate@temp\pxrr@locate@head
      \fi
    \fi
    \let\pxrr@ck@locate\pxrr@locate@temp
%    \end{macrocode}
% 上側と下側のどちらのルビが長いかに応じて引数を変えて、
% |\pxrr@compose@twoside@block@sub| を呼び出す。
%    \begin{macrocode}
    \ifdim\wd\pxrr@boxr<\wd\pxrr@boxb
      \pxrr@compose@twoside@block@sub{#2}{#3}%
       \pxrr@boxr\pxrr@boxb
    \else
      \pxrr@compose@twoside@block@sub{#2}{#4}%
       \pxrr@boxb\pxrr@boxr
    \fi
%    \end{macrocode}
% 親文字の方が長い場合。
% 親文字列の長さに合わせて、両方のルビを（片側の場合と同様の）
% 均等割りで組み直す。
%    \begin{macrocode}
  \else
    \pxrr@protrfalse
%    \end{macrocode}
% 肩付きルビの場合は組み直しを行わない。
%    \begin{macrocode}
    \ifnum\pxrr@athead=\z@
      \@tempdima\wd\pxrr@boxa
      \advance\@tempdima-\wd\pxrr@boxr
      \ifdim\pxrr@epsilon<\@tempdima
        \pxrr@decompose{#3}%
        \edef\pxrr@natwd{\the\wd\pxrr@boxr}%
        \pxrr@evenspace@int{#1}\pxrr@boxr
         \pxrr@use@ruby@font{\wd\pxrr@boxa}%
        \pxrr@adjust@margin
      \fi
      \@tempdima\wd\pxrr@boxa
      \advance\@tempdima-\wd\pxrr@boxb
      \ifdim\pxrr@epsilon<\@tempdima
        \pxrr@decompose{#4}%
        \edef\pxrr@natwd{\the\wd\pxrr@boxb}%
        \pxrr@evenspace@int{#1}\pxrr@boxb
         \pxrr@use@ruby@font{\wd\pxrr@boxa}%
        \pxrr@adjust@margin
      \fi
    \fi
%    \end{macrocode}
% |\pxrr@?space| はゼロに設定する。
%    \begin{macrocode}
    \let\pxrr@bspace\pxrr@zeropt
    \let\pxrr@aspace\pxrr@zeropt
  \fi
%    \end{macrocode}
% 実際に組版を行う。
%    \begin{macrocode}
  \setbox\z@\hbox{%
    \@tempdima\wd\pxrr@boxr
    \raise\pxrr@ruby@raise\box\pxrr@boxr
    \kern-\@tempdima
    \lower\pxrr@ruby@lower\box\pxrr@boxb
  }%
  \ifnum \ifpxrr@combo\pxrr@ck@ruby@combo\else\z@\fi >\z@
    \pxrr@ck@compose{#2}%
  \fi
  \ht\z@\z@ \dp\z@\z@
  \@tempdima\wd\z@
  \setbox\pxrr@boxr\hbox{%
    \box\z@
    \kern-\@tempdima
    \box\pxrr@boxa
  }%
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@body@wd}
% |\pxrr@compose@twoside@block@sub| の内部で用いられる変数で、
% “親文字列の実際の長さ”（均等割りで入った中間の空きを入れるが
% 両端の空きを入れない）を表す。
% 寸法値マクロ。
%    \begin{macrocode}
\let\pxrr@body@wd\relax
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@compose@twoside@block@sub}
% |\pxrr@compose@twoside@block@sub| の内部で用いられるマクロ。
%    \begin{macrocode}
\let\pxrr@restore@margin@values\relax
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@compose@twoside@block@sub}
% |\pxrr@compose@twoside@block@sub{|^^A
% \jmeta{親文字}|}{|\jmeta{短い方のルビ文字}|}\CSa\CSb|\Means
% 両側ルビで親文字列より長いルビ文字列が存在する場合の
% 組み直しの処理を行う。
% このマクロの呼出時、上側ルビの出力結果が |\pxrr@boxr|、
% 下側ルビの出力結果が |\pxrr@boxb| に入っているが、
% この2つのボックスのうち、短いルビの方が |\CSa|、
% 長いルビの方が |\CSb| として渡されている。
%    \begin{macrocode}
\def\pxrr@compose@twoside@block@sub#1#2#3#4{%
  \pxrr@decompose{#1}%
  \edef\pxrr@natwd{\the\wd\pxrr@boxa}%
  \pxrr@evenspace@int\pxrr@locate@temp\pxrr@boxa\relax{\wd#4}%
  \@tempdima\wd#4%
  \advance\@tempdima-\pxrr@bspace\relax
  \advance\@tempdima-\pxrr@aspace\relax
  \edef\pxrr@body@wd{\the\@tempdima}%
  \advance\@tempdima-\wd#3%
  \ifdim\pxrr@epsilon<\@tempdima
    \edef\pxrr@restore@margin@values{%
      \edef\noexpand\pxrr@bspace{\pxrr@bspace}%
      \edef\noexpand\pxrr@aspace{\pxrr@aspace}%
    }%
    \pxrr@decompose{#2}%
    \edef\pxrr@natwd{\the\wd#3}%
    \pxrr@evenspace@int\pxrr@locate@temp#3%
     \pxrr@use@ruby@font{\pxrr@body@wd}%
    \pxrr@adjust@margin
    \pxrr@restore@margin@values
    \setbox#3\hbox{%
      \kern\pxrr@bspace\relax
      \box#3%
    }%
  \else
    \ifnum\pxrr@locate@temp=\pxrr@locate@head
      \@tempdima\z@
    \else\ifnum\pxrr@locate@temp=\pxrr@locate@inner
      \@tempdima.5\@tempdima
    \fi\fi
    \advance\@tempdima\pxrr@bspace\relax
    \setbox#3\hbox{%
      \kern\@tempdima
      \box#3%
    }%
  \fi
}
%     \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@compose@block@pre}
% |\pxrr@compose@block@pre{|\jmeta{パターン}|}{|^^A
%r \jmeta{親文字}|}{|\jmeta{ルビ1}|}{|\jmeta{ルビ2}|}|\Means
% 親文字列・ルビ文字列の加工を行う。
% \Note 両側ルビ対応のため、ルビ用引数が2つある。
%    \begin{macrocode}
\def\pxrr@compose@block@pre{%
%    \end{macrocode}
% |f| 指定時は小書き仮名の変換を施す。
%    \begin{macrocode}
  \pxrr@cond\ifnum\pxrr@fullsize>\z@\fi{%
    \pxrr@compose@block@pre@a
  }{%
    \pxrr@compose@block@pre@d
  }%
}
% {パターン}{親文字}{ルビ1}{ルビ2}
\def\pxrr@compose@block@pre@a#1#2#3#4{%
  \def\pxrr@compose@block@tempa{#4}%
  \pxrr@transform@kana\pxrr@compose@block@tempa
  \expandafter\pxrr@compose@block@pre@b
   \expandafter{\pxrr@compose@block@tempa}{#1}{#2}{#3}%
}
% {ルビ2}{パターン}{親文字}{ルビ1}
\def\pxrr@compose@block@pre@b#1#2#3#4{%
  \def\pxrr@compose@block@tempa{#4}%
  \pxrr@transform@kana\pxrr@compose@block@tempa
  \expandafter\pxrr@compose@block@pre@c
   \expandafter{\pxrr@compose@block@tempa}{#1}{#2}{#3}%
}
% {ルビ1}{ルビ2}{パターン}{親文字}
\def\pxrr@compose@block@pre@c#1#2#3#4{%
  \pxrr@compose@block@pre@d{#3}{#4}{#1}{#2}%
}
\def\pxrr@compose@block@pre@d{%
  \pxrr@cond\ifnum\pxrr@evensp=\z@\fi{%
    \pxrr@compose@block@pre@e
  }{%
    \pxrr@compose@block@pre@f
  }%
}
% {パターン}{親文字}
\def\pxrr@compose@block@pre@e#1#2{%
  \pxrr@compose@block@pre@f{#1}{{#2}}%
}
\def\pxrr@compose@block@pre@f{%
  \pxrr@cond\ifnum\pxrr@revensp=\z@\fi{%
    \pxrr@compose@block@pre@g
  }{%
    \pxrr@compose@block@do
  }%
}
% {パターン}{親文字}{ルビ1}{ルビ2}
\def\pxrr@compose@block@pre@g#1#2#3#4{%
  \pxrr@compose@block@do{#1}{#2}{{#3}}{{#4}}%
}
\let\pxrr@compose@block@tempa\@undefined
%    \end{macrocode}
% \end{macro}
%
% \subsection{命令の頑強化}
%
% \begin{macro}{\pxrr@add@protect}
% |\pxrr@add@protect\CS|\Means
% 命令 |\CS| に |\protect| を施して頑強なものに変える。
% |\CS| は最初から |\DeclareRobustCommand| で定義された頑強な命令と
% ほぼ同じように振舞う
% ――例えば、|\CS| の定義の本体は \verb*+\CS + という制御綴に
% 移される。
% 唯一の相違点は、「組版中」
% （すなわち |\protect|$\;=\;$|\@typeset@protect|）の場合は、
% |\CS| は \verb*+\protect\CS + ではなく、単なる \verb*+\CS + に
% 展開されることである。
% 組版中は |\protect| は結局 |\relax| であるので、
% |\DeclareRobustCommand| 定義の命令の場合、|\relax| が「実行」
% されることになるが、{p\TeX}ではこれがメトリックグル―の挿入に
% 干渉するので、このパッケージの目的に沿わないのである。
% \Note
% |\CS| は「制御語」（制御記号でなく）である必要がある。
%    \begin{macrocode}
\def\pxrr@add@protect#1{%
  \expandafter\pxrr@add@protect@a
    \csname\expandafter\@gobble\string#1\space\endcsname#1%
}
\def\pxrr@add@protect@a#1#2{%
  \let#1=#2%
  \def#2{\pxrr@check@protect\protect#1}%
}
\def\pxrr@check@protect{%
  \ifx\protect\@typeset@protect
    \expandafter\@gobble
  \fi
}
%    \end{macrocode}
% \end{macro}
%
% \subsection{致命的エラー対策}
%
% 致命的エラーが起こった場合は、ルビ入力を放棄して
% 単に親文字列を出力することにする。
%
% \begin{macro}{\pxrr@body@input}
% 入力された親文字列。
%    \begin{macrocode}
\let\pxrr@body@input\@empty
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@prepare@fallback}
% |\pxrr@prepare@fallback{|\jmeta{親文字列}|}|\Means
%    \begin{macrocode}
\def\pxrr@prepare@fallback#1{%
  \pxrr@fatal@errorfalse
  \def\pxrr@body@input{#1}%
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@fallback}
% 致命的エラー時に出力となるもの。
% 単に親文字列を出力することにする。
%    \begin{macrocode}
\def\pxrr@fallback{%
  \pxrr@body@input
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@if@alive}
% |\pxrr@if@alive{|\jmeta{コード}|}|\Means
% 致命的エラーが未発生の場合に限り、\jmeta{コード}に展開する。
%    \begin{macrocode}
\def\pxrr@if@alive{%
  \ifpxrr@fatal@error \expandafter\@gobble
  \else \expandafter\@firstofone
  \fi
}
%    \end{macrocode}
% \end{macro}
%
% \subsection{先読み処理}
%
% ゴースト処理が無効の場合に後ろ側の禁則処理を行うため、
% ルビ命令の直後に続くトークンを取得して、
% その前禁則ペナルティ（|\prebreakpenalty|）の値を保存する。
% 信頼性の低い方法なので、ゴースト処理が可能な場合はそちらを
% 利用するべきである。
%
% \begin{macro}{\pxrr@end@kinsoku}
% ルビ命令直後の文字の前禁則ペナルティ値とみなす値。
%    \begin{macrocode}
\def\pxrr@end@kinsoku{0}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@ruby@scan}
% 片側ルビ用の先読み処理。
%    \begin{macrocode}
\def\pxrr@ruby@scan#1#2{%
%    \end{macrocode}
% |\pxrr@check@kinsoku| の続きの処理。
% |\pxrr@cntr| の値を |\pxrr@end@kinsoku| に保存して、
% ルビ処理本体を呼び出す。
%    \begin{macrocode}
  \def\pxrr@tempc{%
    \edef\pxrr@end@kinsoku{\the\pxrr@cntr}%
    \pxrr@do@proc{#1}{#2}%
  }%
  \pxrr@check@kinsoku\pxrr@tempc
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@truby@scan}
% 両側ルビ用の先読み処理。
%    \begin{macrocode}
\def\pxrr@truby@scan#1#2#3{%
  \def\pxrr@tempc{%
    \edef\pxrr@end@kinsoku{\the\pxrr@cntr}%
    \pxrr@do@proc{#1}{#2}{#3}%
  }%
  \pxrr@check@kinsoku\pxrr@tempc
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@check@kinsoku}
% |\pxrr@check@kinsoku\CS|\Means
% |\CS| の直後に続くトークンについて、
% それが「通常文字」
% （和文文字トークンまたはカテゴリコード11、12の欧文文字トークン）
% である場合にはその前禁則ペナルティ（|\prebreakpenalty|）の値を、
% そうでない場合はゼロを |\pxrr@cntr| に代入する。
% その後、|\CS| を実行（展開）する。
% \Note ただし、欧文ルビの場合、欧文文字の前禁則ペナルティは 20000
% として扱う。
%    \begin{macrocode}
\def\pxrr@check@kinsoku#1{%
  \let\pxrr@tempb#1%
  \futurelet\pxrr@token\pxrr@check@kinsoku@a
}
\def\pxrr@check@kinsoku@a{%
  \pxrr@check@char\pxrr@token
%    \end{macrocode}
% 和文ルビの場合は、欧文通常文字も和文通常文字と同じ扱いにする。
%    \begin{macrocode}
  \ifpxrr@abody\else
    \ifnum\pxrr@cntr=\@ne
      \pxrr@cntr\tw@
    \fi
  \fi
  \ifcase\pxrr@cntr
    \pxrr@cntr\z@
    \expandafter\pxrr@tempb
  \or
    \pxrr@cntr\@MM
    \expandafter\pxrr@tempb
  \else
    \expandafter\pxrr@check@kinsoku@b
  \fi
}
%    \end{macrocode}
% |\let| されたトークンのままでは符号位置を得ることができない
% ため、改めてマクロの引数として受け取り、複製した上で
% 片方を後の処理に使う。
% 既に後続トークンは「通常文字」である
% （つまり空白や |{| ではない）ことが判明していることに注意。
%    \begin{macrocode}
\def\pxrr@check@kinsoku@b#1{%
  \pxrr@check@kinsoku@c#1#1%
}
\def\pxrr@check@kinsoku@c#1{%
  \pxrr@get@prebreakpenalty\pxrr@cntr{`#1}%
  \pxrr@tempb
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@check@char}
% |\pxrr@check@char\CS|\Means
% トークン |\CS| が「通常文字」であるかを調べ、以下の値を |\pxrr@cntr|
% に返す： 0 = 通常文字でない；1 = 欧文通常文字；2 = 和文通常文字。
%
% 定義本体の中でカテゴリコード12の |kanji| というトークン列が
% 必要なので、少々特殊な処置をしている。
% まず |\pxrr@check@char| を定義するためのマクロを用意する。
%    \begin{macrocode}
\def\pxrr@tempa#1#2\pxrr@nil{%
%    \end{macrocode}
% 実際に呼び出される時には |#2| はカテゴリコード12の |kanji| に
% 置き換わる。
% （不要な |\| を |#1| に受け取らせている。）
%    \begin{macrocode}
  \def\pxrr@check@char##1{%
%    \end{macrocode}
% まず制御綴とカテゴリコード11、12、13を手早く |\ifcat| で
% 判定する。
%    \begin{macrocode}
    \ifcat\noexpand##1\relax
      \pxrr@cntr\z@
    \else\ifcat\noexpand##1\noexpand~%
      \pxrr@cntr\z@
    \else\ifcat\noexpand##1A%
      \pxrr@cntr\@ne
    \else\ifcat\noexpand##10%
      \pxrr@cntr\@ne
    \else
%    \end{macrocode}
% それ以外の場合。
% 和文文字トークンであるかを |\meaning| テストで調べる。
% （和文文字の |\ifcat| 判定は色々と面倒な点があるので避ける。）
%    \begin{macrocode}
      \pxrr@cntr\z@
      \expandafter\pxrr@check@char@a\meaning##1#2\pxrr@nil
    \fi\fi\fi\fi
  }%
  \def\pxrr@check@char@a##1#2##2\pxrr@nil{%
    \ifcat @##1@%
      \pxrr@cntr\tw@
    \fi
  }%
}
%    \end{macrocode}
% 規定の引数を用意して「定義マクロ」を呼ぶ。
%    \begin{macrocode}
\expandafter\pxrr@tempa\string\kanji\pxrr@nil
%    \end{macrocode}
% \end{macro}
%
% \subsection{進入処理}
%
% \begin{macro}{\pxrr@auto@penalty}
% 自動挿入されるペナルティ。
% （整数定数への |\let|。）
%    \begin{macrocode}
\let\pxrr@auto@penalty\z@
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@auto@icspace}
% 文字間の空き。
% 寸法値マクロ。
%    \begin{macrocode}
\let\pxrr@auto@icspace\pxrr@zeropt
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@intr@amount}
% 進入の幅。
% 寸法値マクロ。
%    \begin{macrocode}
\let\pxrr@intr@amount\pxrr@zeropt
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@intrude@setauto@j}
% 和文の場合の |\pxrr@auto@*| の設定。
%    \begin{macrocode}
\def\pxrr@intrude@setauto@j{%
%    \end{macrocode}
% 行分割禁止（|*|）の場合、
% ペナルティを 20000 とし、字間空きはゼロにする。
%    \begin{macrocode}
  \ifpxrr@bnobr
    \let\pxrr@auto@penalty\@MM
    \let\pxrr@auto@icspace\pxrr@zeropt
%    \end{macrocode}
% それ以外の場合は、ペナルティはゼロで、
% |\pxrr@bspace| の設定を活かす。
%    \begin{macrocode}
  \else
    \let\pxrr@auto@penalty\z@
    \if :\pxrr@bscomp
      \let\pxrr@auto@icspace\pxrr@iaiskip
    \else\if .\pxrr@bscomp
      \let\pxrr@auto@icspace\pxrr@zeropt
    \else
      \let\pxrr@auto@icspace\pxrr@iiskip
    \fi\fi
  \fi
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@intrude@setauto@a}
% 欧文の場合の |\pxrr@auto@*| の設定。
%    \begin{macrocode}
\def\pxrr@intrude@setauto@a{%
%    \end{macrocode}
% 欧文の場合、和欧文間空白挿入指定（|:|）でない場合は、
% （欧文同士と見做して）行分割禁止にする。
%    \begin{macrocode}
  \if :\pxrr@bscomp\else
    \pxrr@bnobrtrue
  \fi
  \ifpxrr@bnobr
    \let\pxrr@auto@penalty\@MM
    \let\pxrr@auto@icspace\pxrr@zeropt
  \else
%    \end{macrocode}
% この分岐は和欧文間空白挿入指定（|:|）に限る。
%    \begin{macrocode}
    \let\pxrr@auto@penalty\z@
    \let\pxrr@auto@icspace\pxrr@iaiskip
  \fi
}
%    \end{macrocode}
% \end{macro}
%
% \subsubsection{前側進入処理}
%
% \begin{macro}{\pxrr@intrude@head}
% 前側の進入処理。
%    \begin{macrocode}
\def\pxrr@intrude@head{%
%    \end{macrocode}
% ゴースト処理が有効な場合は進入処理を行わない。
% （だから進入が扱えない。）
%    \begin{macrocode}
  \ifpxrr@ghost\else
%    \end{macrocode}
% 実効の進入幅は |\pxrr@bintr| と |\pxrr@bspace| の小さい方。
%    \begin{macrocode}
    \let\pxrr@intr@amount\pxrr@bspace
    \ifdim\pxrr@bintr<\pxrr@intr@amount\relax
      \let\pxrr@intr@amount\pxrr@bintr
    \fi
%    \end{macrocode}
% |\pxrr@auto@*| の設定法は和文ルビと欧文ルビで処理が異なる。
%    \begin{macrocode}
    \ifpxrr@abody
      \pxrr@intrude@setauto@a
    \else
      \pxrr@intrude@setauto@j
    \fi
%    \end{macrocode}
% 実際に項目の出力を行う。
%
% 段落冒頭の場合、|!| 指定（|pxrr@bfintr| が真）ならば進入のための
% 負のグル―を入れる（他の項目は入れない）。
%    \begin{macrocode}
    \ifpxrr@par@head
      \ifpxrr@bfintr
        \hskip-\pxrr@intr@amount\relax
      \fi
%    \end{macrocode}
% 段落冒頭でない場合、字間空きのグル―、進入用のグル―を
% 順番に入れる。
% \Note ペナルティは |\pxrr@put@head@penalty| で既に入れている。
%    \begin{macrocode}
    \else
%     \penalty\pxrr@auto@penalty\relax
      \hskip-\pxrr@intr@amount\relax
      \hskip\pxrr@auto@icspace\relax
    \fi
  \fi
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@put@head@penalty}
% 前側に補助指定で定められた値のペナルティを置く。
% 現在位置に既にペナルティがある場合は合算する。
%    \begin{macrocode}
\def\pxrr@put@head@penalty{%
  \ifpxrr@ghost\else \ifpxrr@par@head\else
    \ifpxrr@abody
      \pxrr@intrude@setauto@a
    \else
      \pxrr@intrude@setauto@j
    \fi
    \ifnum\pxrr@auto@penalty=\z@\else
      \pxrr@cnta\lastpenalty \unpenalty
      \advance\pxrr@cnta\pxrr@auto@penalty\relax
      \penalty\pxrr@cnta
    \fi
  \fi\fi
}
%    \end{macrocode}
% \end{macro}
%
% \subsubsection{後側進入処理}
%
% \begin{macro}{\pxrr@intrude@end}
% 末尾での進入処理。
%    \begin{macrocode}
\def\pxrr@intrude@end{%
  \ifpxrr@ghost\else
%    \end{macrocode}
% 実効の進入幅は |\pxrr@aintr| と |\pxrr@aspace| の小さい方。
%    \begin{macrocode}
    \let\pxrr@intr@amount\pxrr@aspace
    \ifdim\pxrr@aintr<\pxrr@intr@amount\relax
      \let\pxrr@intr@amount\pxrr@aintr
    \fi
%    \end{macrocode}
% |\pxrr@auto@*| の設定法は和文ルビと欧文ルビで処理が異なる。
%    \begin{macrocode}
    \pxrr@csletcs{ifpxrr@bnobr}{ifpxrr@anobr}%
    \let\pxrr@bscomp\pxrr@ascomp
    \ifpxrr@abody
      \pxrr@intrude@setauto@a
    \else
      \pxrr@intrude@setauto@j
    \fi
%    \end{macrocode}
% 直後の文字の前禁則ペナルティが、挿入されるグルーの前に
% 入るようにする。
%    \begin{macrocode}
    \ifnum\pxrr@auto@penalty=\z@
      \let\pxrr@auto@penalty\pxrr@end@kinsoku
    \fi
    \ifpxrr@afintr
%    \end{macrocode}
% 段落末尾での進入を許す場合。
%    \begin{macrocode}
      \ifnum\pxrr@auto@penalty=\z@\else
        \penalty\pxrr@auto@penalty\relax
      \fi
      \kern-\pxrr@intr@amount\relax
%    \end{macrocode}
% 段落末尾では次のグル―を消滅させる（前のカーンは残る）。
% そのため、禁則ペナルティがある（段落末尾ではあり得ない）場合にのみ
% その次のペナルティ20000を置く。
% 本物の禁則ペナルティはこれに加算されるが、合計値は 10000 以上になる
% のでこの位置での行分割が禁止される。
%    \begin{macrocode}
      \hskip\pxrr@auto@icspace\relax
      \ifnum\pxrr@auto@penalty=\z@\else
        \penalty\@MM
      \fi
    \else
%    \end{macrocode}
% 段落末尾での進入を許さない場合。
%    \begin{macrocode}
      \@tempskipa-\pxrr@intr@amount\relax
      \advance\@tempskipa\pxrr@auto@icspace\relax
      \ifnum\pxrr@auto@penalty=\z@\else
        \penalty\pxrr@auto@penalty\relax
      \fi
      \hskip\@tempskipa
      \ifnum\pxrr@auto@penalty=\z@\else
        \penalty\@MM
      \fi
    \fi
  \fi
}
%    \end{macrocode}
% \end{macro}
%
% \subsection{メインです}
%
% \subsubsection{エントリーポイント}
%
% \begin{macro}{\ruby}
% \begin{macro}{\jruby}
% 和文ルビの公開命令。
% |\jruby| を頑強な命令として定義した上で、|\ruby| はそれに
% 展開されるマクロに（未定義ならば）定義する。
%    \begin{macrocode}
\AtBeginDocument{%
  \providecommand*{\ruby}{\jruby}%
}
\newcommand*{\jruby}{%
  \pxrr@jprologue
  \pxrr@trubyfalse
  \pxrr@ruby
}
%    \end{macrocode}
% 頑強にするために、先に定義した |\pxrr@add@protect| を用いる。
%    \begin{macrocode}
\pxrr@add@protect\jruby
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\aruby}
% 欧文ルビの公開命令。
% こちらも頑強な命令にする。
%    \begin{macrocode}
\newcommand*{\aruby}{%
  \pxrr@aprologue
  \pxrr@trubyfalse
  \pxrr@ruby
}
\pxrr@add@protect\aruby
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\truby}
% 和文両側ルビの公開命令。
%    \begin{macrocode}
\newcommand*{\truby}{%
  \pxrr@jprologue
  \pxrr@trubytrue
  \pxrr@ruby
}
\pxrr@add@protect\truby
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\atruby}
% 欧文両側ルビの公開命令。
%    \begin{macrocode}
\newcommand*{\atruby}{%
  \pxrr@aprologue
  \pxrr@trubytrue
  \pxrr@ruby
}
\pxrr@add@protect\atruby
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\ifpxrr@truby}
% 両側ルビであるか。
% スイッチ。
% |\pxrr@parse@option| で |\pxrr@side| を適切に設定する
% ために使われる。
%    \begin{macrocode}
\newif\ifpxrr@truby
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@option}
% \begin{macro}{\pxrr@exoption}
% オプションおよび第2オプションを格納するマクロ。
%    \begin{macrocode}
\let\pxrr@option\@empty
\let\pxrr@exoption\@empty
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\pxrr@do@proc}
% \begin{macro}{\pxrr@do@scan}
% |\pxrr@ruby| の処理中に使われる。
%    \begin{macrocode}
\let\pxrr@do@proc\@empty
\let\pxrr@do@scan\@empty
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\pxrr@ruby}
% |\ruby| および |\aruby| の共通の下請け。
% オプションの処理を行う。
%
% オプションを読みマクロに格納する。
%    \begin{macrocode}
\def\pxrr@ruby{%
  \@testopt\pxrr@ruby@a{}%
}
\def\pxrr@ruby@a[#1]{%
  \def\pxrr@option{#1}%
  \@testopt\pxrr@ruby@b{}%
}
\def\pxrr@ruby@b[#1]{%
  \def\pxrr@exoption{#1}%
  \ifpxrr@truby
    \let\pxrr@do@proc\pxrr@truby@proc
    \let\pxrr@do@scan\pxrr@truby@scan
  \else
    \let\pxrr@do@proc\pxrr@ruby@proc
    \let\pxrr@do@scan\pxrr@ruby@scan
  \fi
  \pxrr@ruby@c
}
\def\pxrr@ruby@c{%
  \ifpxrr@ghost
    \expandafter\pxrr@do@proc
  \else
    \expandafter\pxrr@do@scan
  \fi
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@mode@is@switching}
% |\if\pxrr@mode@is@switching{|\jmeta{基本モード}|}| の形の
% if文として使う。
% モードが“選択的”（|M|・|J|）であるか。
%    \begin{macrocode}
\def\pxrr@mode@is@switching{%
  \if      M\pxrr@mode T%
  \else\if J\pxrr@mode T%
  \else F%
  \fi\fi T%
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@bind@param}
% “呼出時変数”へのコピーを行う。
%    \begin{macrocode}
\def\pxrr@bind@param{%
%    \end{macrocode}
% 圏点ルビ同時付加フラグの処理。
% 圏点側が指定した |apply@combo| の値を“呼出時パラメタ”の |pxrr@combo| に
% 移動させる。
%    \begin{macrocode}
  \ifpxrr@apply@combo
    \pxrr@apply@combofalse
    \pxrr@combotrue
    \pxrr@ck@bind@param
  \else
    \pxrr@combofalse
  \fi
  \let\pxrr@c@ruby@font\pxrr@ruby@font
  \let\pxrr@c@size@ratio\pxrr@size@ratio
  \let\pxrr@c@inter@gap\pxrr@inter@gap
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@ruby@proc}
% |\pxrr@ruby@proc{|\jmeta{親文字列}|}{|\jmeta{ルビ文字列}|}|\Means
% これが手続の本体となる。
%    \begin{macrocode}
\def\pxrr@ruby@proc#1#2{%
  \pxrr@prepare@fallback{#1}%
%    \end{macrocode}
% フォントサイズの変数を設定して、
%    \begin{macrocode}
  \pxrr@bind@param
  \pxrr@assign@fsize
%    \end{macrocode}
% オプションを解析する。
%    \begin{macrocode}
  \pxrr@parse@option\pxrr@option
%    \end{macrocode}
% ルビ文字入力をグループ列に分解する。
%    \begin{macrocode}
  \pxrr@decompbar{#2}%
  \let\pxrr@ruby@list\pxrr@res
  \edef\pxrr@ruby@count{\the\pxrr@cntr}%
  \let\pxrr@sruby@list\relax
%    \end{macrocode}
% 親文字入力をグループ列に分解する。
%    \begin{macrocode}
  \pxrr@decompbar{#1}%
  \let\pxrr@body@list\pxrr@res
  \edef\pxrr@body@count{\the\pxrr@cntr}%
%    \end{macrocode}
% 安全モードに関する処理を行う。
%    \begin{macrocode}
  \ifpxrr@safe@mode
    \pxrr@setup@safe@mode
  \fi
%    \end{macrocode}
% モードが“選択的”である場合、“普通の”モード
% （|m|・|j|・|g|）に帰着させる。
%    \begin{macrocode}
  \if\pxrr@mode@is@switching
    \pxrr@resolve@mode
  \fi
\ifpxrrDebug
  \pxrr@debug@show@input
\fi
%    \end{macrocode}
% 入力検査を行い、パスした場合は組版処理に進む。
%    \begin{macrocode}
  \pxrr@if@alive{%
    \if g\pxrr@mode
      \pxrr@ruby@check@g
      \pxrr@if@alive{%
        \ifnum\pxrr@body@count>\@ne
          \pxrr@ruby@main@mg
        \else
          \pxrr@ruby@main@g
        \fi
      }%
    \else
      \pxrr@ruby@check@m
      \pxrr@if@alive{\pxrr@ruby@main@m}%
    \fi
  }%
%    \end{macrocode}
% 後処理を行う。
%    \begin{macrocode}
  \pxrr@ruby@exit
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@truby@proc}
% |\pxrr@ruby@proc{|\jmeta{親文字列}|}{|\jmeta{上側ルビ文字列}^^A
% |}{|\jmeta{下側ルビ文字列}|}|\Means
% 両側ルビの場合の手続の本体。
%    \begin{macrocode}
\def\pxrr@truby@proc#1#2#3{%
  \pxrr@prepare@fallback{#1}%
%    \end{macrocode}
% フォントサイズの変数を設定して、
%    \begin{macrocode}
  \pxrr@bind@param
  \pxrr@assign@fsize
%    \end{macrocode}
% オプションを解析する。
%    \begin{macrocode}
  \pxrr@parse@option\pxrr@option
%    \end{macrocode}
% 両側のグループルビでは |pxrr@all@input| を利用するので、
% 入力文字列を設定する。
%    \begin{macrocode}
  \def\pxrr@all@input{{#1}{#2}{#3}}%
%    \end{macrocode}
% 入力文字列のグループ分解を行う。
%    \begin{macrocode}
  \pxrr@decompbar{#3}%
  \let\pxrr@sruby@list\pxrr@res
  \edef\pxrr@sruby@count{\the\pxrr@cntr}%
  \pxrr@decompbar{#2}%
  \let\pxrr@ruby@list\pxrr@res
  \edef\pxrr@ruby@count{\the\pxrr@cntr}%
  \pxrr@decompbar{#1}%
  \let\pxrr@body@list\pxrr@res
  \edef\pxrr@body@count{\the\pxrr@cntr}%
%    \end{macrocode}
% 安全モードに関する処理を行う。
%    \begin{macrocode}
  \ifpxrr@safe@mode
    \pxrr@setup@safe@mode
  \fi
  \if\pxrr@mode@is@switching
    \pxrr@resolve@mode
  \fi
\ifpxrrDebug
  \pxrr@debug@show@input
\fi
%    \end{macrocode}
% 入力検査を行い、パスした場合は組版処理に進む。
%    \begin{macrocode}
  \pxrr@if@alive{%
    \if g\pxrr@mode
      \pxrr@ruby@check@tg
      \pxrr@if@alive{\pxrr@ruby@main@tg}%
    \else
      \pxrr@ruby@check@tm
      \pxrr@if@alive{\pxrr@ruby@main@tm}%
    \fi
  }%
%    \end{macrocode}
% 後処理を行う。
%    \begin{macrocode}
  \pxrr@ruby@exit
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@setup@safe@mode}
% 安全モード用の設定。
%    \begin{macrocode}
\def\pxrr@setup@safe@mode{%
%    \end{macrocode}
% 単純グループルビに強制的に変更する。
% これに応じて、親文字列とルビ文字列のグループを1つに集成する。
%    \begin{macrocode}
  \let\pxrr@mode=g\relax
  \pxrr@unite@group\pxrr@body@list
  \def\pxrr@body@count{1}%
  \pxrr@unite@group\pxrr@ruby@list
  \def\pxrr@ruby@count{1}%
  \ifx\pxrr@sruby@list\relax\else
    \pxrr@unite@group\pxrr@sruby@list
    \def\pxrr@sruby@count{1}%
  \fi
%    \end{macrocode}
% “文字単位のスキャン”が必要な機能を無効にする。
%    \begin{macrocode}
  \chardef\pxrr@evensp\z@
  \chardef\pxrr@revensp\z@
  \chardef\pxrr@fullsize\z@
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@resolve@mode}
% 基本モードが“選択的”（|M|・|J|）である場合に、状況に応じて
% 適切な通常のモードに切り替える。
%    \begin{macrocode}
\def\pxrr@resolve@mode{%
  \ifnum\pxrr@body@count=\@ne
%    \end{macrocode}
% ルビグループが1つで親文字が複数ある場合にはグループルビを選択し、
%    \begin{macrocode}
    \ifnum\pxrr@ruby@count=\@ne
      \let\pxrr@pre\pxrr@decompose
      \let\pxrr@post\relax
      \pxrr@body@list
      \ifnum\pxrr@cntr=\@ne\else
        \let\pxrr@mode=g%
      \fi
    \fi
%    \end{macrocode}
% それ以外はモノルビ・熟語ルビを選択する。
%    \begin{macrocode}
    \if M\pxrr@mode \let\pxrr@mode=m\fi
    \if J\pxrr@mode \let\pxrr@mode=j\fi
\ifpxrrDebug
  \pxrr@debug@show@resolve@mode
\fi
%    \end{macrocode}
% |\pxrr@check@option| で行っている調整をやり直す。
%    \begin{macrocode}
    \if g\pxrr@mode
      \chardef\pxrr@athead\z@
    \fi
    \if g\pxrr@mode\else
      \chardef\pxrr@evensp\@ne
    \fi
  \else
    \pxrr@fatal@bad@switching
  \fi
}
%    \end{macrocode}
% \end{macro}
%
% \subsubsection{入力検査}
%
% グループ・文字の個数の検査を行う手続。
%
% \begin{macro}{\pxrr@ruby@check@g}
% グループルビの場合、ルビ文字グループと親文字グループの個数が
% 一致する必要がある。
% さらに、グループが複数（可動グループルビ）にできるのは、
% 和文ルビであり、
% しかも拡張機能が有効である場合に限られる。
%    \begin{macrocode}
\def\pxrr@ruby@check@g{%
  \ifnum\pxrr@body@count=\pxrr@ruby@count\relax
    \ifnum\pxrr@body@count=\@ne\else
      \ifpxrr@abody
        \pxrr@fatal@bad@movable
      \else\ifnum\pxrr@extra=\z@
        \pxrr@fatal@na@movable
      \fi\fi
    \fi
  \else
    \pxrr@fatal@bad@length\pxrr@body@count\pxrr@ruby@count
  \fi
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@ruby@check@m}
% モノルビ・熟語ルビの場合、親文字列は単一のグループからなる
% 必要がある。
% さらに、親文字列の《文字》の個数とルビ文字列のグループの個数が
% 一致する必要がある。
%    \begin{macrocode}
\def\pxrr@ruby@check@m{%
  \ifnum\pxrr@body@count=\@ne
%    \end{macrocode}
% ここで |\pxrr@body@list|／|count| を文字ごとの分解に置き換える。
%    \begin{macrocode}
    \let\pxrr@pre\pxrr@decompose
    \let\pxrr@post\relax
    \pxrr@body@list
    \let\pxrr@body@list\pxrr@res
    \edef\pxrr@body@count{\the\pxrr@cntr}%
    \ifnum\pxrr@body@count=\pxrr@ruby@count\relax\else
      \pxrr@fatal@bad@length\pxrr@body@count\pxrr@ruby@count
    \fi
  \else
    \pxrr@fatal@bad@mono
  \fi
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@ruby@check@tg}
% 両側のグループルビの場合。
% ルビが2つあることを除き、片側の場合と同じ。
%    \begin{macrocode}
\def\pxrr@ruby@check@tg{%
  \ifnum\pxrr@body@count=\pxrr@ruby@count\relax\else
    \pxrr@fatal@bad@length\pxrr@body@count\pxrr@ruby@count
  \fi
  \ifnum\pxrr@body@count=\pxrr@sruby@count\relax\else
    \pxrr@fatal@bad@length\pxrr@body@count\pxrr@sruby@count
  \fi
  \pxrr@if@alive{%
    \ifnum\pxrr@body@count=\@ne\else
      \ifpxrr@abody
        \pxrr@fatal@bad@movable
      \else\ifnum\pxrr@extra=\z@
        \pxrr@fatal@na@movable
      \fi\fi
    \fi
  }%
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@ruby@check@tm}
% 両側のモノルビの場合。
% ルビが2つあることを除き、片側の場合と同じ。
%    \begin{macrocode}
\def\pxrr@ruby@check@tm{%
  \ifnum\pxrr@body@count=\@ne
    \let\pxrr@pre\pxrr@decompose
    \let\pxrr@post\relax
    \pxrr@body@list
    \let\pxrr@body@list\pxrr@res
    \edef\pxrr@body@count{\the\pxrr@cntr}%
    \ifnum\pxrr@body@count=\pxrr@ruby@count\relax\else
      \pxrr@fatal@bad@length\pxrr@body@count\pxrr@ruby@count
    \fi
    \ifnum\pxrr@body@count=\pxrr@sruby@count\relax\else
      \pxrr@fatal@bad@length\pxrr@body@count\pxrr@sruby@count
    \fi
  \else
    \pxrr@fatal@bad@mono
  \fi
}
%    \end{macrocode}
% \end{macro}
%
% \subsubsection{ルビ組版処理}
%
% \begin{macro}{\ifpxrr@par@head}
% ルビ付文字列の出力位置が段落の先頭であるか。
%    \begin{macrocode}
\newif\ifpxrr@par@head
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@check@par@head}
% 現在の位置に基づいて |\ifpxrr@par@head| の値を設定する。
% 当然、何らかの出力を行う前に呼ぶ必要がある。
%    \begin{macrocode}
\def\pxrr@check@par@head{%
  \ifvmode
    \pxrr@par@headtrue
  \else
    \pxrr@par@headfalse
  \fi
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@if@last}
% |\pxrr@if@last{|\jmeta{真}|}{|\jmeta{偽}|}|\Means
% |\pxrr@pre/inter| の本体として使い、それが最後の |\pxrr@pre/inter|
% である（|\pxrr@post| の直前にある）場合に\jmeta{真}、ない場合に
% \jmeta{偽}に展開される。
% このマクロの呼出は |\pxrr@preinterpre| の本体の末尾でなければならない。
%    \begin{macrocode}
\def\pxrr@if@last#1#2#3{%
  \ifx#3\pxrr@post #1%
  \else #2%
  \fi
  #3%
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@inter@mono}
% モノルビのブロック間に挿入される空き。
% 和文間空白とする。
%    \begin{macrocode}
\def\pxrr@inter@mono{%
  \hskip\pxrr@iiskip\relax
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@takeout@any@protr}
% |\ifpxrr@any@protr| の値を |\pxrr@hbox| の外に出す。
% \Note
% color 不使用時は |\hbox| による 1 段のグループだけ処理すれば
% よいが、color 使用時は |\color@begingroup|〜|\color@endgroup|
% によるグループが生じるので、2 段分の処理が必要。
%
% color 不使用時の定義。
%    \begin{macrocode}
\def\pxrr@takeout@any@protr@nocolor{%
  \ifpxrr@any@protr
    \aftergroup\pxrr@any@protrtrue
  \fi
}
%    \end{macrocode}
% color 使用時の定義。
%    \begin{macrocode}
\def\pxrr@takeout@any@protr{%
  \ifpxrr@any@protr
    \aftergroup\pxrr@takeout@any@protr@a
  \fi
}
\def\pxrr@takeout@any@protr@a{%
  \aftergroup\pxrr@any@protrtrue
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@ruby@main@m}
% モノルビ。
%    \begin{macrocode}
\def\pxrr@ruby@main@m{%
  \pxrr@zip@list\pxrr@body@list\pxrr@ruby@list
  \let\pxrr@whole@list\pxrr@res
  \pxrr@check@par@head
  \pxrr@put@head@penalty
  \pxrr@any@protrfalse
\ifpxrrDebug
\pxrr@debug@show@recomp
\fi
%    \end{macrocode}
% |\ifpxrr@?intr| の値に応じて |\pxrr@locate@*@| の値を決定する。
% なお、両側で突出を禁止するのは不可であることに注意。
%    \begin{macrocode}
  \let\pxrr@locate@head@\pxrr@locate@inner
  \let\pxrr@locate@end@\pxrr@locate@inner
  \let\pxrr@locate@sing@\pxrr@locate@inner
  \ifpxrr@aprotr\else
    \let\pxrr@locate@end@\pxrr@locate@end
    \let\pxrr@locate@sing@\pxrr@locate@end
  \fi
  \ifpxrr@bprotr\else
    \let\pxrr@locate@head@\pxrr@locate@head
    \let\pxrr@locate@sing@\pxrr@locate@head
  \fi
  \def\pxrr@pre##1##2{%
    \pxrr@if@last{%
%    \end{macrocode}
% 単独ブロックの場合。
%    \begin{macrocode}
      \pxrr@compose@block\pxrr@locate@sing@{##1}{##2}%
      \pxrr@intrude@head
      \unhbox\pxrr@boxr
      \pxrr@intrude@end
      \pxrr@takeout@any@protr
    }{%
%    \end{macrocode}
% 先頭ブロックの場合。
%    \begin{macrocode}
      \pxrr@compose@block\pxrr@locate@head@{##1}{##2}%
      \pxrr@intrude@head
      \unhbox\pxrr@boxr
    }%
  }%
  \def\pxrr@inter##1##2{%
    \pxrr@if@last{%
%    \end{macrocode}
% 末尾ブロックの場合。
%    \begin{macrocode}
      \pxrr@compose@block\pxrr@locate@end@{##1}{##2}%
      \pxrr@inter@mono
      \unhbox\pxrr@boxr
      \pxrr@intrude@end
      \pxrr@takeout@any@protr
    }{%
%    \end{macrocode}
% 中間ブロックの場合。
%    \begin{macrocode}
      \pxrr@compose@block\pxrr@locate@inner{##1}{##2}%
      \pxrr@inter@mono
      \unhbox\pxrr@boxr
    }%
  }%
  \let\pxrr@post\@empty
  \setbox\pxrr@boxr\pxrr@hbox{\pxrr@whole@list}%
%    \end{macrocode}
% 熟語ルビ指定の場合、|\ifpxrr@any@protr| が真である場合は再調整する。
%    \begin{macrocode}
  \if j\pxrr@mode
    \ifpxrr@any@protr
      \pxrr@ruby@redo@j
    \fi
  \fi
  \unhbox\pxrr@boxr
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@ruby@redo@j}
% モノルビ処理できない（ルビが長くなるブロックがある）熟語ルビを
% 適切に組みなおす。
% 現状では、単純にグループルビの組み方にする。
%    \begin{macrocode}
\def\pxrr@ruby@redo@j{%
  \pxrr@concat@list\pxrr@body@list
  \let\pxrr@body@list\pxrr@res
  \pxrr@concat@list\pxrr@ruby@list
  \let\pxrr@ruby@list\pxrr@res
  \pxrr@zip@single\pxrr@body@list\pxrr@ruby@list
  \let\pxrr@whole@list\pxrr@res
\ifpxrrDebug
\pxrr@debug@show@concat
\fi
  \let\pxrr@locate@sing@\pxrr@locate@inner
  \ifpxrr@aprotr\else
    \let\pxrr@locate@sing@\pxrr@locate@end
  \fi
  \ifpxrr@bprotr\else
    \let\pxrr@locate@sing@\pxrr@locate@head
  \fi
  \def\pxrr@pre##1##2{%
    \pxrr@compose@block\pxrr@locate@sing@{##1}{##2}%
    \pxrr@intrude@head
    \unhbox\pxrr@boxr
    \pxrr@intrude@end
  }%
  \let\pxrr@inter\@undefined
  \let\pxrr@post\@empty
  \setbox\pxrr@boxr\pxrr@hbox{\pxrr@whole@list}%
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@ruby@main@g}
% 単純グループルビの場合。
%
% グループが1つしかない前提なので多少冗長となるが、
% 基本的に |\pxrr@ruby@main@m| の処理を踏襲する。
%    \begin{macrocode}
\def\pxrr@ruby@main@g{%
  \pxrr@zip@list\pxrr@body@list\pxrr@ruby@list
  \let\pxrr@whole@list\pxrr@res
  \pxrr@check@par@head
  \pxrr@put@head@penalty
\ifpxrrDebug
\pxrr@debug@show@recomp
\fi
  \let\pxrr@locate@sing@\pxrr@locate@inner
  \ifpxrr@aprotr\else
    \let\pxrr@locate@sing@\pxrr@locate@end
  \fi
  \ifpxrr@bprotr\else
    \let\pxrr@locate@sing@\pxrr@locate@head
  \fi
  \def\pxrr@pre##1##2{%
    \pxrr@compose@block\pxrr@locate@sing@{##1}{##2}%
    \pxrr@intrude@head
    \unhbox\pxrr@boxr
    \pxrr@intrude@end
  }%
  \let\pxrr@inter\@undefined
  \let\pxrr@post\@empty
%    \end{macrocode}
% グループルビは |\ifpxrr@any@protr| の判定が不要なので直接出力する。
%    \begin{macrocode}
  \pxrr@whole@list
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@ruby@main@tm}
% 両側のモノルビの場合。
%    \begin{macrocode}
\def\pxrr@ruby@main@tm{%
  \pxrr@tzip@list\pxrr@body@list\pxrr@ruby@list\pxrr@sruby@list
  \let\pxrr@whole@list\pxrr@res
  \pxrr@check@par@head
  \pxrr@any@protrfalse
\ifpxrrDebug
\pxrr@debug@show@recomp
\fi
  \let\pxrr@locate@head@\pxrr@locate@inner
  \let\pxrr@locate@end@\pxrr@locate@inner
  \let\pxrr@locate@sing@\pxrr@locate@inner
  \ifpxrr@aprotr\else
    \let\pxrr@locate@end@\pxrr@locate@end
    \let\pxrr@locate@sing@\pxrr@locate@end
  \fi
  \ifpxrr@bprotr\else
    \let\pxrr@locate@head@\pxrr@locate@head
    \let\pxrr@locate@sing@\pxrr@locate@head
  \fi
  \def\pxrr@pre##1##2##3{%
    \pxrr@if@last{%
      \pxrr@compose@twoside@block\pxrr@locate@sing@
       {##1}{##2}{##3}%
      \pxrr@intrude@head
      \unhbox\pxrr@boxr
      \pxrr@intrude@end
      \pxrr@takeout@any@protr
    }{%
      \pxrr@compose@twoside@block\pxrr@locate@head@
       {##1}{##2}{##3}%
      \pxrr@intrude@head
      \unhbox\pxrr@boxr
    }%
  }%
  \def\pxrr@inter##1##2##3{%
    \pxrr@if@last{%
      \pxrr@compose@twoside@block\pxrr@locate@end@
       {##1}{##2}{##3}%
      \pxrr@inter@mono
      \unhbox\pxrr@boxr
      \pxrr@intrude@end
      \pxrr@takeout@any@protr
    }{%
      \pxrr@compose@twoside@block\pxrr@locate@inner
       {##1}{##2}{##3}%
      \pxrr@inter@mono
      \unhbox\pxrr@boxr
    }%
  }%
  \let\pxrr@post\@empty
  \setbox\pxrr@boxr\pxrr@hbox{\pxrr@whole@list}%
  \unhbox\pxrr@boxr
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@ruby@main@tg}
% 両側の単純グループルビの場合。
%    \begin{macrocode}
\def\pxrr@ruby@main@tg{%
  \pxrr@check@par@head
  \pxrr@put@head@penalty
  \let\pxrr@locate@sing@\pxrr@locate@inner
  \ifpxrr@aprotr\else
    \let\pxrr@locate@sing@\pxrr@locate@end
  \fi
  \ifpxrr@bprotr\else
    \let\pxrr@locate@sing@\pxrr@locate@head
  \fi
  \expandafter\pxrr@compose@twoside@block\expandafter\pxrr@locate@sing@
   \pxrr@all@input
  \pxrr@intrude@head
  \unhbox\pxrr@boxr
  \pxrr@intrude@end
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@ruby@main@mg}
% 未実装（呼出もない）。
%    \begin{macrocode}
\let\pxrr@ruby@main@mg\@undefined
%    \end{macrocode}
% \end{macro}
%
% \subsubsection{前処理}
%
% ゴースト処理する。そのため、展開不能命令が…。
%
% \begin{macro}{\ifpxrr@ghost}
% 実行中のルビ命令でゴースト処理が有効か。
%    \begin{macrocode}
\newif\ifpxrr@ghost
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@jprologue}
% 和文ルビ用の開始処理。
%    \begin{macrocode}
\def\pxrr@jprologue{%
%    \end{macrocode}
% ゴースト処理を行う場合、一番最初に現れる展開不能トークンが
% ゴースト文字（全角空白）であることが肝要である。
%    \begin{macrocode}
  \ifpxrr@jghost
    \pxrr@jghost@char
    \pxrr@inhibitglue
  \fi
%    \end{macrocode}
% ルビの処理の本体は全てこのグループの中で行われる。
%    \begin{macrocode}
  \begingroup
    \pxrr@abodyfalse
    \pxrr@csletcs{ifpxrr@ghost}{ifpxrr@jghost}%
%    \end{macrocode}
% 出力した全角空白の幅だけ戻しておく。
%    \begin{macrocode}
    \ifpxrr@jghost
      \setbox\pxrr@boxa\hbox{\pxrr@jghost@char}%
      \kern-\wd\pxrr@boxa
    \fi
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@aghost}
% 欧文用のゴースト文字の定義。
% 合成語記号はT1エンコーディングの位置23にある。
% 従って、T1のフォントが必要になるが、ここでは
% Latin Modern Romanを2.5\,ptのサイズで用いる。
% 極小のサイズにしているのは、合成語記号の高さが影響する可能性を
% 避けるためである。
% LMフォントの{\TeX}フォント名は版により異なるようなので、
% NFSSを通して目的のフォントのfontdefを得ている。
% （グループ内で |\usefont{T1}{lmr}{m}{n}| を呼んでおくと、
% 大域的に |\T1/lmr/m/n/2.5| が定義される。）
%    \begin{macrocode}
\chardef\pxrr@aghostchar=23 % compwordmark
\let\pxrr@aghost\relax
\let\pxrr@aghostfont\relax
\def\pxrr@setup@aghost{%
  \global\let\pxrr@setup@aghost\relax
  \IfFileExists{t1lmr.fd}{%
    \begingroup
      \fontsize{2.5}{0}\usefont{T1}{lmr}{m}{n}%
    \endgroup
    \global\pxrr@letcs\pxrr@aghostfont{T1/lmr/m/n/2.5}%
    \gdef\pxrr@aghost{{\pxrr@aghostfont\pxrr@aghostchar}}%
    \pxrr@force@nonpunct@achar{\pxrr@aghostchar}%
  }{%else
    \pxrr@warn{Ghost embedding for \string\aruby\space
      is disabled,\MessageBreak
      since package lmodern is missing}%
    \global\pxrr@aghostfalse
    \global\let\pxrr@aghosttrue\relax
  }%
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@aprologue}
% 欧文ルビ用の開始処理。
%    \begin{macrocode}
\def\pxrr@aprologue{%
  \ifpxrr@aghost
    \pxrr@aghost
  \fi
  \begingroup
    \pxrr@abodytrue
    \pxrr@csletcs{ifpxrr@ghost}{ifpxrr@aghost}%
}
%    \end{macrocode}
% \end{macro}
%
% \subsubsection{後処理}
%
% ゴースト処理する。
%
% \begin{macro}{\pxrr@ruby@exit}
% 出力を終えて、最後に呼ばれるマクロ。
% 致命的エラーが起こった場合はフォールバック処理を行う。
% その後は、和文ルビと欧文ルビで処理が異なる。
%    \begin{macrocode}
\def\pxrr@ruby@exit{%
  \ifpxrr@fatal@error
    \pxrr@fallback
  \fi
  \ifpxrr@abody
    \expandafter\pxrr@aepilogue
  \else
    \expandafter\pxrr@jepilogue
  \fi
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@jepilogue}
% 和文の場合の終了処理。
% 開始処理と同様、全角空白をゴースト文字に用いる。
%    \begin{macrocode}
\def\pxrr@jepilogue{%
    \ifpxrr@jghost
      \setbox\pxrr@boxa\hbox{\pxrr@jghost@char}%
      \kern-\wd\pxrr@boxa
    \fi
%    \end{macrocode}
% |\pxrr@?prologue| の中の |\begingroup| で始まるグループを閉じる。
%    \begin{macrocode}
  \endgroup
  \ifpxrr@jghost
    \pxrr@inhibitglue
    \pxrr@jghost@char
  \fi
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@aepilogue}
% 欧文の場合の終了処理。
% 合成語記号をゴースト文字に用いる。
%    \begin{macrocode}
\def\pxrr@aepilogue{%
  \endgroup
  \ifpxrr@aghost
    \pxrr@aghost
  \fi
}
%    \end{macrocode}
% \end{macro}
%
% \subsection{デバッグ用出力}
%
%    \begin{macrocode}
\def\pxrr@debug@show@input{%
  \typeout{----\pxrr@pkgname\space input:^^J%
    ifpxrr@abody = \meaning\ifpxrr@abody^^J%
    ifpxrr@truby = \meaning\ifpxrr@truby^^J%
    pxrr@ruby@fsize = \pxrr@ruby@fsize^^J%
    pxrr@body@zw = \pxrr@body@zw^^J%
    pxrr@ruby@zw = \pxrr@ruby@zw^^J%
    pxrr@iiskip = \pxrr@iiskip^^J%
    pxrr@iaiskip = \pxrr@iaiskip^^J%
    pxrr@htratio = \pxrr@htratio^^J%
    pxrr@ruby@raise = \pxrr@ruby@raise^^J%
    pxrr@ruby@lower = \pxrr@ruby@lower^^J%
    ifpxrr@bprotr = \meaning\ifpxrr@bprotr^^J%
    ifpxrr@aprotr = \meaning\ifpxrr@aprotr^^J%
    pxrr@side = \the\pxrr@side^^J%
    pxrr@evensp = \the\pxrr@evensp^^J%
    pxrr@fullsize = \the\pxrr@fullsize^^J%
    pxrr@bscomp = \meaning\pxrr@bscomp^^J%
    pxrr@ascomp = \meaning\pxrr@ascomp^^J%
    ifpxrr@bnobr = \meaning\ifpxrr@bnobr^^J%
    ifpxrr@anobr = \meaning\ifpxrr@anobr^^J%
    ifpxrr@bfintr = \meaning\ifpxrr@bfintr^^J%
    ifpxrr@afintr = \meaning\ifpxrr@afintr^^J%
    pxrr@bintr = \pxrr@bintr^^J%
    pxrr@aintr = \pxrr@aintr^^J%
    pxrr@athead = \the\pxrr@athead^^J%
    pxrr@mode = \meaning\pxrr@mode^^J%
    ifpxrr@athead@given = \meaning\ifpxrr@athead@given^^J%
    ifpxrr@mode@given = \meaning\ifpxrr@mode@given^^J%
    pxrr@body@list = \meaning\pxrr@body@list^^J%
    pxrr@body@count = \@nameuse{pxrr@body@count}^^J%
    pxrr@ruby@list = \meaning\pxrr@ruby@list^^J%
    pxrr@ruby@count = \@nameuse{pxrr@ruby@count}^^J%
    pxrr@end@kinsoku = \pxrr@end@kinsoku^^J%
    ----
  }%
}
\def\pxrr@debug@show@recomp{%
  \typeout{----\pxrr@pkgname\space recomp:^^J%
    pxrr@body@list = \meaning\pxrr@body@list^^J%
    pxrr@body@count = \pxrr@body@count^^J%
    pxrr@ruby@list = \meaning\pxrr@ruby@list^^J%
    pxrr@ruby@count = \pxrr@ruby@count^^J%
    pxrr@res = \meaning\pxrr@res^^J%
    ----
  }%
}
\def\pxrr@debug@show@concat{%
  \typeout{----\pxrr@pkgname\space concat:^^J%
    pxrr@body@list = \meaning\pxrr@body@list^^J%
    pxrr@ruby@list = \meaning\pxrr@ruby@list^^J%
    pxrr@whole@list = \meaning\pxrr@whole@list^^J%
    ----
  }%
}
\def\pxrr@debug@show@resolve@mode{%
  \typeout{----\pxrr@pkgname\space resolve-mode:
    \meaning\pxrr@mode}%
}
%    \end{macrocode}
%
%^^A------------------------------------
% \section{実装（圏点関連）}
%
% \subsection{エラーメッセージ}
%
% 指定の名前の圏点文字が未登録の場合。
%    \begin{macrocode}
\def\pxrr@warn@na@kmark#1{%
  \pxrr@warn{Unavailable kenten mark '#1'}%
}
%    \end{macrocode}
%
% パラメタ設定命令で無効な値が指定された場合。
%    \begin{macrocode}
\def\pxrr@err@invalid@value#1{%
  \pxrr@error{Invalid value '#1'}%
      {\@eha}%
}
%    \end{macrocode}
%
% \subsection{パラメタ}
%
% \subsubsection{全般設定}
%
% \begin{macro}{\pxrr@k@ymark}
% 横組の主の圏点マークのコード。
%    \begin{macrocode}
\let\pxrr@k@ymark\@undefined
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@k@ysmark}
% 横組の副の圏点マークのコード。
%    \begin{macrocode}
\let\pxrr@k@ysmark\@undefined
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@k@tmark}
% 縦組の主の圏点マークのコード。
%    \begin{macrocode}
\let\pxrr@k@tmark\@undefined
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@k@tsmark}
% 縦組の服の圏点マークのコード。
%    \begin{macrocode}
\let\pxrr@k@tsmark\@undefined
%    \end{macrocode}
% \end{macro}
%
% 圏点マークの初期値の設定。
%    \begin{macrocode}
\AtEndOfPackage{%
  \pxrr@k@get@mark\pxrr@k@ymark{bullet*}%
  \pxrr@k@get@mark\pxrr@k@ysmark{sesame*}%
  \pxrr@k@get@mark\pxrr@k@tmark{sesame*}%
  \pxrr@k@get@mark\pxrr@k@tsmark{bullet*}%
}
%    \end{macrocode}
%
% \begin{macro}{\pxrr@k@ruby@font}
% 圏点用フォント切替命令。
%    \begin{macrocode}
\let\pxrr@k@ruby@font\@empty
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@k@size@ratio}
% 圏点文字サイズ。
% （|\kentensizeratio|）。
% 実数値マクロ。
%    \begin{macrocode}
\def\pxrr@k@size@ratio{0.5}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\ifpxrr@k@ghost}
% ゴースト処理を行うか。
% スイッチ。
% \Note 圏点では和文ゴースト処理を必ず行う。
%    \begin{macrocode}
\newif\ifpxrr@k@ghost \pxrr@k@ghosttrue
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@k@inter@gap}
% 圏点と親文字の間の空き
% （|\kentenintergap|）。
% 実数値マクロ。
%    \begin{macrocode}
\def\pxrr@k@inter@gap{0}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@k@ruby@inter@gap}
% 圏点とルビの間の空き
% （|\kentenrubyintergap|）。
% 実数値マクロ。
%    \begin{macrocode}
\def\pxrr@k@ruby@inter@gap{0}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@k@d@side}
% 圏点を親文字の上下のどちらに付すか。
% 0 = 上側；1 = 下側。
% |\kentensetup| の |P|／|S| の設定。
% 整数定数。
%    \begin{macrocode}
\chardef\pxrr@k@d@side=0
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@k@d@mark}
% 圏点マークの種類。
% 0 = 主；1 = 副。
% |\kentensetup| の |p|／|s| の設定。
% 整数定数。
%    \begin{macrocode}
\chardef\pxrr@k@d@mark=0
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@k@ruby@combo}
% ルビと圏点が同時に適用された場合の挙動。
% 0 = ルビだけ出力；1 = ルビの上に圏点（同時付加）。
% |\kentenrubycombination| の設定値に対応する。
% 整数定数。
%    \begin{macrocode}
\chardef\pxrr@k@ruby@combo=1
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@k@d@full}
% 約物にも圏点を付加するか。
% 0 = 無効；1 = 有効。
% |\kentensetup| の |f|／|F| の設定。
% 整数定数。
%    \begin{macrocode}
\chardef\pxrr@k@d@full=0
%    \end{macrocode}
% \end{macro}
%
% \subsubsection{呼出時の設定}
%
% |\kenten| の |P|／|S| の設定は、|\pxrr@side| をルビと共用する。
%
% \begin{macro}{\pxrr@k@mark}
% 圏点マークの種類。
% 0 = 主；1 = 副。
% |\kenten| の |p|／|s| の設定。
% 整数定数。
%    \begin{macrocode}
\chardef\pxrr@k@mark=0
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@k@full}
% 約物にも圏点を付加するか。
% 0 = 無効；1 = 有効。
% |\kenten| の |f|／|F| の設定。
% 整数定数。
%    \begin{macrocode}
\chardef\pxrr@k@full=0
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@k@the@mark}
% 適用される圏点マークの命令。
%    \begin{macrocode}
\let\pxrr@k@the@mark\relax
%    \end{macrocode}
% \end{macro}
%
% \subsection{補助手続}
%
% \subsubsection{\cs{UTF}命令対応}
%
% \begin{macro}{\ifpxrr@avail@UTF}
% |\UTF| 命令が利用できるか。
% スイッチ。
%    \begin{macrocode}
\newif\ifpxrr@avail@UTF
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@decide@avail@UTF}
% |\ifpxrr@avail@UTF| の値を確定させる。
%    \begin{macrocode}
\def\pxrr@decide@avail@UTF{%
  \global\let\pxrr@decide@avail@UTF\relax
  \ifx\UTF\@undefined \global\pxrr@avail@UTFfalse
  \else \global\pxrr@avail@UTFtrue
  \fi
}
%    \end{macrocode}
% \end{macro}
%
% \subsubsection{リスト分解}
%
% \begin{macro}{\pxrr@k@decompose}
% |\pxrr@k@decompose{|\jmeta{テキスト}|}|\Means
% テキスト（圏点命令の引数）を分解した結果の圏点項目リスト
% を |\pxrr@res| に返す。
% \Note 圏点項目リストの形式\Means\par
% |\pxrr@entry|[|@XXX|]|{|\jmeta{引数}|}|……
% |\pxrr@entry|[|@XXX|]|{|\jmeta{引数}|}||\pxrr@post|
%    \begin{macrocode}
\def\pxrr@k@decompose#1{%
  \let\pxrr@res\@empty
  \pxrr@cntr=\z@
  \pxrr@k@decompose@loopa#1\pxrr@end
}
\def\pxrr@k@decompose@loopa{%
  \futurelet\pxrr@token\pxrr@k@decompose@loopb
}
\def\pxrr@k@decompose@loopb{%
  \pxrr@cond\ifx\pxrr@token\pxrr@end\fi{%
    \pxrr@appto\pxrr@res{\pxrr@post}%
  }{\pxrr@if@kspan@cmd\pxrr@token{%
    \pxrr@k@decompose@special\pxrr@k@decompose@kspan
  }{\pxrr@if@ruby@cmd\pxrr@token{%
    \pxrr@k@decompose@special\pxrr@k@decompose@ruby
  }{\pxrr@if@truby@cmd\pxrr@token{%
    \pxrr@k@decompose@special\pxrr@k@decompose@truby
  }{\pxrr@if@kenten@cmd\pxrr@token{%
    \pxrr@k@decompose@special\pxrr@k@decompose@kenten
  }{\pxrr@cond\ifx\pxrr@token\@sptoken\fi{%
    \pxrr@k@decompose@loope
  }{%
    \pxrr@setok{\pxrr@ifx{\pxrr@token\bgroup}}%
    \pxrr@k@decompose@loopc
  }}}}}}%
}
\def\pxrr@k@decompose@loopc#1{%
  \pxrr@appto\pxrr@res{\pxrr@entry}%
  \ifpxrr@ok
    \pxrr@appto\pxrr@res{{{#1}}}%
  \else
    \pxrr@appto\pxrr@res{{#1}}%
  \fi
  \pxrr@k@decompose@loopd
}
\def\pxrr@k@decompose@loopd{%
  \advance\pxrr@cntr\@ne
  \pxrr@k@decompose@loopa
}
\expandafter\def\expandafter\pxrr@k@decompose@loope\space{%
  \pxrr@okfalse
  \pxrr@k@decompose@loopc{ }%
}
\def\pxrr@k@decompose@special#1#2#{%
  #1{#2}%
}
\def\pxrr@k@decompose@kspan#1#2{%
  \pxrr@appto\pxrr@res{\pxrr@entry@kspan{#1{#2}}}%
  \pxrr@k@decompose@loopd
}
\def\pxrr@k@decompose@ruby#1#2#3{%
  \pxrr@appto\pxrr@res{\pxrr@entry@ruby{#1{#2}{#3}}}%
  \pxrr@k@decompose@loopd
}
\def\pxrr@k@decompose@truby#1#2#3#4{%
  \pxrr@appto\pxrr@res{\pxrr@entry@ruby{#1{#2}{#3}{#4}}}%
  \pxrr@k@decompose@loopd
}
\def\pxrr@k@decompose@kenten#1#2{%
  \pxrr@appto\pxrr@res{\pxrr@entry@kenten{#1{#2}}}%
  \pxrr@k@decompose@loopd
}
\def\pxrr@cmd@ruby{\jruby}
\def\pxrr@cmd@kenten{\jkenten}
\def\pxrr@if@ruby@cmd#1{%
  \if \ifcat\noexpand#1\relax
        \ifx#1\pxrr@cmd@ruby T%
        \else\ifx#1\jruby T%
        \else\ifx#1\aruby T%
        \else F%
        \fi\fi\fi
      \else F%
      \fi T\expandafter\@firstoftwo
  \else \expandafter\@secondoftwo
  \fi
}
\def\pxrr@if@truby@cmd#1{%
  \if \ifcat\noexpand#1\relax
        \ifx#1\truby T%
        \else\ifx#1\atruby T%
        \else F%
        \fi\fi
      \else F%
      \fi T\expandafter\@firstoftwo
  \else \expandafter\@secondoftwo
  \fi
}
\def\pxrr@if@kspan@cmd#1{%
  \pxrr@cond\ifx#1\kspan\fi
}
\def\pxrr@if@kenten@cmd#1{%
  \if \ifcat\noexpand#1\relax
        \ifx#1\pxrr@cmd@kenten T%
        \else\ifx#1\jkenten T%
        \else F%
        \fi\fi
      \else F%
      \fi T\expandafter\@firstoftwo
  \else \expandafter\@secondoftwo
  \fi
}
%    \end{macrocode}
% \end{macro}
%
% \subsection{パラメタ設定公開命令}
%
% \begin{macro}{\kentensetup}
% |\pxrr@k@parse@option| で解析した後、設定値を全般設定に
% コピーする。
%    \begin{macrocode}
\newcommand*\kentensetup[1]{%
  \pxrr@in@setuptrue
  \pxrr@fatal@errorfalse
  \pxrr@k@parse@option{#1}%
  \ifpxrr@fatal@error\else
    \let\pxrr@k@d@side\pxrr@side
    \let\pxrr@k@d@mark\pxrr@k@mark
    \let\pxrr@k@d@full\pxrr@k@full
  \fi
%    \end{macrocode}
% |\ifpxrr@in@setup| を偽に戻す。
% ただし |\ifpxrr@fatal@error| は書き換えられたままであることに注意。
%    \begin{macrocode}
  \pxrr@in@setupfalse
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\kentenfontsetup}
% 対応するパラメタを設定する。
%    \begin{macrocode}
\newcommand*\kentenfontsetup{}
\def\kentenfontsetup#{%
  \def\pxrr@k@ruby@font
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\kentensizeratio}
% 対応するパラメタを設定する。
%    \begin{macrocode}
\newcommand*\kentensizeratio[1]{%
  \edef\pxrr@k@size@ratio{#1}%
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\kentenintergap}
% 対応するパラメタを設定する。
%    \begin{macrocode}
\newcommand*\kentenintergap[1]{%
  \edef\pxrr@k@inter@gap{#1}%
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\kentenrubyintergap}
% 対応するパラメタを設定する。
%    \begin{macrocode}
\newcommand*\kentenrubyintergap[1]{%
  \edef\pxrr@k@ruby@inter@gap{#1}%
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\kentenmarkinyoko}
% \begin{macro}{\kentensubmarkinyoko}
% \begin{macro}{\kentenmarkintate}
% \begin{macro}{\kentensubmarkintate}
% 対応するパラメタを設定する。
%    \begin{macrocode}
\newcommand*\kentenmarkinyoko[1]{%
  \pxrr@k@get@mark\pxrr@k@ymark{#1}%
}
\newcommand*\kentensubmarkinyoko[1]{%
  \pxrr@k@get@mark\pxrr@k@ysmark{#1}%
}
\newcommand*\kentenmarkintate[1]{%
  \pxrr@k@get@mark\pxrr@k@tmark{#1}%
}
\newcommand*\kentensubmarkintate[1]{%
  \pxrr@k@get@mark\pxrr@k@tsmark{#1}%
}
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\kentenrubycombination}
% 対応するパラメタを設定する。
%    \begin{macrocode}
\chardef\pxrr@k@ruby@combo@ruby=0
\chardef\pxrr@k@ruby@combo@both=1
\newcommand*\kentenrubycombination[1]{%
  \pxrr@letcs\pxrr@tempa{pxrr@k@ruby@combo@#1}%
  \ifx\pxrr@tempa\relax
    \pxrr@err@invalid@value{#1}%
  \else
    \let\pxrr@k@ruby@combo\pxrr@tempa
  \fi
}
%    \end{macrocode}
% \end{macro}
%
% \subsection{圏点文字}
%
% \begin{macro}{\pxrr@k@declare@mark}
% |\pxrr@k@declare@mark{|\jmeta{名前}|}{|\jmeta{本体}|}|\Means
% 圏点マーク命令を定義する。
%    \begin{macrocode}
\def\pxrr@k@declare@mark#1{%
  \global\@namedef{pxrr@k@mark@@#1}%
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@k@let@mark}
% |\pxrr@k@declare@mark{|\jmeta{名前}|}\CS|\Means
% 圏点マーク命令を |\let| で定義する。
%    \begin{macrocode}
\def\pxrr@k@let@mark#1{%
  \global\pxrr@cslet{pxrr@k@mark@@#1}%
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@k@get@mark}
% |\pxrr@k@get@mark\CS{|\jmeta{名前または定義本体}|}|\Means
% 指定の圏点マーク命令を |\CS| に代入する。
% 第2引数の先頭トークンがASCII英字の場合は名前と見なし、
% それ以外は定義本体のコードと見なす。
%    \begin{macrocode}
\def\pxrr@k@get@mark#1#2{%
  \futurelet\pxrr@token\pxrr@k@get@mark@a#2\pxrr@nil#1%
}
\def\pxrr@k@get@mark@a{%
  \pxrr@cond\ifcat A\noexpand\pxrr@token\fi{%
    \pxrr@k@get@mark@c
  }{%else
    \pxrr@k@get@mark@b
  }%
}
\def\pxrr@k@get@mark@b#1\pxrr@nil#2{%
  \def#2{#1}%
}
\def\pxrr@k@get@mark@c#1#2\pxrr@nil#3{%
  \ifnum`#1<128
    \pxrr@letcs\pxrr@tempa{pxrr@k@mark@@#1#2}%
    \ifx\pxrr@tempa\relax
      \pxrr@warn@na@kmark{#1#2}%
    \else
      \let#3\pxrr@tempa
    \fi
  \else
    \pxrr@k@get@mark@b#1#2\pxrr@nil#3%
  \fi
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@k@declare@mark@char}
% |\pxrr@k@declare@mark@char\CS{|\jmeta{二重コード}|}|\Means
% 指定のコード値の文字の（和文）chardefを |\CS| に代入する。
% ただし{\pTeX}でJISに無い文字
% （便宜的に和文空白のJISコード値|2121|で表す）
% の場合は代わりに |\pxrr@k@char@UTF| を利用する。
%    \begin{macrocode}
\def\pxrr@k@declare@mark@char#1#2{%
  \pxrr@k@declare@mark@char@a{#1}#2\pxrr@end
}
\def\pxrr@k@declare@mark@char@a#1#2:#3\pxrr@end{%
  \pxrr@jchardef\pxrr@tempa\pxrr@jc{#2:#3}%
  \ifnum\pxrr@tempa=\pxrr@zspace
%    \end{macrocode}
% エンジンが{\pTeX}でかつJISに無い文字である場合。
%    \begin{macrocode}
    \pxrr@k@declare@mark{#1}{\pxrr@k@char@UTF{#1}{#3}}%
  \else
    \pxrr@k@let@mark{#1}\pxrr@tempa
  \fi
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@k@char@UTF}
% |\pxrr@k@char@UTF{|\jmeta{名前}|}{|\jmeta{Unicode値}|}|\Means
% |\UTF{|\jmeta{Unicode値}|}| を実行するが、
% |\UTF| が利用不可の場合は、
% （最初の1回だけ）警告した上で何も出力しない。
%    \begin{macrocode}
\def\pxrr@k@char@UTF#1#2{%
  \pxrr@decide@avail@UTF
  \ifpxrr@avail@UTF
    \pxrr@k@declare@mark{#1}{\UTF{#2}}%
    \UTF{#2}%
  \else
    \pxrr@k@let@mark{#1}\@empty
    \pxrr@warn@na@kmark{#1}%
  \fi
}
%    \end{macrocode}
% \end{macro}
%
% 標準サポートの圏点マークの定義。
%    \begin{macrocode}
\pxrr@k@declare@mark@char{bullet}  {2121:2022}
\pxrr@k@declare@mark@char{triangle}{2225:25B2}
\pxrr@k@declare@mark@char{Triangle}{2224:25B3}
\pxrr@k@declare@mark@char{fisheye} {2121:25C9}
\pxrr@k@declare@mark@char{Circle}  {217B:25CB}
\pxrr@k@declare@mark@char{bullseye}{217D:25CE}
\pxrr@k@declare@mark@char{circle}  {217C:25CF}
\pxrr@k@declare@mark@char{Bullet}  {2121:25E6}
\pxrr@k@declare@mark@char{sesame}  {2121:FE45}
\pxrr@k@declare@mark@char{Sesame}  {2121:FE46}
\pxrr@jchardef\pxrr@ja@dot=\pxrr@jc{2126:30FB}
\pxrr@jchardef\pxrr@ja@comma=\pxrr@jc{2122:3001}
\pxrr@k@declare@mark{bullet*}{%
  \pxrr@dima=\pxrr@ruby@zw\relax
  \hb@xt@\pxrr@dima{%
    \kern-.5\pxrr@dima
    \pxrr@if@in@tate{}{\lower.38\pxrr@dima}%
    \hb@xt@2\pxrr@dima{%
      \pxrr@dima=\f@size\p@
      \fontsize{2\pxrr@dima}{\z@}\selectfont
      \hss
      \pxrr@ja@dot
      \hss
    }%
    \hss
  }%
}
\pxrr@k@declare@mark{sesame*}{%
  \pxrr@dima=\pxrr@ruby@zw\relax
  \hb@xt@\pxrr@dima{%
    \pxrr@if@in@tate{\kern.1\pxrr@dima}{\kern.05\pxrr@dima}%
    \pxrr@if@in@tate{\lower.85\pxrr@dima}{\raise.3\pxrr@dima}%
    \hbox{%
      \pxrr@dima=\f@size\p@
      \fontsize{2.4\pxrr@dima}{\z@}\selectfont
      \pxrr@ja@comma
    }%
    \hss
  }%
}
%    \end{macrocode}
%
% \subsection{圏点オプション解析}
%
% \begin{macro}{\pxrr@k@parse@option}
% |\pxrr@k@parse@option{|\jmeta{オプション}|}|\Means
% \jmeta{オプション}を解析し、
% |\pxrr@side| や |\pxrr@k@mark| 等のパラメタを設定する。
%    \begin{macrocode}
\def\pxrr@k@parse@option#1{%
  \edef\pxrr@tempa{#1}%
  \let\pxrr@side\pxrr@k@d@side
  \let\pxrr@k@mark\pxrr@k@d@mark
  \let\pxrr@k@full\pxrr@k@d@full
  \expandafter\pxrr@k@parse@option@loop\pxrr@tempa @\pxrr@end
}
\def\pxrr@k@parse@option@loop#1{%
%    \end{macrocode}
% 圏点オプションの解析器は“有限状態”を持たないので
% 非常に単純である。
%    \begin{macrocode}
  \pxrr@letcs\pxrr@tempa{pxrr@k@po@PR@#1}%
  \pxrr@cond\ifx\pxrr@tempa\relax\fi{%
    \pxrr@fatal@knx@letter{#1}%
    \pxrr@k@parse@option@exit
  }{%
    \pxrr@tempa
    \pxrr@k@parse@option@loop
  }%
}
\def\pxrr@k@parse@option@exit#1\pxrr@end{%
  \ifpxrr@in@setup\else
    \pxrr@k@check@option
%    \end{macrocode}
% ここで |\pxrr@k@the@mark| を適切に定義する。
%    \begin{macrocode}
    \pxrr@if@in@tate{%
      \ifcase\pxrr@k@mark \let\pxrr@k@the@mark\pxrr@k@tmark
      \or \let\pxrr@k@the@mark\pxrr@k@tsmark
      \fi
    }{%
      \ifcase\pxrr@k@mark \let\pxrr@k@the@mark\pxrr@k@ymark
      \or \let\pxrr@k@the@mark\pxrr@k@ysmark
      \fi
    }%
  \fi
}
\def\pxrr@k@po@PR@@{%
  \pxrr@k@parse@option@exit
}
\def\pxrr@k@po@PR@P{%
  \chardef\pxrr@side\z@
}
\def\pxrr@k@po@PR@S{%
  \chardef\pxrr@side\@ne
}
\def\pxrr@k@po@PR@p{%
  \chardef\pxrr@k@mark\z@
}
\def\pxrr@k@po@PR@s{%
  \chardef\pxrr@k@mark\@ne
}
\def\pxrr@k@po@PR@F{%
  \chardef\pxrr@k@full\z@
}
\def\pxrr@k@po@PR@f{%
  \chardef\pxrr@k@full\@ne
}
%    \end{macrocode}
% \end{macro}
%
% \subsection{オプション整合性検査}
%
% 今のところ検査すべき点がない。
%    \begin{macrocode}
\def\pxrr@k@check@option{%
}
%    \end{macrocode}
%
% \subsection{ブロック毎の組版}
%
% \begin{macro}{\pxrr@k@compose@block}
% |\pxrr@k@compose@block{|\jmeta{親文字ブロック}|}|^^A
% |{|\jmeta{圏点の個数}|}|\Means
% 1つのブロックの組版処理。
% ボックス |\pxrr@boxb| に圏点1つを組版したものが入っている
% 必要がある。
% なお、圏点はゼロ幅に潰した形で扱う前提のため、
% |\pxrr@boxb| の幅はゼロでないといけない。
%
% 基本的に、ルビ用の |\pxrr@compose@oneside@block| を非常に簡略化
% した処理になっている。
%    \begin{macrocode}
\def\pxrr@k@compose@block#1#2{%
  \setbox\pxrr@boxa\pxrr@hbox{#1}%
%    \end{macrocode}
% |\pxrr@evenspace@int| を使うために辻褄を合わせる。
% すなわち、|\copy\pxrr@boxb| を圏点個数分だけ反復した
% リストを |\pxrr@res| に入れて、“圏点の自然長”に
% 当たる |\pxrr@natwd| をゼロとする。
%    \begin{macrocode}
  \pxrr@k@make@rep@list{\copy\pxrr@boxb}{#2}%
  \let\pxrr@natwd\pxrr@zeropt
  \pxrr@evenspace@int\pxrr@locate@inner\pxrr@boxr
       \relax{\wd\pxrr@boxa}%
  \setbox\z@\hbox{%
    \ifnum\pxrr@side=\z@
      \raise\pxrr@ruby@raise\box\pxrr@boxr
    \else
      \lower\pxrr@ruby@lower\box\pxrr@boxr
    \fi
  }%
  \ht\z@\z@ \dp\z@\z@
  \@tempdima\wd\z@
  \setbox\pxrr@boxr\hbox{%
    \box\z@
    \kern-\@tempdima
    \box\pxrr@boxa
  }%
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@k@make@rep@list}
% |\pxrr@k@make@rep@list{|\jmeta{要素}|}{|\jmeta{回数}|}|\Means
% 要素を指定の回数だけ反復したリストを |\pxrr@res| に代入する。
%    \begin{macrocode}
\def\pxrr@k@make@rep@list#1#2{%
  \def\pxrr@res{\pxrr@pre{#1}}%
  \pxrr@cntr=#2\relax
  \ifnum\pxrr@cntr>\@ne
    \@tempcnta\pxrr@cntr \advance\@tempcnta\m@ne
    \@whilenum{\@tempcnta>\z@}\do{%
      \pxrr@appto\pxrr@res{\pxrr@inter{#1}}%
      \advance\@tempcnta\m@ne
    }%
  \fi
  \pxrr@appto\pxrr@res{\pxrr@post}%
}
%    \end{macrocode}
% \end{macro}
%
% \subsection{圏点項目}
%
% \begin{itemize}
% \item 圏点項目リスト\Means
%   テキストを |\pxrr@k@decompose| で分解した結果のリスト。
% \item 圏点項目\Means
%   圏点リストに含まれる |\pxrr@entry|[|@XXX|]|{...}| という形式のこと。
%   圏点項目は直接に実行する（出力する）ことができる。
% \item 圏点ブロック\Means
%   一つの《文字》に圏点を付加して出力したもの。
% \item 参照文字コード\Means
%   圏点項目の出力の前後の禁則ペナルティの扱いにおいて、
%   「ある文字と同等」と扱う場合の、その文字の文字コード。
% \end{itemize}
%
% ※現状では、まず |\pxrr@kenten@entry@XXX| というマクロを定義して
% 圏点命令の実行時にそれを |\pxrr@entry@XXX| にコピーする、という
% 手続きを採っている。
% （ただそうする意味が全く無い気がする。）
%
% \begin{macro}{\ifpxrr@k@first@entry}
% 先頭の項目であるか。
%    \begin{macrocode}
\newif\ifpxrr@k@first@entry
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\ifpxrr@k@last@entry}
% 末尾の項目であるか。
%    \begin{macrocode}
\newif\ifpxrr@k@last@entry
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\ifpxrr@k@prev@is@block}
% 直前の項目の結果が圏点ブロックであったか。
%    \begin{macrocode}
\newif\ifpxrr@k@prev@is@block
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@k@accum@res}
% 累積の直接出力。
%    \begin{macrocode}
\let\pxrr@k@accum@res\relax
%    \end{macrocode}
% \end{macro}
%
% 以下の3つの変数は“項目の下請けマクロ”が値を返すべきもの。
% これらに加えて、|\pxrr@res| と |\pxrr@boxr| の一方に
% （組版の）結果を返す必要がある。
%
% \begin{macro}{\pxrr@k@prebreakpenalty}
% 圏点項目の前禁則ペナルティ。
%    \begin{macrocode}
\mathchardef\pxrr@k@prebreakpenalty\z@
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@k@postbreakpenalty}
% 圏点項目の後禁則ペナルティ。
%    \begin{macrocode}
\mathchardef\pxrr@k@postbreakpenalty\z@
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@k@entry@res@type}
% 項目の出力のタイプ。
% 0=直接出力；1=ボックス出力；2=圏点ブロック。
% 0の場合、出力は |\pxrr@res| にあり、それ以外は、
% 出力は |\pxrr@boxr| にある。
%    \begin{macrocode}
\chardef\pxrr@k@entry@res@type\z@
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@k@list@pre}
% 圏点項目リストの出力の開始時に行う処理。
%    \begin{macrocode}
\def\pxrr@k@list@pre{%
  \pxrr@k@first@entrytrue
  \pxrr@k@last@entryfalse
  \pxrr@k@prev@is@blockfalse
  \let\pxrr@k@accum@res\@empty
  \chardef\pxrr@k@block@seq@state\z@
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@k@entry@with}
% 補助マクロ。
% 各種圏点項目の共通の処理を行う。
% \Note |#1| は各圏点項目命令の下請けのマクロで、|#2| は
% 圏点項目の引数。
%    \begin{macrocode}
\def\pxrr@k@entry@with#1#2{%
  \pxrr@if@last{%
    \pxrr@k@last@entrytrue
    \pxrr@k@entry@with@a#1{#2}%
  }{%
    \pxrr@k@entry@with@a#1{#2}%
  }%
}
\def\pxrr@k@entry@with@a#1#2{%
  \mathchardef\pxrr@k@prebreakpenalty\z@
  \mathchardef\pxrr@k@postbreakpenalty\z@
%    \end{macrocode}
% 下請けマクロを実行して結果を得る。
%    \begin{macrocode}
  #1{#2}%
%\typeout{%
%first=\meaning\ifpxrr@k@first@entry^^J%
%last=\meaning\ifpxrr@k@last@entry^^J%
%prev=\meaning\ifpxrr@k@prev@is@block^^J%
%res=\meaning\pxrr@res^^J%
%type=\meaning\pxrr@k@entry@res@type^^J%
%prepen=\the\pxrr@k@prebreakpenalty^^J%
%postpen=\the\pxrr@k@postbreakpenalty}%
%    \end{macrocode}
% 累積直接出力の処理。
%    \begin{macrocode}
  \ifnum\pxrr@k@entry@res@type=\z@
    \expandafter\pxrr@appto\expandafter\pxrr@k@accum@res
        \expandafter{\pxrr@res}%
  \else
    \pxrr@k@accum@res
    \let\pxrr@k@accum@res\@empty
  \fi
%    \end{macrocode}
% 前禁則ペナルティを入れる。
%    \begin{macrocode}
  \ifnum\pxrr@k@prebreakpenalty>\z@
    \@tempcntb\lastpenalty \unpenalty
    \advance\@tempcntb\pxrr@k@prebreakpenalty
    \penalty\@tempcntb
  \fi
%    \end{macrocode}
% 圏点ブロックが連続する場合は和文間空白を入れる。
%    \begin{macrocode}
  \ifnum\pxrr@k@entry@res@type=\tw@
    \ifpxrr@k@prev@is@block
      \pxrr@inter@mono
    \fi
    \pxrr@k@prev@is@blocktrue
  \else
    \pxrr@k@prev@is@blockfalse
  \fi
%    \end{macrocode}
% ボックスの結果を実際に出力する。
%    \begin{macrocode}
  \ifnum\pxrr@k@entry@res@type>\z@
    \unhbox\pxrr@boxr
  \fi
%    \end{macrocode}
% 後禁則ペナルティを入れる。
%    \begin{macrocode}
  \ifnum\pxrr@k@postbreakpenalty>\z@
    \penalty\pxrr@k@postbreakpenalty
  \fi
%    \end{macrocode}
% 次の項目に進む。
%    \begin{macrocode}
  \pxrr@k@first@entryfalse
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@k@list@post}
% 圏点項目リストの出力の最後に行う処理。
%    \begin{macrocode}
\def\pxrr@k@list@post{%
  \pxrr@k@accum@res
  \let\pxrr@k@accum@res\@empty
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@kenten@entry}
% 一般の《文字》を表す圏点項目 |\pxrr@entry{|\jmeta{文字}|}| の処理。
% 圏点を1つ付けて出力する。
%    \begin{macrocode}
\def\pxrr@kenten@entry{%
  \pxrr@k@entry@with\pxrr@kenten@entry@
}
\def\pxrr@kenten@entry@#1{%
  \pxrr@k@check@char{#1}%
  \ifpxrr@ok
    \pxrr@k@compose@block{#1}\@ne
    \chardef\pxrr@k@entry@res@type=\tw@
  \else
    \def\pxrr@res{#1}%
    \chardef\pxrr@k@entry@res@type=\z@
  \fi
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@kenten@entry@kspan}
% |\kspan| 命令を表す圏点項目\ 
% |\pxrr@entry@kspan{\kspan{|\jmeta{テキスト}|}}| の処理。
% テキストの幅が“およそ$n$全角”である場合に、
% $n$個の圏点をルビ均等割りで配置して出力する。
%    \begin{macrocode}
\def\pxrr@kenten@entry@kspan{%
  \pxrr@k@entry@with\pxrr@kenten@entry@kspan@
}
\def\pxrr@kenten@entry@kspan@#1{%
  \pxrr@kenten@entry@kspan@a#1%
}
\def\pxrr@kenten@entry@kspan@a#1{%
%    \end{macrocode}
% |\kspan|（=\,|#1|）が |*| 付かを調べる。
%    \begin{macrocode}
  \@ifstar{%
    \@testopt\pxrr@kenten@entry@kspan@c{}%
  }{%
    \@testopt\pxrr@kenten@entry@kspan@b{}%
  }%
}
\def\pxrr@kenten@entry@kspan@b[#1]#2{%
%    \end{macrocode}
% ($n-1/4$)zw以上($n+3/4$)zw未満の時に“およそ$n$全角”と見なす。
%    \begin{macrocode}
  \setbox\z@\pxrr@hbox{#2}%
  \@tempdima\pxrr@body@zw\relax
  \@tempdimb\wd\z@ \advance\@tempdimb.25\@tempdima
  \divide\@tempdimb\@tempdima
  \edef\pxrr@kenten@entry@tempa{\number\@tempdimb}%
  \pxrr@k@compose@block{#2}\pxrr@kenten@entry@tempa
  \chardef\pxrr@k@entry@res@type=\tw@
}
\def\pxrr@kenten@entry@kspan@c[#1]#2{%
%    \end{macrocode}
% |\kspan*| となっている場合。
% この時は圏点を付加せず直接出力する。
%    \begin{macrocode}
  \def\pxrr@res{#2}%
  \chardef\pxrr@k@entry@res@type=\z@
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@kenten@entry@kenten}
% ネストした |\kenten| 命令の圏点項目。
% 単純にその |\kenten| を実行したものを出力とする。
% すなわち、内側の圏点の設定のみが生きる。
%    \begin{macrocode}
\def\pxrr@kenten@entry@kenten{%
  \pxrr@k@entry@with\pxrr@kenten@entry@kenten@
}
\def\pxrr@kenten@entry@kenten@#1{%
%    \end{macrocode}
% この場合は圏点ブロックとは見なさないことに注意。
%    \begin{macrocode}
  \setbox\pxrr@boxr\hbox{#1}%
  \chardef\pxrr@k@entry@res@type=\@ne
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@kenten@entry@ruby}
% ルビ命令の圏点項目。
%    \begin{macrocode}
\def\pxrr@kenten@entry@ruby{%
  \pxrr@k@entry@with\pxrr@kenten@entry@ruby@
}
\def\pxrr@kenten@entry@ruby@#1{%
  \pxrr@apply@combotrue
  \setbox\pxrr@boxr\hbox{#1}%
  \chardef\pxrr@k@entry@res@type=\@ne
}
%    \end{macrocode}
% \end{macro}
%
% \subsubsection{\cs{kspan}命令}
%
% \begin{macro}{\kspan}
% テキストの幅に相応した個数の圏点を付ける命令。
% |\kenten| の引数のテキストの中で使う。
%
% |\kenten| の外で使われた場合は単純に引数を出力するだけ。
%
% \Note 処理の都合上、オプション引数を持たせているが、
% 実際には（現在は）これは使われない。
%    \begin{macrocode}
\newcommand*\kspan{%
  \@ifstar{%
    \@testopt\pxrr@kspan@a{}%
  }{%
    \@testopt\pxrr@kspan@a{}%
  }%
}
\pxrr@add@protect\kspan
\def\pxrr@kspan@a[#1]#2{%
  \begingroup
    #2%
  \endgroup
}
%    \end{macrocode}
% \end{macro}
%
% \subsection{自動抑止の検査}
%
% \begin{macro}{\pxrr@k@check@char}
% 通常項目（|\pxrr@entry|）の引数を検査して、
% 圏点を付加すべきか否かをスイッチ |pxrr@ok| に返す。
% また、項目の前禁則・後禁則ペナルティを設定する。
%
% 引数が（単一の）通常文字である時はその文字、
% 引数がグループの場合は和文空白の内部文字コードを |\pxrr@cntr| に
% 返す（禁則ペナルティを後で見られるように）。
%    \begin{macrocode}
\def\pxrr@k@check@char#1{%
  \futurelet\pxrr@token\pxrr@k@check@char@a#1\pxrr@end
}
\def\pxrr@k@check@char@a#1\pxrr@end{%
  \pxrr@cond\ifx\pxrr@token\bgroup\fi{%
%    \end{macrocode}
% グループには圏点を付ける。
%    \begin{macrocode}
    \pxrr@oktrue
  }{\pxrr@cond\ifx\pxrr@token\@sptoken\fi{%
%    \end{macrocode}
% 欧文空白には圏点を付けない。
%    \begin{macrocode}
    \pxrr@okfalse
  }{%
    \pxrr@check@char\pxrr@token
    \ifcase\pxrr@cntr
%    \end{macrocode}
% 通常文字でないので圏点を付けない。
%    \begin{macrocode}
      \pxrr@okfalse
    \or
%    \end{macrocode}
% 欧文の通常文字。圏点を付ける。
%    \begin{macrocode}
      \pxrr@oktrue
      \chardef\pxrr@check@char@temp\z@
    \or
%    \end{macrocode}
% 和文の通常文字。圏点を付ける。
%    \begin{macrocode}
      \pxrr@oktrue
      \chardef\pxrr@check@char@temp\@ne
    \fi
%    \end{macrocode}
% 約物の圏点付加が無効の場合は、引数の文字が約物であるか検査し、
% そうである場合は圏点を付けない。
%    \begin{macrocode}
    \ifnum\pxrr@k@full=\z@\ifpxrr@ok
      \pxrr@check@punct@char{`#1}\pxrr@check@char@temp
      \ifpxrr@ok \pxrr@okfalse
      \else \pxrr@oktrue
      \fi
    \fi\fi
    \ifpxrr@ok
      \pxrr@get@prebreakpenalty\@tempcnta{`#1}%
      \mathchardef\pxrr@k@prebreakpenalty\@tempcnta
      \pxrr@get@postbreakpenalty\@tempcnta{`#1}%
      \mathchardef\pxrr@k@postbreakpenalty\@tempcnta
    \fi
  }}%
}
%    \end{macrocode}
% \end{macro}
%
% \subsection{メインです}
%
% \subsubsection{エントリーポイント}
%
% \begin{macro}{\kenten}
% \begin{macro}{\jkenten}
% 圏点の公開命令。
% |\jkenten| を頑強な命令として定義した上で、|\kenten| はそれに
% 展開されるマクロに（未定義ならば）定義する。
%    \begin{macrocode}
\AtBeginDocument{%
  \providecommand*{\kenten}{\jkenten}%
}
\newcommand*{\jkenten}{%
  \pxrr@k@prologue
  \pxrr@kenten
}
\pxrr@add@protect\jkenten
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\pxrr@kenten}
% オプションの処理を行う。
%    \begin{macrocode}
\def\pxrr@kenten{%
  \@testopt\pxrr@kenten@a{}%
}
\def\pxrr@kenten@a[#1]{%
  \def\pxrr@option{#1}%
  \ifpxrr@safe@mode
%    \end{macrocode}
% 安全モードでは圏点機能は無効なので、フォールバックとして
% 引数のテキストをそのまま出力する。
%    \begin{macrocode}
    \expandafter\@firstofone
  \else
    \expandafter\pxrr@kenten@proc
  \fi
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@k@bind@param}
% “呼出時変数”へのコピーを行う。
%    \begin{macrocode}
\def\pxrr@k@bind@param{%
  \let\pxrr@c@ruby@font\pxrr@k@ruby@font
  \let\pxrr@c@size@ratio\pxrr@k@size@ratio
  \let\pxrr@c@inter@gap\pxrr@k@inter@gap
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@kenten@proc}
% |\pxrr@kenten@proc{|\jmeta{親文字列}|}|\Means
% これが手続の本体となる。
%    \begin{macrocode}
\def\pxrr@kenten@proc#1{%
  \pxrr@prepare@fallback{#1}%
  \pxrr@k@bind@param
  \pxrr@assign@fsize
  \pxrr@k@parse@option\pxrr@option
  \pxrr@if@alive{%
    \pxrr@k@decompose{#1}%
    \let\pxrr@body@list\pxrr@res
    \pxrr@kenten@main
  }%
  \pxrr@kenten@exit
}
%    \end{macrocode}
% \end{macro}
%
% \subsubsection{組版処理}
%
% \begin{macro}{\pxrr@kenten@main}
% 圏点の組版処理。
%    \begin{macrocode}
\def\pxrr@kenten@main{%
  \setbox\pxrr@boxb\pxrr@hbox@to\z@{%
    \pxrr@use@ruby@font
    \hss\pxrr@k@the@mark\hss
  }%
  \let\pxrr@entry\pxrr@kenten@entry
  \let\pxrr@entry@kspan\pxrr@kenten@entry@kspan
  \let\pxrr@entry@ruby\pxrr@kenten@entry@ruby
  \let\pxrr@entry@kenten\pxrr@kenten@entry@kenten
  \let\pxrr@post\pxrr@k@list@post
  \pxrr@k@list@pre
  \pxrr@body@list
}
%    \end{macrocode}
% \end{macro}
%
% \subsubsection{前処理}
%
% \begin{macro}{\pxrr@jprologue}
% 圏点用の開始処理。
%    \begin{macrocode}
\def\pxrr@k@prologue{%
  \ifpxrr@k@ghost
    \pxrr@jghost@char
    \pxrr@inhibitglue
  \fi
  \begingroup
    \ifpxrr@k@ghost
      \setbox\pxrr@boxa\hbox{\pxrr@jghost@char}%
      \kern-\wd\pxrr@boxa
    \fi
}
%    \end{macrocode}
% \end{macro}
%
% \subsubsection{後処理}
%
% \begin{macro}{\pxrr@kenten@exit}
% 出力を終えて、最後に呼ばれるマクロ。
%    \begin{macrocode}
\def\pxrr@kenten@exit{%
  \ifpxrr@fatal@error
    \pxrr@fallback
  \fi
  \pxrr@k@epilogue
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@jepilogue}
% 終了処理。
%    \begin{macrocode}
\def\pxrr@k@epilogue{%
    \ifpxrr@k@ghost
      \setbox\pxrr@boxa\hbox{\pxrr@jghost@char}%
      \kern-\wd\pxrr@boxa
    \fi
  \endgroup
  \ifpxrr@k@ghost
    \pxrr@inhibitglue
    \pxrr@jghost@char
  \fi
}
%    \end{macrocode}
% \end{macro}
%
% \subsection{デバッグ用出力}
%
%    \begin{macrocode}
\def\pxrr@debug@show@kenten@input{%
  \typeout{%
pxrr@k@the@mark=\meaning\pxrr@k@the@mark^^J%
pxrr@side=\meaning\pxrr@side^^J%
pxrr@body@list=\meaning\pxrr@body@list^^J%
  }%
}
%    \end{macrocode}
%
%^^A------------------------------------
% \section{実装（圏点ルビ同時付加）}
%
% コンボ！
%
% \subsection{呼出時パラメタ}
%
% \begin{macro}{\ifpxrr@apply@combo}
% 直後に実行するルビ命令について同時付加を行うか。
% スイッチ。
%    \begin{macrocode}
\newif\ifpxrr@apply@combo
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\ifpxrr@combo}
% 現在実行中のルビ命令について同時付加を行うか。
% スイッチ。
%    \begin{macrocode}
\newif\ifpxrr@combo
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@ck@ruby@font}
% \begin{macro}{\pxrr@ck@size@ratio}
% \begin{macro}{\pxrr@ck@inter@gap}
% \begin{macro}{\pxrr@ck@ruby@inter@gap}
% \begin{macro}{\pxrr@ck@side}
% \begin{macro}{\pxrr@ck@the@mark}
% \begin{macro}{\pxrr@ck@ruby@combo}
% 同時付加時の圏点側の呼出時パラメタの値。
%    \begin{macrocode}
\let\pxrr@ck@ruby@font\relax
\let\pxrr@ck@size@ratio\relax
\let\pxrr@ck@inter@gap\relax
\let\pxrr@ck@ruby@inter@gap\relax
\let\pxrr@ck@side\relax
\let\pxrr@ck@the@mark\relax
\let\pxrr@ck@ruby@combo\relax
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\ifpxrr@ck@kenten@head}
% 当該のルビ命令が、圏点命令の引数の先頭にあるか。
%    \begin{macrocode}
\newif\ifpxrr@ck@kenten@head
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\ifpxrr@ck@kenten@end}
% 当該のルビ命令が、圏点命令の引数の先頭にあるか。
%    \begin{macrocode}
\newif\ifpxrr@ck@kenten@end
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@ck@bind@param}
% “呼出時変数”へのコピーを行う。
%    \begin{macrocode}
\def\pxrr@ck@bind@param{%
  \let\pxrr@ck@ruby@font\pxrr@c@ruby@font
  \let\pxrr@ck@size@ratio\pxrr@c@size@ratio
  \let\pxrr@ck@inter@gap\pxrr@c@inter@gap
  \let\pxrr@ck@ruby@inter@gap\pxrr@k@ruby@inter@gap
  \let\pxrr@ck@side\pxrr@side
  \let\pxrr@ck@the@mark\pxrr@k@the@mark
  \let\pxrr@ck@ruby@combo\pxrr@k@ruby@combo
  \pxrr@csletcs{ifpxrr@ck@kenten@head}{ifpxrr@k@first@entry}%
  \pxrr@csletcs{ifpxrr@ck@kenten@end}{ifpxrr@k@last@entry}%
}
%    \end{macrocode}
% \end{macro}

% \subsection{その他の変数}
%
% \begin{macro}{\pxrr@ck@zw}
% 圏点の全角幅。
%    \begin{macrocode}
\let\pxrr@ck@zw\relax
%    \end{macrocode}
% \end{macro}
% \begin{macro}{\pxrr@ck@raise@P}
% ルビ側が |P| である場合の、圏点の垂直方向の移動量。
% \Note 圏点側が |S| である場合は負値になる。
%    \begin{macrocode}
\let\pxrr@ck@raise@P\relax
%    \end{macrocode}
% \end{macro}
% \begin{macro}{\pxrr@ck@raise@S}
% ルビ側が |S| である場合の、圏点の垂直方向の移動量。
%    \begin{macrocode}
\let\pxrr@ck@raise@S\relax
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@ck@raise@t}
% ルビ側が両側ルビである場合の、圏点の垂直方向の移動量。
%    \begin{macrocode}
\let\pxrr@ck@raise@t\relax
%    \end{macrocode}
% \end{macro}
%
% \subsection{オプション整合性検査}
%
% \begin{macro}{\pxrr@ck@check@option}
% 同時付加のための呼出時パラメタの調整。
%    \begin{macrocode}
\def\pxrr@ck@check@option{%
  \ifpxrr@ck@kenten@head
    \let\pxrr@bintr@\@empty
    \let\pxrr@bscomp=.\relax
    \pxrr@bnobrtrue
  \fi
  \ifpxrr@ck@kenten@end
    \let\pxrr@aintr@\@empty
    \let\pxrr@ascomp=.\relax
    \pxrr@anobrtrue
  \fi
}
%    \end{macrocode}
% \end{macro}
%
% \subsection{フォントサイズ}
%
% \begin{macro}{\pxrr@ck@assign@fsize}
% フォントに関連する設定。
%    \begin{macrocode}
\def\pxrr@ck@assign@fsize{%
%    \end{macrocode}
% |\pxrr@ck@zw| の値を求める。
%    \begin{macrocode}
  \begingroup
    \@tempdima=\f@size\p@
    \@tempdima\pxrr@ck@size@ratio\@tempdima
    \edef\pxrr@ruby@fsize{\the\@tempdima}%
    \let\pxrr@c@ruby@font\pxrr@ck@ruby@font
    \pxrr@use@ruby@font
    \pxrr@get@zwidth\pxrr@ck@zw
    \global\let\pxrr@gtempa\pxrr@ck@zw
  \endgroup
  \let\pxrr@ck@zw\pxrr@gtempa
%    \end{macrocode}
% |\pxrr@ck@raise@P|、|\pxrr@ck@raise@S| の値を計算する。
%    \begin{macrocode}
  \ifcase\pxrr@ck@side
%    \end{macrocode}
% 圏点側が |P| の場合。
%    \begin{macrocode}
    \@tempdimc\pxrr@ck@zw
    \advance\@tempdimc-\pxrr@htratio\@tempdimc
    \@tempdima\pxrr@ruby@raise\relax
    \@tempdimb\pxrr@ruby@zw\relax
    \advance\@tempdima\pxrr@htratio\@tempdimb
    \@tempdimb\pxrr@body@zw\relax
    \advance\@tempdima\pxrr@ck@ruby@inter@gap\@tempdimb
    \advance\@tempdima\@tempdimc
    \edef\pxrr@ck@raise@P{\the\@tempdima}%
    \@tempdima\pxrr@body@zw\relax
    \@tempdima\pxrr@htratio\@tempdima
    \@tempdimb\pxrr@body@zw\relax
    \advance\@tempdima\pxrr@ck@inter@gap\@tempdimb
    \advance\@tempdima\@tempdimc
    \edef\pxrr@ck@raise@S{\the\@tempdima}%
    \let\pxrr@ck@raise@t\pxrr@ck@raise@P
  \or
%    \end{macrocode}
% 圏点側が |S| の場合。
%    \begin{macrocode}
    \@tempdimc\pxrr@ck@zw
    \@tempdimc\pxrr@htratio\@tempdimc
    \@tempdima-\pxrr@ruby@lower\relax
    \@tempdimb\pxrr@ruby@zw\relax
    \advance\@tempdimb-\pxrr@htratio\@tempdimb
    \advance\@tempdima-\@tempdimb
    \@tempdimb\pxrr@body@zw\relax
    \advance\@tempdima-\pxrr@ck@ruby@inter@gap\@tempdimb
    \advance\@tempdima-\@tempdimc
    \edef\pxrr@ck@raise@S{\the\@tempdima}%
    \@tempdima-\pxrr@body@zw\relax
    \advance\@tempdima-\pxrr@htratio\@tempdima
    \@tempdimb\pxrr@body@zw\relax
    \advance\@tempdima-\pxrr@ck@inter@gap\@tempdimb
    \advance\@tempdima-\@tempdimc
    \edef\pxrr@ck@raise@P{\the\@tempdima}%
    \let\pxrr@ck@raise@t\pxrr@ck@raise@S
  \fi
}
%    \end{macrocode}
% \end{macro}
%
% \subsection{ブロック毎の組版}
%
% \begin{macro}{\pxrr@ck@body@natwd}
% 親文字列の自然長。
%    \begin{macrocode}
\let\pxrr@ck@body@natwd\relax
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@ck@locate}
% 圏点列のパターン指定。
%    \begin{macrocode}
\let\pxrr@ck@locate\relax
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@ck@kenten@list}
% 圏点列のリスト。
%    \begin{macrocode}
\let\pxrr@ck@kenten@list\relax
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@ck@compose}
% |#1| に親文字テキスト、|\pxrr@ck@body@natwd| に親文字の自然長、
% ボックス0にルビ出力、|\pxrr@boxa| に親文字出力、
% |\pxrr@ck@locate| にパターンが入っている前提で、
% ボックス0に圏点を追加する。
% 
%    \begin{macrocode}
\def\pxrr@ck@compose#1{%
%    \end{macrocode}
% 圏点を組んだボックスを作る。
%    \begin{macrocode}
  \setbox\tw@\pxrr@hbox@to\z@{%
    \@tempdima=\f@size\p@
    \@tempdima\pxrr@ck@size@ratio\@tempdima
    \edef\pxrr@ruby@fsize{\the\@tempdima}%
    \let\pxrr@c@ruby@font\pxrr@ck@ruby@font
    \pxrr@use@ruby@font
    \hss\pxrr@ck@the@mark\hss
  }%
%    \end{macrocode}
% 親文字テキストを分解した後、リスト |\pxrr@res| を
% 圏点のリストに置き換える。
%    \begin{macrocode}
  \pxrr@save@listproc
  \pxrr@decompose{#1}%
  \def\pxrr@pre{%
    \let\pxrr@res\@empty
    \pxrr@ck@compose@entry\pxrr@pre
  }%
  \def\pxrr@inter{%
    \pxrr@ck@compose@entry\pxrr@inter
  }%
  \def\pxrr@post{%
    \pxrr@appto\pxrr@res{\pxrr@post}%
  }%
  \pxrr@res
  \pxrr@restore@listproc
  \let\pxrr@natwd\pxrr@ck@body@natwd
%    \end{macrocode}
% 圏点リストを均等配置する。
%    \begin{macrocode}
  \pxrr@evenspace@int\pxrr@ck@locate\pxrr@boxb\relax
      {\wd\pxrr@boxa}%
%    \end{macrocode}
% 合成処理。
%    \begin{macrocode}
  \setbox\z@\hbox{%
    \unhcopy\z@
    \kern-\wd\z@
    \ifcase\pxrr@side
      \raise\pxrr@ck@raise@P
    \or
      \raise\pxrr@ck@raise@S
    \or
      \raise\pxrr@ck@raise@t
    \fi
    \hb@xt@\wd\pxrr@boxa{\hss\copy\pxrr@boxb\hss}%
  }%
}
\def\pxrr@ck@compose@entry#1#2{%
  \setbox\pxrr@boxb\pxrr@hbox{#2}%
  \edef\pxrr@tempa{%
    \noexpand\pxrr@appto\noexpand\pxrr@res{\noexpand#1{%
        \hb@xt@\the\wd\pxrr@boxb{\hss\copy\tw@\hss}}}%
  }\pxrr@tempa
}
%    \end{macrocode}
% \end{macro}
%
%^^A------------------------------------
% \section{実装：hyperref対策}
%
% PDF文字列中ではルビ命令や圏点命令が“無難な出力”をするようにする。
% 現状では、ルビ・圏点ともに親文字のみを出力することにする。
%
% \begin{macro}{\pxrr@dumb@sub}
% オプション部分を読み飛ばす補助マクロ。
%    \begin{macrocode}
\def\pxrr@dumb@sub#1#2#{#1}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@dumb@ruby}
% 無難なルビ命令。
%    \begin{macrocode}
\def\pxrr@dumb@ruby{%
  \pxrr@dumb@sub\pxrr@dumb@ruby@
}
\def\pxrr@dumb@ruby@#1#2{#1}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@dumb@truby}
% 無難な両側ルビ命令。
%    \begin{macrocode}
\def\pxrr@dumb@truby{%
  \pxrr@dumb@sub\pxrr@dumb@truby@
}
\def\pxrr@dumb@truby@#1#2#3{#1}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pxrr@dumb@tkenten}
% 無難な圏点命令。
% \Note |\kspan| もこの定義を利用する。
%    \begin{macrocode}
\def\pxrr@dumb@kenten{%
  \pxrr@dumb@sub\pxrr@dumb@kenten@
}
\def\pxrr@dumb@kenten@#1{#1}
%    \end{macrocode}
% \end{macro}
%
% \PKN{hyperref}の |\pdfstringdef| 用のフック |\pdfstringdefPreHook|
% に上書き処理を追記する。
%    \begin{macrocode}
\providecommand*\pdfstringdefPreHook{}
\g@addto@macro\pdfstringdefPreHook{%
%    \end{macrocode}
% |\ruby| と |\kenten| は「本パッケージの命令であるか」の検査が必要。
%    \begin{macrocode}
  \ifx\pxrr@cmd@ruby\ruby
    \let\ruby\pxrr@dumb@ruby
  \fi
  \let\jruby\pxrr@dumb@ruby
  \let\aruby\pxrr@dumb@ruby
  \let\truby\pxrr@dumb@truby
  \let\atruby\pxrr@dumb@truby
  \ifx\pxrr@cmd@kenten\kenten
    \let\kenten\pxrr@dumb@kenten
  \fi
  \let\kspan\pxrr@dumb@kenten
}
%    \end{macrocode}
%
%^^A------------------------------------
% \Finale
%
\endinput
