%#!make ptex-manual.pdf
\documentclass[a4paper,11pt,nomag,dvipdfmx]{jsarticle}
\usepackage[textwidth=42zw,lines=40,truedimen,centering]{geometry}
%%%%%%%%%%%%%%%%
% additional packages
\usepackage{amsmath}
\usepackage{array}\usepackage[all]{xy}
\SelectTips{cm}{}
%\usepackage[dvipdfmx]{graphicx}
\usepackage[T1]{fontenc}
\usepackage{booktabs,enumitem,multicol}
\usepackage[defaultsups]{newpxtext}
\usepackage[zerostyle=c,straightquotes]{newtxtt}
\usepackage{newpxmath}
\usepackage[hyperfootnotes=false]{hyperref}
\usepackage{pxjahyper}
\usepackage{makeidx}\makeindex
% common
\usepackage{ptex-manual}
%%%%%%%%%%%%%%%%
\makeatletter
\setlist{leftmargin=2zw}
\setlist[description]{labelwidth=2zw,labelindent=1zw,topsep=\medskipamount}
\def\tsp{_{\mbox{\fontsize\sf@size\z@\ttfamily \char32}}}
\def\tpar{_{\mbox{\fontsize\sf@size\z@\ttfamily \string\par}}}
\def\tign{_{\mbox{\fontsize\sf@size\z@\selectfont --}}}
\def\tableautorefname{表}
\def\figureautorefname{図}
\def\HyRef@autoref#1#2{%
\begingroup
\Hy@safe@activestrue
\expandafter\HyRef@autosetref\csname r@#2\endcsname{#2}{#1}%
\endgroup\textcompwordmark %欧文ゴースト
}
\makeatother
\usepackage{shortvrb}
\MakeShortVerb*{|}
%%%%%%%%%%%%%%%%
\def\_{\leavevmode\vrule width .45em height -.2ex depth .3ex\relax}
\def\Pver{p\the\ptexversion.\the\ptexminorversion\ptexrevision}
\def\UPver{\Pver-u\the\uptexversion\uptexrevision}
\frenchspacing
\begin{document}
\title{\emph{\pTeX マニュアル}}
\author{日本語\TeX 開発コミュニティ\null
\thanks{\url{
https://texjp.org},\ e-mail: \texttt{issue(at)texjp.org}}}
\date{\pTeX: version \Pver \\ \upTeX: vesrion \UPver \\[1ex] \today}
\maketitle
本ドキュメントは,日本語\TeX 開発コミュニティ版の
\pTeX~\Pver(以下,「コミュニティ版\pTeX 」)および
\upTeX~\UPver についてまとめたものである.
\pTeX はもともとアスキー株式会社によって開発された\footnote{最新版は
p3.1.11 (2009/08/17).\url{
https://asciidwango.github.io/ptex/}}ので,
しばしば「アスキー\pTeX 」または「ASCII \pTeX 」と呼ばれる.
コミュニティ版\pTeX は,日本語\TeX 開発コミュニティがアスキー\pTeX を
国際的なディストリビューション(かつてのte\TeX や現在の\TeX~Live)へ
導入するにあたって幾つかの改良を加えたものであり,オリジナルとは
動作が異なる点もあるので注意されたい.
\upTeX は田中琢爾氏による\pTeX の拡張版であり,
\epTeX および\eupTeX は北川弘典氏によりそれぞれ\pTeX と\upTeX に
\eTeX がマージされた拡張版である.
これらはいずれもコミュニティ版\pTeX をベースに開発されており,
総称して「\pTeX 系列」と呼ばれる.
本ドキュメント(\jobname.pdf)では,\pTeX 系列における共通機能と
\upTeX による拡張を説明する.% 和文文字トークンの扱いが異なる
\epTeX/\eupTeX による拡張についてはeptexdoc.pdfを参照されたい.
\begin{itemize}
\item コミュニティ版\pTeX の開発元:\\
\url{
https://github.com/texjporg/tex-jp-build/}
\item 本ドキュメントの開発元:\\
\url{
https://github.com/texjporg/ptex-manual/}
\end{itemize}
\newpage
\tableofcontents
\newpage
%%%%%
\section*{表記について}
\pTeX 系列については,以下のようにまとめた表記もしばしば用いられる.
\begin{itemize}
\item \pTeX, \upTeX → (u)\pTeX
\item \pTeX, \epTeX → (\eTeXpre)\pTeX
\item \upTeX, \eupTeX → (\eTeXpre)\upTeX
\item \epTeX, \eupTeX → \eTeXpre(u)\pTeX
\item \pTeX, \upTeX, \epTeX, \eupTeX → (\eTeXpre)(u)\pTeX
\end{itemize}
本ドキュメントでは,特に断らない限り単に\pTeX と表記すれば
(\eTeXpre)(u)\pTeX の4種類全てを指すこととする.
また\upTeX と表記すれば(\eTeXpre)\upTeX の2種類を指すこととする.
ただし,節タイトルで\emph{【\pTeX の場合】【\upTeX の場合】}の
ように分割した箇所については,
それぞれ(\eTeXpre)\pTeX と(\eTeXpre)\upTeX を指すこととする.
また,(すぐ下のように)列挙する形で記す場合は
それぞれ単独のエンジンを指す.
\section*{\TeX~Liveにおける配布}
\def\MODEext{{\tiny 拡張モード}}
現在,\TeX~Liveで配布されている主要なエンジンと
\pTeX 系列の関係性は以下の図で表される.
独立したプログラム(バイナリ)として配布されているものを
\fbox{枠}で囲んである.\par\vskip-35pt
\[
\xymatrix@ur{
\text{\fbox{\TeX}} \ar[r]\ar[d] & \text{\eTeX} \ar[r]\ar[d]\ar[rd]
& \text{\fbox{\pdfTeX}} \ar[rd] & \\
\text{\pTeX} \ar[r]\ar[d] & \text{\epTeX} \ar[d]
& \text{\fbox{\hologo{XeTeX}}} & \text{\fbox{Lua\TeX}} \\
\text{\upTeX} \ar[r] & \text{\fbox{\eupTeX}} & & %\\ &&&
}
\]
\TeX~Live 2022までは
\pTeX, \upTeX, \epTeX, \eupTeX の4種類のエンジンが
独立したプログラムとして配布されていたが,
\TeX~Live 2023では素の\pTeX と\upTeX の配布が停止され,
それぞれ\epTeX と\eupTeX の互換モードに置き換えられた.
さらに\TeX~Live 2024ではオリジナルの\epTeX の配布も停止され,
4種類のエンジンは全て\eupTeX という単一のプログラムによる
エミュレートへと整理された.表にまとめると次のようになる.
\begin{description}\small
\item[互換モード]
\eTeX の拡張モード(extended mode)でない状態,
すなわち\code{-etex}スイッチ無効状態.\\
例えば,2022年まではコマンド\code{ptex}で
\code{This is pTeX, Version ...}が起動していたが,2023年は
\code{This is e-pTeX, Version ...}が起動する.
ここだけ見るとコマンド\code{eptex}と似ているが,\code{eptex}では
直後に\code{entering extended mode}と拡張モードに入るのと異なり,
\code{ptex}では拡張モードに入らないので,\eTeX 特有の
機能およびプリミティブは無効化された状態となる.
\item[内部レガシー]
(\eTeXpre)\upTeX が文字コードに関する内部処理を
Unicodeではなく(\eTeXpre)\pTeX 同様の
レガシーエンコーディング(EUC-JPやShift-JIS)で行うことを指す.
内部コードの差異だけであり,その他の(\eTeXpre)\upTeX 特有の
機能およびプリミティブは利用可能な状態である.
本文中\code{-kanji-internal}の説明も参照.\\
例えば,2023年のコマンド\code{eptex}が
\code{This is e-pTeX, Version ... (utf8.euc)}であったならば,
2024年には
\code{This is e-upTeX, Version ... (utf8.euc)}に変わっている.
一方\code{euptex}は
\code{This is e-upTeX, Version ... (utf8.uptex)}であるから
内部コードが異なる.
\end{description}
\begin{table}[ht]
\centering
\begin{tabular}{cccc}\hline
\code{コマンド名} & \TeX~Live 2022まで & \TeX~Live 2023 & \TeX~Live 2024以降 \\ \hline
\code{ptex} & \pTeX & \epTeX の互換モード & \eupTeX の内部レガシーの互換モード \\
\code{uptex} & \upTeX & \eupTeX の互換モード & →変更なし \\
\code{eptex} & \epTeX\MODEext & →変更なし & \eupTeX の内部レガシー \\
\code{euptex} & \eupTeX\MODEext & →変更なし & →変更なし \\ \hline
\end{tabular}
\end{table}
\section*{\pTeX 系列における\LaTeX}
(\eTeXpre)\pTeX で動くように調整された\LaTeX を\pLaTeX,
(\eTeXpre)\upTeX で動くように調整された\LaTeX を\upLaTeX と呼ぶ.
\pLaTeX はもともとアスキー株式会社によって\pTeX と一体で
開発されていた\footnote{最新版は2006/11/10.これを
「アスキー版\pLaTeX」と呼ぶことにする.}.
2010年にコミュニティ版\pTeX が\TeX~Liveに収録されて以降,
そこで独自の改良や仕様変更が加えられるようになり,
またベースである\LaTeX も更新が進んでいる.
特に2020年以降は,\LaTeX は素の\TeX では動作せず,
拡張モードの\eTeX~``$+\alpha$''が動作条件となっており,
したがって素の(u)\pTeX では動作しない.
そうした流れに合わせてアスキー版\pLaTeX からforkしたのが
「コミュニティ版\pLaTeX」である.
\upLaTeX はもともとアスキー版\pLaTeX を元に\upTeX と一体で
開発されていたが,現在はコミュニティ版\pLaTeX をベースにしている.
\begin{itemize}
\item コミュニティ版\pLaTeX の開発元:\\
\url{
https://github.com/texjporg/platex/}
\item コミュニティ版\upLaTeX の開発元:\\
\url{
https://github.com/texjporg/uplatex/}
\end{itemize}
\TeX~Liveでのエンジン利用状況は以下の通りである.
ここで,2023-06-01以降は\code{platex}で\epTeX ではなく
\eupTeX の内部レガシーが起動することに注意
(\code{eptex}より一足早く変更された).
\begin{table}[ht]
\centering
\begin{tabular}{ccc}\hline
\code{コマンド名} & \TeX~Live 2012から2023初期まで & \TeX~Live 2023の2023-06-01以降 \\ \hline
\code{platex} & \epTeX\MODEext & \eupTeX\MODEext の内部レガシー \\
\code{uplatex} & \eupTeX\MODEext & →変更なし \\ \hline
\end{tabular}
\end{table}
\clearpage
%%%%%
\part{\pTeX の日本語組版と追加プリミティブ}
ここでは,\pTeX 系列の日本語組版の概略と,それを実現するために導入された
プリミティブを説明する.
\section{\pTeX 系列で利用可能な文字}
\label{sec:ptexchar}
% このマニュアルを英語化する際は以下も参照.
%
http://tutimura.ath.cx/ptexlive/?ptexenc%2FDetails
%
http://ajt.ktug.org/assets/2008/5/1/0201tsuchimura_kuroki.pdf
%
https://okumuralab.org/tex/mod/forum/discuss.php?d=460
オリジナルの\TeX で扱える文字コードの範囲は0--255であった
\footnote{当初の\TeX82では7-bitだった:\TeX90で8-bitになった.}.
\pTeX 系列では,日本語の文字を(\LaTeX の\code{inpuenc}のようなアクティブ化
によらず)直接扱えるように,文字コードとして有効な範囲を拡張している.
以降では,従来の枠組みで扱える文字を\emph{欧文文字},
それ以外を\emph{和文文字}と呼ぶ.
なお,本節(\ref{sec:ptexchar}節)全体を通して
\epTeX は\pTeX と同じ,\eupTeX は\upTeX と同じである.
\subsection{ファイルのエンコードと内部コード}
\pTeX 系列は,\emph{入出力ファイルのエンコード}として
ISO-2022-JP (jis),EUC-JP (euc),Shift-JIS (sjis)またはUTF-8 (utf8)に対応している.
ただし,入力はそのままのエンコードで扱われるとは限らず,
各行は\emph{内部コード}に変換されてから内部処理に回され,
ファイル出力時にもやはり内部コードからの変換が行われる.
ファイルのエンコードと内部コードが異なる場合は
\code{ptexenc}ライブラリに従ってエンコード変換が発生することとなる.
\TeX の入力プロセッサに実際に渡るのは入力各行の変換結果である.
\pTeX の内部コードはWindowsではShift-JIS,それ以外ではEUC-JPが既定であり,
\upTeX の内部コードは既定でUnicodeであるが,
起動時のオプション|-kanji-internal|(INIモード時のみ有効:後述)に
よって制御できる.
\pTeX/\upTeX の入出力ファイルのエンコードは,
\TeX~Live 2018以降は全てのプラットフォームでUTF-8が既定である
\footnote{\TeX~Live 2017以前では\pTeX に限り,
WindowsではShift-JIS,それ以外ではUTF-8であった.
\upTeX は当初から全てのプラットフォームでUTF-8であった.}が,
個別の入力ファイルのエンコードは次の順番で決まる(\code{ptexenc}による).
この決定手続きはファイルの先頭行を読むときに行われる.
% 注:|PTEX_IN_FILTER| が定義されている場合は別.
\begin{enumerate}
\item ファイル先頭にUTF-8のBOM\footnote{正確には,最初の4byteが
\code{0xEF 0xBB 0xBF 0x7E}以下.}を見つけたらUTF-8(BOM付き)とみなす.
\item エンコード推測機能が有効ならば推測を行い,成功すれば
それを採用する\footnote{\TeX~Live 2022以前はWindows専用の機能であったが,
\TeX~Live 2023で全てのプラットフォームで利用可能となった\cite{tjb142}.
kpathsearchライブラリ変数|guess_input_kanji_encoding|によって制御でき,
値が1ならば有効,0ならば無効である.}.
\item 起動時のオプション|-kanji|(後述)による指定があればそれを使う.
\item 環境変数|PTEX_KANJI_ENC|が定義されていればそれを使う.
\item 以上で決まらない場合は既定のエンコードを使う.
\end{enumerate}
% 以上の記述は阿部さんのブログを基に作成.
%
http://abenori.blogspot.com/2016/02/e-ptexeptexinputencoding.html
% なお LaTeX2e 2018-04-01 での inputenc UTF-8 既定化に合わせて
% Windows (W32TeX) でも Shift-JIS から UTF-8 に変更されている.
%
https://okumuralab.org/tex/mod/forum/discuss.php?d=2396
なお,ISO-2022-JPでエンコードされた文字は現在のエンコードによらず正しく読まれる.
% ISO-2022-JP (JIS) でエンコードされたバイト列は 7 ビットであって,
% 他の 3 つのエンコードと明らかに区別ができるため.
% 実際には,他のエンコードのファイルの途中に JIS の文字列が混ざっていても
% 全て正常に読み込まれる.
%
https://qiita.com/zr_tex8r/items/beda5a7702b84409436e
また,\eTeXpre(u)\pTeX の\.{epTeXinputencoding}を使用すればその次の行から
新しいエンコードで読まれる(\texttt{./eptexdoc.pdf}を参照).
\begin{dangerous}
ここでは,歴史に興味のある読者への情報として,アスキー\pTeX から
現在のコミュニティ版\pTeX に至るエンコードの扱いの変遷を述べる.
初期のアスキー\pTeX は「EUC版\pTeX 」「SJIS版\pTeX 」「JIS版\pTeX 」の
3つのプログラムを別々に用意しており,一つの\pTeX バイナリではエンコードが
EUC-JP,Shift-JIS,ISO-2022-JPのどれか一つのファイルしか処理できなかった.
% JIS のファイルなら EUC/SJIS どちらの ptex でも読み込めますが,
% これも最初からではなく p2.1.5 (1997年) 以降のようで,
% それまではスタイルファイルも EUC や SJIS にしておく必要があったようです.
|-kanji|オプションが追加され,一つの\pTeX バイナリで複数のエンコードを
選択処理できるようになったのは\pTeX~3.0.1と3.0.4の間(2002年10月頃)である.
%
http://tutimura.ath.cx/ptexlive/?ptexenc%2FDetails
% の土村さんのコメント (2008-02-23) より
コミュニティ版\pTeX は,UNIX向け日本語\TeX ディストリビューション
pte\TeX\footnote{Thomas Esserさんによるte\TeX をベースとして,
土村展之さんによって2004年から2009年まで開発.
その後継のptexliveは,2010年に\pTeX が\TeX~Liveに取り込まれる際のベースに
なった.}の開発過程で誕生した.
% コミュニティ版という呼称は2004年当初からのものではなく
% 2016年頃に生じたものであるが,系譜上ptetexと一体で
% 開発されてきたものをコミュニティ版と後から呼ぶことにする.
2006年頃からエンコードがUTF-8のファイル入力への対応が進められ,2007年には
エンコード変換を担う関数群が\code{ptexenc}というライブラリに切り出された.
現在の\TeX~Liveでも\code{ptexenc}は種々のプログラムで利用されている.
\end{dangerous}
\paragraph{\pTeX 系列の起動時のオプション}
\begin{itemize}
\item |-kanji=|<encoding>
\begin{quotation}
入出力テキストファイルのエンコードを指定する.\\
利用可能な<encoding>の値:\code{euc}, \code{sjis}, \code{jis}, \code{utf8}
\end{quotation}
\item |-kanji-internal=|<encoding>
\begin{quotation}
内部コードを指定する(INIモード専用\footnote{フォーマットファイルは
内部コードに依存するので,実際の処理と整合性をとるため
virtual modeでは読み込んだフォーマットファイルと同じ内部コードで
動作するように固定している.\pTeX\ p3.8.2以降の仕様.}).\\
利用可能な<encoding>の値:\code{euc}, \code{sjis}
\quad (\upTeX のみ:\code{uptex}も利用可能)
\end{quotation}
\end{itemize}
\pTeX で利用可能な内部コードは\code{euc} (EUC-JP)か
\code{sjis} (Shift-JIS)のいずれかであるため,
入力を仮にUTF-8としても必ず内部コードへの変換が起こる.
\upTeX では既定状態の内部コードが\code{uptex} (Unicode)なので,
入力をUTF-8とすれば変換は“ほとんど”起こらない\footnote{例外は
\code{ptexenc}による基底文字と濁点に分解された形(結合文字列)の
合成など:後述.}.
\paragraph{\pTeX 系列の起動時のバナー}
入出力ファイルのエンコードと内部コードは起動時のバナーから分かる.
例えば
\begin{verbatim}
This is pTeX, Version 3.14159265-p3.8.0 (utf8.euc) (TeX Live 2018)
(preloaded format=ptex)
\end{verbatim}
というバナーの場合は,|(utf8.euc)| から
\begin{itemize}
\item 入出力ファイルの(既定)エンコードはUTF-8(但し,JIS~X~0208の範囲内)
\item \pTeX の内部コードはEUC-JP
\end{itemize}
という情報が見て取れる.入出力ファイルのエンコードと内部コードが同じ場合は,
\begin{verbatim}
This is pTeX, Version 3.14159265-p3.8.0 (sjis) (TeX Live 2018)
(preloaded format=ptex)
\end{verbatim}
のように表示される(入出力ファイルのエンコードと内部コードがともにShift-JISである例).
\begin{dangerous}
上にはこのように書いたが,
極めて細かい話をすれば,起動時のバナーは時にウソをつくので注意.
ログファイルには記録されるバナーは常に正しい.これは以下の事情による.
virtual modeでは,起動直後にバナーを表示してから,フォーマットファイル
読込が行われる.この時点で初めて,起動時の内部コードとフォーマットの
内部コードの整合性が確認される.ここでもし合致しなかった場合は,\pTeX は
警告を表示してフォーマットに合った内部コードを選択し,以降の処理を行う.
ログファイルはこの後にオープンされるため,そこには正しい内部コード
(フォーマットと同じ内部コード)が書き込まれる\cite{tjb55}.
このようなウソは,\pTeX に限らず\code{(preloaded format=***)}でも見られる.
\end{dangerous}
\subsection{有効な文字コードの範囲【\pTeX の場合】}\label{sec:ptex_code}
\pTeX では,JIS~X~0208すなわちJIS第1, 2水準の文字を利用可能である.
入力は\emph{「7ビットASCII文字集合」に「あるファイルのエンコードで
表現されたJIS~X~0208の文字集合」を加えたもの}として解釈される.
そして,以下の規則により和文文字と欧文文字に区別して取り扱われる.
\begin{itemize}
\item 7ビットASCII文字集合は\emph{欧文文字}として扱われる.
また,\TeX90互換の「|^^|記法」という間接的な入力法
\footnote{|^^ab|のようにカテゴリーコード7の文字2つに続いて
|0|--|9|, |a|--|f|のいずれかが2つ続くと,
それを16進文字コードとする文字入力がなされたのと同じ処理に回る.}も
\emph{常に欧文扱い}される\footnote{|^^|記法の欧文扱いは
アスキー\pTeX~3.1.4以降.
\pTeX~3.1.8で制御綴内での扱いが改善された.また,
コミュニティ版\pTeX~4.0.0で文字列化においても常に欧文扱いするように改修した.
これについては\ref{sec:printkanji16bit}節を参照.}.
% |^^|記法は,|^^@|のようにASCII一文字(0--9,~a-f以外)が続くものと
% |^^ab|のように16進数2桁が続くものがある.
% 前者は\TeX82からあったもので,後者が\TeX90で追加された.
% 参考:Knuth, TUGboat, Volume 10 (1989), No.~3, p.325
\item 最上位ビットが1の場合,そのバイトで始まる列について
ファイルのエンコードから内部コード(EUC-JPまたはShift-JIS)への
変換を試みる(同一コードなら恒等変換).
和文文字の内部コードとして許される整数は
$256c_1+c_2$,但し$c_i\in C_i$であり,ここで
\begin{description}
\item[内部コードがEUC-JPのとき]
$C_1=C_2=\{\hex{a1},\dots,\hex{fe}\}$.
\item[内部コードがShift-JISのとき]
$C_1=\{\hex{81},\dots,\hex{9f}\}\cup\{\hex{e0},\dots,\hex{fc}\}$,\\
$C_2=\{\hex{40},\dots,\hex{7e}\}\cup\{\hex{80},\dots,\hex{fc}\}$.
\end{description}
である.この内部コードのパターンに合えば
「変換後の文字コードを持つ一つの\emph{和文文字}」
として扱われ,合わなければ一旦|^^ab|形式への変換(後出の★)を経て
「\emph{8ビット欧文文字}のバイト列」として扱われる.
\end{itemize}
% TeX の行入力処理
%
https://www.ma.ns.tcu.ac.jp/Pages/TeX/line.input.html
% アスキー pTeX 3.1.4 における ^^ 記法の改修
%
https://www.ma.ns.tcu.ac.jp/Pages/TeX/hat.hat.a.b.html
\begin{dangerous}
一遍に書いているが,
入力ファイルを一行読み込んで必要なエンコード変換を行った結果を
バッファに格納するところまでが\code{ptexenc}による前処理である.
そのバッファを\TeX の入力プロセッサが読み,
文字のカテゴリーコードに従って(和文と欧文の区別を付けながら)
トークン列を生成する,という流れである.
\code{ptexenc}による前処理には
「内部コードに変換できない入力のバイト列を|^^ab|形式に変換」も
含まれるが,この時点ではカテゴリーコードについて知らないため,
文字|^|の\.{catcode}が7かどうかは関係なく|^^|が用いられる.
\end{dangerous}
\pTeX における有効な文字コードの範囲は
「欧文文字として有効な文字コード(0--255)」と
「和文文字として有効な文字コード(内部コードとして許される整数値)」の和集合であり,
前者は1バイト・後者は2バイトなので互いに重ならない.
% 内部コードの範囲:kanji.c の |is_char_kanji| の実装
最近(2010年代以降)では,\pTeX でもファイルのエンコードをUTF-8とする
利用が増えてきた.
コミュニティ版\pTeX はUTF-8ファイル入力に対応しているが,
先述の通り内部コードはEUC-JPまたはShift-JISのいずれかであるため,
\emph{\pTeX はJIS~X~0208外の文字をサポートしない}.
なお,\code{ptexenc}による前処理に以下の特殊な加工を含めてある.
%
http://tutimura.ath.cx/ptetex/?UTF-8%C2%D0%B1%FE%282%29
\begin{itemize}
\item Unicodeでのバラツキを同一視する多対一変換(表\ref{table:jis_uni_var})
\footnote{例えば,ソースファイル中の全角ダーシ(\code{U+2015})と
EMダーシ(\code{U+2014})は同一視され,内部的にはJISコード\hex{213D}と
して扱われ,ファイルに書き出される時は\code{U+2015}になる.}
\item BOMの無視(ファイル先頭に限らず)
\item 結合濁点(\code{U+3099})・半濁点(\code{U+309A})の合字処理
\footnote{ただし,Unicodeで単一の文字コードで表せる場合に限る.}
\item JIS外のため変換できない文字を|^^ab|形式に変換
\footnote{例えば,ソースファイル中にçのようなJIS~X~0208外の文字を直接書くと,
これは和文文字の内部コードに変換できないため|ç|に変換されて欧文扱いされる.}…★
%%%
% [動作チェック!]
% 上の行の説明文では |ç| が『ptexenc による |^^| 形式への変換』を経て
% 欧文 8 文字 |^^c3^^a7| としてリテラル印字されることを期待している!
% 本ソースを pLaTeX で処理すれば真.
% 内部 Unicode の upLaTeX では『ptexenc による |^^| 形式への変換』が起こらず
% 内部コード 0xE7 としてバッファに格納される.
% そして \kcatcode"E7=15 なのでインプットプロセッサの段階で欧文扱いされる.
% 既定の inputenc UTF-8 ならばこれは "E7 の欧文 1 文字になる.
% もし \UseRawInputEncoding ならば "C3 "A7 の欧文 2 文字になる.
\setbox0=\hbox{|ç|}\unless\ifdim\wd0>2em\ptErr{Check above: pLaTeX assumed}\fi
%%%
\end{itemize}
なお,UTF-8ファイル出力時にはこのような加工の逆変換は行わない(入力時に
加工されたままで出力される).
このように\emph{\pTeX は入力を内部コードに変換する処理を含むため,
オリジナルの\TeX や\pdfTeX などの欧文\TeX とは入力に関して必ずしも
互換でない}ことに注意が必要である.
\begin{dangerous}
以上で述べた「内部コードの範囲」はJIS~X~0213の漢字集合1面(Shift-JISの場合は2面も)を
まるまる含んでいるが,\emph{\pTeX はJIS~X~0213には対応していない.}
JIS~X~0213で規定された「85区1点」の位置の文字を入力ファイル中に書いた場合,
\begin{description}
\item[エンコードがEUC,~Shift-JISの場合] DVIには29985~(\hex{7521})%"
番の文字として出力される.
\item[エンコードがJISの場合] ``\verb|! Missing $ inserted.|''というエラーが発生する.
これは,\pTeX がJIS~X~0213の1面を指示するエスケープシーケンス
\texttt{1B 24 28 4F} (JIS2000), \texttt{1B 24 28 51} (JIS2004)を認識せず,
\texttt{24}~(\texttt{\$})を数式モード区切りと解釈してしまうためである.
\item[エンコードがUTF-8の場合] UTF-8のバイト列\texttt{E6 93 84}として読み込まれる.
\end{description}
なお,\.{char}により「\verb|\char\kuten"5521|」%"
のようにして区点コードを指定した場合は,DVIには29985~(\hex{7521})%"
番の文字として出力される.
また,DVIに文字として出力されたからといって,それをPostScriptやPDFに変換したときに
意図通りに出力されるかは全くの別問題である.
\end{dangerous}
\subsection{有効な文字コードの範囲【\upTeX の場合】}\label{sec:uptex_code}
\upTeX は\pTeX と事情が異なるので,ここで説明する.
\pTeX との違いを\emph{強調}してある.
\begin{itemize}
\item 文字集合は内部コードにより範囲が異なる.
\begin{itemize}
\item 内部レガシー(EUC-JPまたはShift-JIS)の場合:
「7ビットASCII文字集合」に「あるファイルのエンコードで
表現されたJIS~X~0208の文字集合」を加えたもの.
つまり\pTeX となんら変わらない.
\item \emph{内部Unicodeの場合:Unicode全体.}
\end{itemize}
\item 和文文字と欧文文字の区別は以下の規則による:
%
\begin{itemize}
\item 7ビットASCII文字集合は欧文文字として扱われる.
また,\TeX90互換の「|^^|記法」という間接的な入力法も
常に欧文扱いされる.(\pTeX と同様)
\item 最上位ビットが1の場合,そのバイトで始まる列について
ファイルのエンコードから内部コードへの変換を試みる(同一コードなら恒等変換).
内部コードのパターンに合えば
「変換後の文字コードを持つ一つの\emph{一文字}」
として扱われ,\emph{それが和文扱いか欧文扱いかは
\.{kcatcode}に依存する(詳細は\ref{sec:uptex_kcat}節).}
合わなければ一旦|^^ab|形式への変換(後出の★)を経て
「8ビット欧文文字のバイト列」として扱われる.
%
% pTeX で和文固定の文字(例えば "あ")も
% upTeX -kanji-internal=euc/sjis なら \kcatcode=15 で欧文扱いできる.
% ただし入力ファイルのエンコードによらず内部コードにより
% 結果は ^^a4^^a2 (euc) / ^^82^^a0 (sjis) になる.
%
\end{itemize}
%
\item \code{ptexenc}ライブラリによる前処理も\pTeX と類似だが,
変換方向によって少々異なる.
%
\begin{itemize}
\item Unicode多対一変換:内部レガシーの場合は\pTeX と同様.
\emph{内部Unicodeの場合は,入出力UTF-8に対しては変換を行わず,
入力EUC-JP/Shift-JISからの変換について一対多対応があれば
Unicodeへの変換は表\ref{table:jis_uni_var}に従う.}
\item BOMの無視は行う.(\pTeX と同様)
\item 結合濁点・半濁点の合字処理は行う(\TeX~Live 2016以降
\footnote{結合濁点・半濁点は\TeX~Live 2015までは\pTeX でのみ
合字処理され,\upTeX では行っていなかった.}).(\pTeX と同様).
\item 範囲外の文字の|^^ab|形式への変換:内部レガシーでは\pTeX と同様.
\emph{内部Unicodeでは,文字集合がUnicode全体なので範囲外の文字は
存在せず,従って}|^^ab|\emph{形式への変換は基本的に起こらない}
\footnote{不正なUTF-8入力などに限り|^^ab|形式に変換される.}.…★
\end{itemize}
% 結合文字列(基底文字+合成用濁点・半濁点)→合成文字
%
https://zrbabbler.hatenablog.com/entry/20151006/1444134044
%
https://okumuralab.org/tex/mod/forum/discuss.php?d=1701
%
\end{itemize}
\begin{table}[bp]
\caption{JIS⇔Unicode一対多変換.Unicode→JIS変換では複数の文字が同一視
される.JIS→Unicode変換では複数候補のうち\emph{太字}が選択される.}
\label{table:jis_uni_var}
% ptexenc/unicode-jp.c の variation[] にて定義.
%
http://www.t-lab.opal.ne.jp/tex/jis_uni_variation_uptex.html
% 下記ZRは
https://github.com/texjporg/jsclasses/issues/49 で言及あり
\centering\small
\begin{tabular}{ccccc}
\toprule
区点 & Character Name & 文字 & JIS~X~0208 & Unicode \\
\midrule
1-17 & \code{OVERLINE} & \kchar\jis"2131
& \code{0x2131} & \code{U+203E}, \emph{\code{U+FFE3}} \\
1-29 & \code{EM DASH} & \kchar\jis"213D
& \code{0x213D} & \code{U+2014}, \emph{\code{U+2015}} \\ %ZR
1-33 & \code{WAVE DASH} & \kchar\jis"2141
& \code{0x2141} & \emph{\code{U+301C}}, \code{U+FF5E} \\ %ZR
1-34 & \code{DOUBLE VERTICAL LINE} & \kchar\jis"2142
& \code{0x2142} & \emph{\code{U+2016}}, \code{U+2225} \\ %ZR
1-36 & \code{HORIZONTAL ELLIPSIS} & \kchar\jis"2144
& \code{0x2144} & \emph{\code{U+2026}}, \code{U+22EF} \\
1-61 & \code{MINUS SIGN} & \kchar\jis"215D
& \code{0x215D} & \emph{\code{U+2212}}, \code{U+FF0D} \\ %ZR
1-79 & \code{YEN SIGN} & \kchar\jis"216F
& \code{0x216F} & \code{U+00A5}, \emph{\code{U+FFE5}} \\
1-81 & \code{CENT SIGN} & \kchar\jis"2171
& \code{0x2171} & \code{U+00A2}, \emph{\code{U+FFE0}} \\ %ZR
1-82 & \code{POUND SIGN} & \kchar\jis"2172
& \code{0x2172} & \code{U+00A3}, \emph{\code{U+FFE1}} \\ %ZR
2-44 & \code{NOT SIGN} & \kchar\jis"224C
& \code{0x224C} & \code{U+00AC}, \emph{\code{U+FFE2}} \\ %ZR
\bottomrule
\end{tabular}
\end{table}
\upTeX における有効な文字コードの範囲は
「欧文文字として有効な文字コード(0--255)」と
「和文文字として有効な文字コード」の和集合である.
内部レガシーの場合は\pTeX と全く同じであり,
前者は1バイト・後者は2バイトなので互いに重ならない.
内部Unicodeの場合は後者がUnicode全体(0以上0x10FFFF以下の
整数値)となるので,\emph{0--255の範囲は重なっており
和文・欧文どちらの文字コードとしても有効である}ことに注意.
% 内部コードの範囲:kanji.c の |is_char_kanji| の実装
いずれの場合も,\upTeX は
オリジナルの\TeX や\pdfTeX などの欧文\TeX とは入力に関して必ずしも
互換でない(内部UnicodeへのUTF-8入力に限っても「BOMの無視」と
「結合濁点・半濁点の合字処理」だけは起こる)が,
\pTeX と比較すれば幾分差異が軽減されている.
\begin{dangerous}
内部コードUnicode (\code{uptex})の場合の上限が0x10FFFFというのは
実は嘘である.24bit整数値が有効であり,うち0x110000以上0xFFFFFF以下は
特殊な用途で利用できるよう留保されている.
\begin{itemize}
\item \verb|Bad character code|エラーが出ない範囲:0以上0xFFFFFF以下
\footnote{\verb|Invalid KANSUJI char|エラーが出ない範囲も同じ.}
\item 和文文字トークンの文字コードとして可能な範囲:0以上0x10FFFF以下
\item 和文文字ノードの文字コードとして可能な範囲:0以上0xFFFFFF以下
\end{itemize}
%
\upTeX では和文文字トークンおよび和文文字ノードにおいて
文字コードをUTF-32の下位24bitで格納する仕様となっている.
Unicode文字入力で0x110000以上0xFFFFFF以下の文字コードはありえないが,
0x110000以上0x21FFFF以下の文字コードを数値で指定する場合の扱いは以下としている:
\begin{itemize}
\item \.{char}, \.{chardef}及び\.{kchar}, \.{kchardef}:
文字コードが0x110000以上でもそのままの値で和文文字ノードを生成する.
DVI出力時には「文字コード mod 0x110000」で書き込まれる.
% Output node |p| ... の処理で toDVI()
\item \.{kansujichar}への文字コード代入:
値の格納時に「文字コード mod 0x110000」を行うので,
以降の\.{kansuji}により生成する文字トークンは0以上0x10FFFF以下.
% eqtb テーブル格納時に toDVI()
\item \eTeXpre(u)\pTeX の\.{Uchar}, \.{Ucharcat}:
文字トークン生成時に「文字コード mod 0x110000」を行うので,
やはり0以上0x10FFFF以下になる.
% print_kanji() の処理で toUCS()
\end{itemize}
特に\.{kchar}の上記仕様はOTFパッケージで使われている.
これは,|\CID| (Adobe-Japan1)のような
Unicodeでない文字コードを扱う内部処理において
Unicodeの正規の文字コード(0x10FFFF以下)の
カテゴリーコードや禁則ペナルティのしがらみの影響を受けない目的である.
0x220000以上の文字コードは上記の数値変換を行わない(\ref{sec:uptex_ivs}節を参照).
% 0x110000 以上の扱い:現状では otf で意図的に利用.
% 将来的に異体字対応の内部コードに使う可能性を留保.
%
https://okumuralab.org/~okumura/texfaq/qa/50036.html
%
https://github.com/texjporg/tex-jp-build/issues/160
%
https://github.com/texjporg/tex-jp-build/issues/46
\end{dangerous}
\subsection{文字コードの範囲の拡張【\upTeX~u1.35, u2.00】}\label{sec:uptex_extension}
\upTeX では従来の文字コードの範囲からの拡張を
u1.35およびu2.00 (\TeX~Live 2025)にて行った.
従来は和文文字をUnicode 1文字のコードポイントで「1文字1トークン」として取り扱うのに対し,
欧文文字は8bitの範囲内にとどまり「1バイト1トークン」で扱っていたが,
それを超えて扱えるようにするものである.
やや特殊な扱いを要する上,新規の要素も多いためここに節を立てて説明する.
\subsubsection{Unicode合成文字と異体字セレクタ(IVS) (\upTeX~u1.35)}\label{sec:uptex_ivs}
Unicodeでは,一つの文字を表すために複数のコードポイントの
連なり(シーケンス)で示すことが規定されている文字がある.
その例が異体字セレクタ(IVS, Ideographic Variation Sequence/Selector)\cite{ivd220913}や
絵文字シーケンス\cite{emseq160}などである.
\upTeX ではそれら合成文字を従来扱うことができなかったが,\upTeX~u1.35で対応を進めた\cite{tjb46}.
仕様は以下の通りである.
\begin{itemize}
\item 想定した範囲のシーケンスの集合%
\footnote{言い換えれば網羅的ではなく想定外のシーケンスには対応していない.}%
を定め,\upTeX 独自の内部用の文字コード(合成文字用拡張文字コード)を定義する(後述).
合成文字用拡張文字コードにはコード値0x220000以降を用い,和文文字として扱う.
\item \code{ptexenc},\upTeX エンジンを拡張する.
\code{ptexenc}ライブラリで文字コードの合成・分解のAPIを用意する.
\upTeX とdviwareの間の文字データ渡しには合成文字用拡張文字コードを用いる.
\item \upTeX に\.{kcatcode} 20 ($\mathit{modifier}$)を新設する.
これはUTF-8の入力バッファの文字列で現れる異体字セレクタや合成用濁点を想定しているが,
\emph{基底文字とは独立した1つの和文文字トークン}として扱われる.
トークンとしての扱いは\.{kcatcode} 16,~17と同様である
(直後の改行は空白とみなさない,コントロールワードに使用可能).
\item \upTeX がトークン列から文字ノードを生成する段階で,
基底文字と$\mathit{modifier}$が連続してノード化されようとする場合
\footnote{ファイル中に直接文字を入力した場合に限らず,
基底文字の直接入力+\.{char}などによるmodifierの文字コード指定入力,
またはその逆でも良い.}には,
独立した2つのノードを生成する代わりに,
基底文字の文字コードを合成文字用拡張文字コードに置き換えた
\emph{単一の合成文字ノード}を生成する
\footnote{文字トークンの段階で2文字だったものが1つの文字ノードに変換される
という点では欧文の合字処理(リガチャ)に似ているが,
基底文字と$\mathit{modifier}$の合成は展開不能トークンが来ても中断されない.}.
% 欧文リガチャ・カーンは TFM の処理.JFM グルー・カーン挿入も同様.
% これに対し modifier の合成は ptexenc の処理なので.
合成に失敗した$\mathit{modifier}$は普通の文字(CJK記号)としてふるまい,
\.{kcatcode} 18 ($\mathit{other\_kchar}$)の文字ノードを生成する.
\item \upTeX エンジン内部では合成文字ノードを単一のノードとして扱うが,
処理中に合成文字のデータを文字バッファに書き戻す際には,
常にUTF-8の複数コードポイントのシーケンスに戻す
\footnote{文字ノードのデータを\.{showlists}で表示する際などが該当.
文字トークンは元々合成されていない.}.
それゆえ,テキスト形式の入出力では特殊な内部コードが現れることはなく必ず正規のUnicodeになる.
\item \upTeX の合成文字用拡張文字コード値を
\.{char}, \.{chardef}などの文字ノード生成プリミティブに直接与えることもできる.
また,合成文字用拡張文字コード値を
\.{kansujichar}や(\eupTeX の)\.{Uchar}などの文字トークン生成プリミティブに
与えると,展開結果は基底文字+modifierの2トークンとなる.
\item \upTeX が合成文字ノードをDVIに書き出す際には,
その合成文字用拡張文字コード値でDVI命令|set3|で書き込む.
\item \code{dvips}, \code{dvipdfmx}などAdobe-Japan1 (AJ1)のCIDが扱えるdviwareでは,
AJ1の文字に対してDVI命令|set3|からAJ1のCIDコードへ変換するvirtual fontを経由して
出力することが可能である.
\item dviware側の実装として,合成文字用拡張文字コードを直接扱い
DVI命令|set3|に対し適切なグリフを選択するようにしてもよい.
\end{itemize}
\upTeX~u1.35で対応した合成文字用拡張文字コードの概略を表\ref{table:compound_charcode}にまとめた.
各文字コードの具体的な変換式は
\href{
https://github.com/texjporg/uptex-base}{\file{uptex-base}}で配布している
\file{01uptex_doc_utf8.txt}を参照されたい.
異体字セレクタ(VS, Variation Selector)は前述のIVSの他,
SVS (Standardized Variation Sequence)にも対応している.
IVSの最大VS256まで拡張可能になるよう合成文字用拡張文字コードでは考慮してあるが,
おおもとのUnicode Ideographic Variation Database\cite{ivd220913}では
今のところVS49〜VS256が未定義である.
仮名の濁点・半濁点は基底文字が平仮名や片仮名の場合に加え変体仮名にも対応している.
絵文字はかつての日本の携帯電話由来の絵文字の大部分に対応しているが,
最近よく追加で規定される長くて複雑なシーケンスには対応していない.
絵文字の国旗(RGI Emoji Flag Sequence)は,
$\mathit{modifier}$と$\mathit{modifier}$の連続が規定通りに組み合わさると合成文字の扱いになる.
国旗および肌色(Emoji Modifier Fitzpatrick Type-1..6)など絵文字全般について,
DVIに書かれたデータをどう出力するかはdviwareにお任せする.
今後,さらに合成文字を追加対応するかどうかは未検討であり計画もない.
\begin{table}[bp]
\caption{合成文字用拡張文字コード.\upTeX~u1.35での対応状況.}
\label{table:compound_charcode}
\centering\small
\begin{tabular}{ccccc}
\toprule
種類 & 基底文字 & modifier
& 合成文字用拡張文字コード & パラメータ \\
\midrule
仮名+濁点 & 仮名 & \code{U+3099}
& 0x22,0000〜0x23,FFFF & \\
仮名+半濁点 & 仮名 & \code{U+309A}
& 0x24,0000〜0x25,E6E5 & \\
絵文字(国旗) & \code{U+1F1E6..1F1FF} & \code{U+1F1E6..1F1FF}
& 0x25,E6E6〜0x25,FFFF & $26種\times 26種$ \\
絵文字(肌色) & 絵文字 & \code{U+1F3FB..1F3FF}
& 0x26,0000〜0x2F,FFFF & Type-1-2〜6 \\
SVS & 漢字,記号など & \code{U+FE00..FE0F}
& 0x40,0000〜0x7F,FFFF & VS1〜VS16 \\
IVS & 漢字 & \code{U+E0100..E011F}
& 0x80,0080〜0xFF,FFFF & VS17〜VS48 \\
\bottomrule
\end{tabular}
\end{table}
表中でmodifierに相当する文字コードは
\upTeX~u1.35では既定で\.{kcatcode}=20 ($\mathit{modifier}$)に設定してある.
合成文字用拡張文字コードのメトリックとしては通常JFMの既定値の全角幅を想定しているが,
文字コード0xFFFFFF以内なので個別に設定することもできる.
virtual fontの仕様としてフォーマットの面では今回新規な部分はないものの,
最大で文字コード0xFFFFFFとなる点は従来の\TeX ファミリーで例がない.
このため周辺ソフトウェアではこれに準拠した拡張が必要になる場合が多い.
\code{omfonts} (\code{ovp2ovf}, \code{ovf2ovp}), \code{dvips}, \code{dvipdfmx}は対応を済ませてあり
\TeX~Live 2025では利用可能である.
\begin{dangerous}
紛らわしいが,\ref{sec:uptex_code}節で述べたように,
結合濁点・半濁点の合字処理のうち,
\begin{itemize}
\item 入力ファイルを一行読み込んでバッファに格納する段階で,
\item かつUnicodeで単一の文字コードで表せるシーケンスがあった場合
\end{itemize}
には,従来から\code{ptexenc}ライブラリによる前処理により
\emph{トークン化以前}の段階で合字処理が行われている
(例えば,|ピ|(U+30D2 U+309A)は|ピ|(U+30D4)と同一の文字トークンとみなされる).
一方,
\begin{itemize}
\item Unicodeでは文字合成でないと表せない仮名の濁点・半濁点
\footnote{想定は,
JIS~X~0213に含まれる「カ」などの半濁点や,%「か゚き゚く゚け゚こ゚カ゚キ゚ク゚ケ゚コ゚セ゚ツ゚ト゚ㇷ゚」
変体仮名の濁点・半濁点である.}
\item トークンを処理した結果として連続したシーケンスが現れてノード化される場合
\footnote{\.{kansuji}, \.{Uchar}等による文字トークン生成や,
基底文字と結合濁点・半濁点を連続して\.{char}で文字ノード生成する場合など.}
\end{itemize}
については,\upTeX~u1.35で導入した\emph{ノード化時の合成}で対応する.
\end{dangerous}
\subsubsection{欧文8bit超 (\upTeX~u2.00, 実験的)}\label{sec:uptex_ofm}
\upTeX では従来,欧文文字として扱える文字コードの範囲は8bit(\TeX90互換の0--255)であったが,
\upTeX~u2.00では0x2E7F以下まで拡張した\cite{tjb170}.
動作実績がまだ少なく関連フォントの整備等にも時間を要するため,今のところ実験的機能と位置づけている.
仕様は以下の通りである.
\begin{itemize}
\item \upTeX エンジンが扱える欧文文字の範囲は0~0x2E7Fである.
文字コード256以上を含む文字フォントはUnicode U+0000..2E7Fであることを想定する.
\item \.{kcatcode} 14 ($\mathit{latin\_ucs}$)を新設する.
UTF-8の入力バッファで8bit文字コード列が正規のUTF-8としてU+2E7F以下と読み取れて,
かつそのコード値を含むブロックの\.{kcatcode}が14となっているとき,
Unicodeの欧文であると解釈して符号位置0~0x2E7Fの欧文文字ノードを生成する.
同時にその文字コードに相当する欧文文字の\.{catcode}が付与される.
このとき「欧文Unicode 1文字に対し1トークン」となる.
\item 欧文用8bit TFMに加えて欧文用16bit OFM Level-0が読み込める.
符号位置0~0x2E7Fの欧文文字ノードはこれで扱う.
和文文字は従来同様JFMで扱う.
\item 256~0x2E7Fの欧文文字コードは,
DVIファイルにはそのままの文字コード(UCS-2相当)でDVI命令|set2|で書き込む.
\item U+2E80以上のUnicode文字は\upTeX では欧文文字として扱わない.
必要な場合はvirtual fontとdviwareで処置%
\footnote{頻出する例にU+FB00..FB06のリガチャ(ff, fi, fl等)が挙げられる.
\TeX90ではそれらを8bit (0--255)の内部コードに割り当てて使用しているが,
それと同様の取り扱いを維持する必要がある.}%
をする.
\item \.{catcode}, \.{lccode}, \.{uccode}, \.{sfcode}の扱う欧文文字コードの
最大値は0x2E7Fとする(\.{kcatcode}=14,15両方).
\item \.{kcatcode}=14のとき,
\.{char}, \.{chardef}は0~0x2E7Fの欧文文字が扱える.
\item \eupTeX では\.{kcatcode}=14のとき,
\.{Uchar}, \.{Ucharcat}, \.{iffontchar}は0~0x2E7Fの欧文文字が扱える.
\item |^^^^abcd|の書式は,その16bitコード(0xABCD)の欧文文字トークンを生成する
(\.{kcatcode}の設定に依らず常に欧文扱い.|^^ab|書式と同様).
\end{itemize}
関連ソフトウェアでは,\code{updvitype}も欧文用16bit OFM Level-0への対応を済ませた.
\pTeX 系列に対応したdviwareではすでにOFMへの対応が施されていることが多く,
\code{dvipdfmx}, \code{dvips}のような主要なdviwareでも
\upTeX の欧文文字コードの範囲拡張はすでにカバーされている.
現時点で\upTeX は欧文用OFM Level-1には未対応である.
\subsection{文字コードの取得と指定}\label{sec:getcode}
(u)\pTeX では「文字コードを引数にとるプリミティブ」といっても,状況によって
\begin{itemize}
\item 欧文文字の文字コード0--255をとる(例:\.{catcode})
\item 和文文字の内部コードをとる(例:\.{inhibitxspcode})
\item 上記2つのどちらでもとれる(例:\.{prebreakpenalty})
\end{itemize}
のいずれの場合もありうる.
\medskip
本ドキュメントでは上のどれかを明示するために,以下のような記法を採用する.
\begin{description}
\item[<8-bit number>] 0--255の範囲内の整数
\item[<kanji code>] 和文文字の内部コード
\item[<character code>] 0--255の範囲内の整数,および和文文字の内部コード
\item[<16-bit number>] 0--65535の範囲内の整数
\end{description}
和文文字の文字コードを数値で指定するには,内部コードで表現する必要がある.
この方法として,(u)\pTeX では以下が利用できる.
\begin{itemize}
\item \TeX82と同様に,
バッククオート(|`|)を使って「|`あ|」のようにして和文文字の内部コードを
内部整数として得ることができる.欧文文字については,1文字の制御綴を
代わりに指定することができる(例えば,「|`b|」と「|`\b|」は同じ意味である).
従来\pTeX 系列では同じことを和文文字に対して「|`\あ|」などと行うことはできなかったが,
\TeX~Live 2025 \pTeX~4.1.2以降可能になった\cite{tjb167}.
\item 数値で直接表現するために,異なるエンコードから内部コードへの
文字コード変換を行うプリミティブが用意されている.
\ref{sec:convert}節を参照.
\end{itemize}
\section{和文カテゴリーコードと\TeX の入力プロセッサ}
\TeX の処理は以下のような段階を踏み,\pTeX 系列でもこれは共通である.
%
https://blog.wtsnjp.com/2016/11/24/tex-by-topic1/
%
https://blog.wtsnjp.com/2017/03/31/tex-by-topic2/
\begin{itemize}
\item 入力を一行単位で読み込む(改行文字はCR,~LFいずれも可).
\item (\code{ptexenc}によるエンコード変換)
\item \emph{入力プロセッサ}がカテゴリーコードに従って「順に」トークン化
しつつ,その過程で
\begin{itemize}
\item \emph{展開プロセッサ}:マクロやアクティブ文字など
展開可能トークンの展開
\item \emph{実行プロセッサ}:代入やマクロ定義,出力リスト構築など
展開不能トークンの実行
\end{itemize}
も介入する\footnote{例えば,実行プロセッサの結果により
カテゴリーコードが変更されれば,
行内でも入力プロセッサの動作に影響を及ぼし,以降の展開・実行結果も変化する.
ただし,順に一度トークン化されたもののカテゴリーコードは固定である.}.
% e-TeX の \scantokens を除く.
\item \emph{ビジュアルプロセッサ}が受け取った出力リストを元に
行分割・ページ分割などを行い,ページをDVIに出力する.
\end{itemize}
\TeX82では各文字に0--15のカテゴリーコード(\.{catcode})を割り当てており,
入力プロセッサは「どのカテゴリーコードの文字が来たか」で状態が遷移する
有限オートマトンとして記述できる\cite{topic}.
\pTeX 系列においても同様であり,和文文字には欧文文字とは異なる
専用のカテゴリーコード(\.{kcatcode})を割り当てることで拡張している.
\.{kcatcode}の仕様は\pTeX と\upTeX で異なるので,別々に説明する.
% [TODO] 和文トークンの話は以下も参照しながら ptex-guide-en を整備
%
https://gist.github.com/zr-tex8r/629b5334d19cbcfc3fe58728b81b1c80
\subsection{和文カテゴリーコード【\pTeX の場合】}
\label{sec:ptex_kcat}
\pTeX が欧文\TeX と大きく異なるのは以下の点である.
\begin{itemize}
\item 文字コードによって和文文字(2バイト)と欧文文字(1バイト)を区別する.
\item 和文文字直後の改行は(欧文文字直後の改行と異なり)空白とみなさない.
\item 和文文字には役割に応じて16~($\mathit{kanji}$), 17~($\mathit{kana}$),
18~($\mathit{other\_kchar}$)の和文カテゴリーコードのいずれかを割り当てる.
初期状態では,JISの1,~2, 7--15, 85--94区の文字は18,3--6区の文字は17,
16--84区の文字は16に設定されている.
\item 和文文字トークンは文字コードのみで表現され,そのカテゴリーコードは
随時算出されるようになっている.
欧文文字トークンが\TeX82と同様にカテゴリーコード$c$と文字コード$s$の
組み合わせ($256c+s$)で表現されているのとは対照的である.
\end{itemize}
和文カテゴリーコードの値は一応,
16が「漢字」,17が「かな」,18が「その他の和文記号」を意図している.
ただし区の中身を見れば分かる通り,\pTeX では特に
全角数字・アルファベット(3区)とギリシャ文字(6区)も17であり,
キリル文字(7区)は18となっている.
和文カテゴリーコードの値による動作の違いは次のようになる
(16と17は\pTeX の内部処理においては全く等価で,18だけが異なる).
\begin{itemize}
\item \TeX82では,「複数文字からなる命令」(コントロールワード)には
カテゴリーコードが11~($\mathit{letter}$)の文字しか使用できないことになっていたが,
\pTeX ではカテゴリーコードが16,~17の和文文字も合わせて使用することができる.
\item 一方,カテゴリーコードが18の和文文字はコントロールワード中には使用できない.
「|\】|」のように一文字命令(コントロールシンボル)に使用することはできる
\footnote{「|\】|」のような和文のコントロールシンボルで行が終わった場合,
「|\!|」のような欧文コントロールシンボルと同様に改行由来の空白が追加されてしまい,
和文文字直後の改行は何も発生しないという原則に反していたが,
これは\TeX~Live 2019の\pTeX~3.8.2で修正された\cite{tjb37}.}.
\item 後で説明する\.{jcharwidowpenalty}は,カテゴリーコードの値が16,~17の
和文文字の前にのみ挿入されうるもので,値が18の和文文字の前には挿入されない.
\item いずれにせよ,和文文字は決して“アクティブ”(欧文文字における
カテゴリーコード13のような状態)にはならない.
\end{itemize}
従って,\emph{\pTeX の既定では
コントロールワードに全角数字・アルファベット・ギリシャ文字を含めることができるが,
キリル文字は不可(コントロールシンボルのみ)である}ことがわかる
(\upTeX の既定では全て不可).
% upTeX の既定では,全角数字とアルファベット(Halfwidth and Fullwidth Forms)・
% ギリシャ文字・キリル文字の全てが18である.
\medskip
和文カテゴリーコードを取得・設定するプリミティブが\.{kcatcode}である.
\begin{cslist}
\csitem[\.{kcatcode} <character code>=<16--18>]
コミュニティ版\pTeX では,和文カテゴリーコード(\.{kcatcode})は
DVI中の上位バイトごと(すなわち,JISコードでいう区ごと)に値が設定可能である
\footnote{%
オリジナルのアスキー\pTeX では,内部コードの上位バイトごとに値が設定可能であった.
すなわち,内部コードがEUC-JPのときは区ごとに設定可能であったが,
内部コードがShift-JISのときは
$2n-1$区・$2n$区($1\leq n\leq 47$)は同一のカテゴリーコードを持つことになる.
}.\end{cslist}
\begin{dangerous}
\.{kcatcode}では欧文文字の文字コード(0--255)も指定することができるが,
その場合「0区扱い」として扱われる.
\pTeX の処理でこの「0区」の\.{kcatcode}が使われることはないので,
事実上は「16--18のどれかを格納可能な追加レジスタ」程度の使い方しかない.
\end{dangerous}
しかし,
\pTeX においては,\.{kcatcode}を文書の処理途中で変更することは想定されていない.
というのも,\pTeX では(\upTeX と異なり)和文文字トークンに
カテゴリーコードの情報は保存されず,
和文文字が処理対象となるたびにカテゴリーコードの値が随時算出されるためである.
ただし,\pTeX でも |\let\CS=あ| などとして和文文字トークンを|\let|すると,|\CS|には
その時のカテゴリーコード(\.{kcatcode})が保存される\footnote{コミュニティ版\pTeX では,
一時的に「和文文字トークンを|\let|した|\CS|においても,それが処理対象となるたびに
カテゴリーコードの値を再取得する」という挙動に変更しようとした(r51021).
しかし,この変更が不完全で「\.{ifcat}では再取得するが,\.{ifx}では再取得しない」という
不統一な状態となってしまったため,r59699で従来の挙動に戻した(アスキー版と同じ).
結果的に,\TeX~Live 2019--2021では「ただし,…」が当てはまらない\cite{man4}.}.
% 不統一な挙動になっているのは以下のバージョン.
% * TeX Live 2019 rebuild 2019-05-30 (p3.8.2)
% * TeX Live 2020 (p3.8.3)
% * TeX Live 2021 (p3.9.0)
\begin{dangerous}
例えば,\pTeX では以下のコードで定義される|\X|,~|\Y|で引数終端を示す「あ」には
カテゴリーコードの情報は格納されないため,|\X|と|\Y|は全く同じ動作となる.
一方,同じコードを\upTeX で実行すると,|\X|と|\Y|は異なる動作となる.
\begin{verbatim}
\kcatcode`あ=16
\def\X#1あ{\message{X: #1}}
\kcatcode`あ=17
\def\Y#1あ{\message{X: #1}}
\end{verbatim}
\end{dangerous}
\subsection{和文カテゴリーコード,和文文字と欧文文字の区別【\upTeX の場合】}
\label{sec:uptex_kcat}
\upTeX においては\.{kcatcode}が\pTeX から大きく仕様変更されている
\footnote{\upTeX の正式用語としては,和文文字トークン(和文トークン)は
CJK文字トークン(CJKトークン)と呼ぶべきだが,本文書では単純化のため
\pTeX と同じ用語を用いる.}:
\begin{itemize}
\item \.{kcatcode}プリミティブに和文文字の役割の分類だけでなく,
トークン列生成における和文文字と欧文文字の区別という機能も付与する.
具体的には,\emph{\.{kcatcode}に特別な値として15~}($\mathit{not\_cjk})$\emph{を
設定すると,それは8ビット欧文文字のバイト列として扱われ,和文扱いされなくなる}.
\item 和文文字に可能なカテゴリーコードとして19~($\mathit{hangul}$)を追加する.
\emph{カテゴリーコード19の和文文字は,直後の改行を欧文同様に空白とみなす}
という点が特別であり,それ以外の点ではカテゴリーコード16,~17の和文文字と同様である
(例えば,コントロールワード中にも使用できる).
\item \emph{和文文字トークンについてもカテゴリーコード}(\.{kcatcode})\emph{の情報を含む}.
欧文トークンをcatcode 4bit + charcode 8bitで,
和文トークンをkcatcode 5bit + charcode 24bitで表す.
\item \.{kcatcode}に14 ($\mathit{latin\_ucs}$)と20 ($\mathit{modifier}$)が\TeX~Live 2025で新設された.
内容は\ref{sec:uptex_extension}節で詳説した.
\end{itemize}
\begin{cslist}
\csitem[\.{kcatcode} <character code>=<14--20>]
内部レガシーの\upTeX では,\pTeX と同様に
JISコードでいう区ごとに値が設定可能.
内部Unicodeの\upTeX では,和文カテゴリーコード(\.{kcatcode})は
概ねUnicodeのブロックごと(※一部のブロックは分割してある)に値が設定可能である.
% 分割状況:
https://github.com/texjporg/tex-jp-build/issues/43
\end{cslist}
このように内部Unicodeの\upTeX では\.{kcatcode}の設定が
Unicodeのブロックごとであるので,
\pTeX のJISコードの区ごとに設定したものとは分類が必ずしも一致しない.
各ブロックの初期値については
\href{
https://github.com/texjporg/uptex-base}{\file{uptex-base}}で配布している
\file{01uptex_doc_utf8.txt}を参照のこと.
\begin{dangerous}
例えば長音記号「ー」はJISコードで\codeHEX{\tojis`ー}% JIS 0x213C
であり,記号として1区に含まれるから\pTeX での\.{kcatcode}は18である
(内部レガシーの\upTeX でも同様).一方Unicodeでは\codeHEX{\toucs`ー}% U+30FC
であり,カタカナと同じブロックに含まれるから内部Unicodeの\upTeX での
\.{kcatcode}は17である.すなわち,\pTeX では「ー」をコントロールワード中に
含められないが,\upTeX では許される.
\begin{verbatim}
\def\黄マーカー{...}
% => pTeX では「\黄マ」という命令と「ーカー」という終端
% => upTeX では「\黄マーカー」という命令が定義される
\newcommand{\黄マーカー}[1]{...}% => pTeX ではエラー,upTeX では通る
\end{verbatim}
%
https://okumuralab.org/tex/mod/forum/discuss.php?d=2703
もちろんこの逆の例もあり,
\pTeX では全角数字とアルファベット(Halfwidth and Fullwidth Forms),
ギリシャ文字が17であったが,\upTeX では(キリル文字と同じく)18としている.
\end{dangerous}
なお\ref{sec:uptex_code}節で述べた通り,\upTeX では内部コードによらず
0--127の7ビットASCII文字集合は常に欧文文字トークンとして扱うこととしている.
裏を返せば\emph{和文文字トークンで文字コードが0--127という状況は
起こりえない}\footnote{和文文字ノードとしては文字コード0--127も可能:
\ref{sec:kchar}節で出てくる\.{kchar}で生成される.}し,
このブロックの\.{kcatcode}を15以外に設定しても和文扱いはされない.
\begin{dangerous}
例えば\upTeX の既定(内部Unicode)から |\kcatcode`あ=15| を実行すると,
以降の「|あ|\relax」は |^^e3^^81^^82| を入力したとみなされる
\footnote{内部EUC-JPでは |^^a4^^a2|,内部Shift-JISでは |^^82^^a0|になる.}.
この状況で続けて |\kcatcode`あ=17| を実行しても,
それは |\kcatcode`^^e3^^81^^82| の入力とみなされるので元には戻らない:
代わりに |\kcatcode\ucs"3042=17| と実行する必要がある.
\end{dangerous}
既定ではこのように和文と欧文が\.{kcatcode}の値(16--20か,14--15か)に従って
区別されるが,以下のプリミティブによって変更可能である.
\begin{cslist}
\csitem[\.{enablecjktoken}]
和文文字と欧文文字の区別について\.{kcatcode}の設定に従い,
15以下なら欧文扱い,16以上なら和文扱いにする.
\upTeX の既定はこの状態である.
\csitem[\.{disablecjktoken}]
全てのUnicode文字を(\.{kcatcode}にかかわらず)欧文扱いにする(単なるバイト列として扱う).
入力に関して(\code{ptexenc}ライブラリによる前処理を除き)8-bit欧文\TeX と互換になる.
\csitem[\.{forcecjktoken}]
ASCII文字以外のUnicode文字を(\.{kcatcode}にかかわらず)
強制的に和文扱いにする.
このとき,\.{kcatcode}が15の文字は「その他和文」(18)扱いになる.
\begin{verbatim}
\forcecjktoken\kcatcode`西=15
\message{\the\kcatcode`@ % ==> 18
\ifcat 西@ T\else F\fi}% ==> T
\end{verbatim}
\end{cslist}
\subsection{\pTeX の入力プロセッサ}% \pTeX~4.0.0での改修を含む
\label{sec:ptex_input}
\begin{figure}[b]
\small
\[
\entrymodifiers={++[o][F-]}
\xymatrix{%
*\txt{}&*\txt{}&*\txt{}&*\txt{}\\
*\txt{}\ar[r]&
\textit{N} \ar@(ur,ul)[rr]^{1,2,7,13,E}
\ar[u]^{5\tpar, 14}
\ar@(d,l)[]^{9\tign,10\tign}
\ar@/_3em/[ddrr]^(0.55){J}
\ar[dr]^(0.4){0}&*\txt{}
&\textit{M}
\ar[u]^-{5\tsp,14}\ar@/_.5em/[dd]_(0.7){J}
\ar@/_3em/[lldd]_(0.85){10}
\ar@(u,r)[]^{1,2,7,9\tign,13,E}
\ar@/_1ex/[dl]_0&*\txt{}\\
*\txt{}&*\txt{}&*+[F-]\txt{\mbox{制御綴読み取り}}
\ar@{-->}@/^1ex/[dl]\ar@{-->}@/_1ex/[ur]
\ar@{-->}@/^1ex/[rrr]
&*\txt{}&*\txt{}&\textit{T}
\ar@/^1ex/[lll]^(0.25){0}
\ar[llu]_{7,13,E}\ar[d]^-{5,14}\ar@/^1ex/[lld]^{1,2,J}
\ar@(u,r)[]^{9\tign,10\tign}
\\
*\txt{}&
\textit{S}\ar@/^.5em/[ur]^-(0.4){0}
\ar[d]^-{5,14}
\ar@(d,l)^{9\tign,10\tign}
\ar@(d,d)@/_3em/[rr]_{J}
\ar@/_3em/[uurr]_(0.3){1,2,7,13,E}&*\txt{}&
\textit{K}\ar[ul]^(0.3){0}\ar@/_.5em/[uu]_(0.3){7,13,E}
\ar@/^1.5em/[ll]^{10}
\ar@(d,r)[]_{1,2,9\tign,J}
\ar[d]_-{5,14}
&*\txt{}&*\txt{}\\
*\txt{}&*\txt{}&*\txt{}&*\txt{}
%
}
\]
\centering
\parbox{35zw}{%
``E''はカテゴリーコード3, 4, 6, 8, 11, 12の文字達を,``J''は和文文字を表す.\\
``$5\tpar$''のような下付き添字は「挿入するトークン」を表す.\\
但し,``$9\tign$'', ``$10\tign$''はその文字を無視することを示している.
}
\caption{\pTeX~4.0.0(既定)の入力プロセッサの状態遷移図}
\label{fig:ptex_input}
\end{figure}
% [TODO] カテゴリーコード 19 を図に入れていない
先に述べた通りであるが,\pTeX の入力プロセッサは\TeX82のそれを拡張したものになっている.
\autoref{fig:ptex_input}は\emph{\pTeX~4.0.0既定時}における入力プロセッサの状態遷移図である.
\TeX82から拡張された点,および説明が必要な点を以下に述べる.
\begin{description}
\item[内部状態の追加] \TeX82では状態\textit{N} (new line),状態\textit{M} (middle of line),
状態\textit{S} (skipping spaces)という3状態であったが,\pTeX では
次の2状態が追加された:
\begin{description}
\item[状態\textit{K}] 和文文字の直後.状態\textit{M}との差異は改行でスペースを出力しないこと.
\item[状態\textit{T}] 和文文字で終わるコントロールワードの直後.
状態\textit{S}との差異はグループ開始・終了(|{|, |}|)での遷移先が
状態\textit{M}でなく状態\textit{K}であること.
\end{description}
\item[「制御綴読み取り」後の状態] 以下のように決まっている:
\begin{itemize}
\item 制御綴が「|\ |」のようなカテゴリーコード10の文字
からなるコントロールシンボルのときは状態$S$に遷移する.
\item 制御綴が「|\#|」「|\】|」のようなその他のコントロールシンボルのときは状態$M$に遷移する.
\item 制御綴がコントロールワードのときは,
その名称の末尾の文字が欧文文字のときは状態$S$に,和文文字のときは状態$T$に遷移する.
\end{itemize}
\end{description}
図を見れば分かる通り,(欧文文字直後の改行は空白文字扱いされるのと対照的に)
\emph{和文文字直後の改行は何も発生しない}.
これは,日本語の原稿内では自由な箇所で改行が行えたほうが便利なためである.
% jtexdoc.tex に記載あり
実際には以下に説明する\.{ptexlineendmode}プリミティブによって,\pTeX の入力プロセッサの挙動は
ある程度ユーザが制御できる.
\begin{cslist}
\csitem[\.{ptexlineendmode}=<0--7>]
\pTeX の入力プロセッサの挙動を制御する.この値を2進法で$zyx$と表したとき
\footnote{%
つまり$x$は「一の位」,$y$は「二の位」,$z$は「四の位」である.
8以上の値を指定した場合は,下位3~bitの値が使われる.
負数を指定してもエラーは発生しないが,その場合の動作は未定義である.
},$x$,~$y$,~$z$の値は,それぞれ以下のような状態で行が終わった場合,
改行が空白文字を発生させるかを制御する.
いずれも0では「空白文字を発生させない」,1では「空白文字を発生させる」.
\begin{description}
\item[$x$] 和文文字で終わるコントロールワードの直後にグループ開始・終了が1つ以上
\footnote{%
\pTeX では,このとき「改行が何も発生させない」挙動を伝統的にとってきた
(\TeX82からの改造量を減らしたかったのであろう).
この挙動の是非が\.{ptexlineendmode}実装の一要因となった.
}
\item[$y$] 和文文字からなるコントロールシンボルの直後
\item[$z$] (コントロールワード・コントロールシンボルの名称の一部でない)
和文文字の直後にグループ開始・終了が1つ以上
\end{description}
このプリミティブは\pTeX~4.0.0で追加された.既定値は0(つまり$x=y=z=0$).
\end{cslist}
\begin{dangerous}
「和文文字からなるコントロールシンボルの直後にグループ開始・終了が1つ以上ある」状態で行が終了した場合,
改行が空白文字を発生させるのは$y$,~$z$のうち少なくとも1つが1のときである.
\end{dangerous}
\begin{dangerous}
従って,和文文字と行末の関係を例で示すと,以下のようになる:
\medskip
\begin{enumerate}
\itemsep\medskipamount
\item コントロールワード・コントロールシンボルの一部でない和文文字で行が終わった場合,
改行は何も発生しない.
\medskip
\begin{minipage}[t]{13zw}
\begin{verbatim}
あいあ
い
\end{verbatim}
\end{minipage}\quad →\quad
\begin{minipage}[t]{5zw}
あいあ
い
\end{minipage}%
\item コントロールワード・コントロールシンボルの一部でない和文文字の直後に
グループ開始・終了(|{|, |}|)が1つ以上ある状態で行が終わった場合,
\.{ptexlineendmode}の値が0--3のとき,改行は何も発生しない.
4--7のとき,改行は空白文字を発生する.
\medskip
\begin{minipage}[t]{13zw}
\begin{verbatim}
\ptexlineendmode=0
{あいあ}
い
\end{verbatim}
\end{minipage}\quad →\quad
\begin{minipage}[t]{5zw}
\ptexlineendmode=0
{あいあ}
い
\end{minipage}%
\hfill\vrule\hfill\kern-2zw
\begin{minipage}[t]{13zw}
\begin{verbatim}
\ptexlineendmode=4
{あいあ}
い
\end{verbatim}
\end{minipage}\quad →\quad
\begin{minipage}[t]{5zw}
\ptexlineendmode=4
{あいあ}
い
\end{minipage}
\item 和文文字で終わるコントロールワードの直後にグループ開始・終了が
1つ以上ある状態で行が終わった場合,
\.{ptexlineendmode}の値が偶数のとき,改行は何も発生しない.
奇数のとき,改行は空白文字を発生する.
\medskip
\begin{minipage}[t]{13zw}
\begin{verbatim}
\ptexlineendmode=0
\def\漢{あ}{\漢}
い
\end{verbatim}
\end{minipage}\quad →\quad
\begin{minipage}[t]{5zw}
\ptexlineendmode=0
\def\漢{あ}{\漢}
い
\end{minipage}%
\hfill\vrule\hfill\kern-2zw
\begin{minipage}[t]{13zw}
\begin{verbatim}
\ptexlineendmode=1
\def\漢{あ}{\漢}
い
\end{verbatim}
\end{minipage}\quad →\quad
\begin{minipage}[t]{5zw}
\ptexlineendmode=1
\def\漢{あ}{\漢}
い
\end{minipage}
\item 和文文字からなるコントロールシンボルで行が終わった場合,
\.{ptexlineendmode}の値が0,~1, 4,~5のとき,改行は何も発生しない.
2,~3, 6,~7のとき,改行は空白文字を発生する.
\medskip
\begin{minipage}[t]{13zw}
\begin{verbatim}
\ptexlineendmode=0
\def\】{あ}\】
い
\end{verbatim}
\end{minipage}\quad →\quad
\begin{minipage}[t]{5zw}
\ptexlineendmode=0
\def\】{あ}\】
い
\end{minipage}%
\hfill\vrule\hfill\kern-2zw
\begin{minipage}[t]{13zw}
\begin{verbatim}
\ptexlineendmode=2
\def\】{あ}\】
い
\end{verbatim}
\end{minipage}\quad →\quad
\begin{minipage}[t]{5zw}
\ptexlineendmode=2
\def\】{あ}\】
い
\end{minipage}
\item 和文文字からなるコントロールシンボルの直後にグループ開始・終了が1つ以上ある状態で行が終わった場合,
\.{ptexlineendmode}の値が0,~1のとき,改行は何も発生しない.
その他のとき,改行は空白文字を発生する.
\medskip
\begin{minipage}[t]{13zw}
\begin{verbatim}
\ptexlineendmode=0
\def\】{あ}{\】}
い
\end{verbatim}
\end{minipage}\quad →\quad
\begin{minipage}[t]{5zw}
\ptexlineendmode=0
\def\】{あ}{\】}
い
\end{minipage}%
\hfill\vrule\hfill\kern-2zw
\begin{minipage}[t]{13zw}
\begin{verbatim}
\ptexlineendmode=1
\def\】{あ}{\】}
い
\end{verbatim}
\end{minipage}\quad →\quad
\begin{minipage}[t]{5zw}
\ptexlineendmode=1
\def\】{あ}{\】}
い
\end{minipage}
\par\medskip
\begin{minipage}[t]{13zw}
\begin{verbatim}
\ptexlineendmode=2
\def\】{あ}{\】}
い
\end{verbatim}
\end{minipage}\quad →\quad
\begin{minipage}[t]{5zw}
\ptexlineendmode=2
\def\】{あ}{\】}
い
\end{minipage}%
\hfill\vrule\hfill\kern-2zw
\begin{minipage}[t]{13zw}
\begin{verbatim}
\ptexlineendmode=4
\def\】{あ}{\】}
い
\end{verbatim}
\end{minipage}\quad →\quad
\begin{minipage}[t]{5zw}
\ptexlineendmode=4
\def\】{あ}{\】}
い
\end{minipage}
\medskip
\end{enumerate}
\ptexlineendmode=0
なお,以前の\pTeX の入力プロセッサの挙動は
\begin{itemize}
\item \pTeX~3.8.1以前(アスキー版も同じ)の挙動は|\ptexlineendmode=3|~($(x,y,z)=(1,1,0)$)
\item \pTeX~3.8.2以降3.10.0までの挙動は|\ptexlineendmode=1|~($(x,y,z)=(1,0,0)$)
\end{itemize}
としてそれぞれ再現できる\cite{tjb87}.
% * 欧文文字直後の改行では空白文字を発生させる
% * コントロールワードや「\ 」の直後の改行は何も発生しない
% * 「\ 」以外のコントロールシンボルの直後の改行は空白文字を発生させる
% * 和文文字直後の改行は何も発生させない
% * 和文文字→グループ境界 {, } が有限個という状態で行が終わった場合も,
% 何も発生しない(!)
% ref.
https://qiita.com/h-kitagawa/items/de963380bd3e576ab4e3
\end{dangerous}
\subsection{和文文字の文字列化の挙動}% \pTeX~4.0.0での改修を含む
\label{sec:printkanji16bit}
\.{meaning}や\.{string}などの文字トークン列生成(いわゆる“\.{the}-文字列化”)に
ついては以下の通りである.
\begin{itemize}
\item 欧文文字は\TeX82と同様で,(文字コード32の空白を除き)
すべてカテゴリーコード12の欧文文字トークンになるが,
和文文字は和文文字トークンになる.その和文カテゴリーコードは
\pTeX では随時算出により,\upTeX では「その時の\.{kcatcode}の値」(ただし
それが15の場合は18)になる.
\item 制御綴名の文字列化において「コントロールワードの文字列化では後ろに空白文字を補い,
コントロールシンボルの文字列化では空白文字を補わない」という点は,
和文文字を含む場合も同様である
\footnote{「|\】|」のように和文文字からなるコントロールシンボルを文字列化する際に,
バージョンp3.7.2以前の\pTeX では「|\】 |」と後ろに余計な空白文字を補ってしまう
という問題があった.
\TeX~Live 2018の\pTeX~3.8.1でこの問題は修正された\cite{tjb37}.}.
\item 和文文字はそのカテゴリーコードによらず,\.{meaning}すると
\begin{itemize}% すべて "kanji character " になる
\item \the\kcatcode`漢:\quad \texttt{\meaning 漢}
\item \the\kcatcode`あ:\quad \texttt{\meaning あ}
\item \the\kcatcode`):\quad \texttt{\meaning )}
\end{itemize}
となる.
\end{itemize}
さて,\pTeX~version 3系列(\TeX~Live 2021まで)では\.{meaning},\.{string}等の
文字列化や制御綴名において和文文字と欧文文字の区別が失われてしまうケースがあった.
% 途中の結果を一旦配列 |str_pool| に格納する処理で和欧文の区別が失われていた.
\emph{\pTeX~4.0.0以降}(\TeX~Live 2022)では,この状況でも
和欧文の区別が維持される\cite{tjb81}.
\begin{dangerous}
\eTeX 由来の\.{scantokens}(\eTeXpre(u)\pTeX で利用可能)は
和文文字と欧文文字の区別が維持されない.
例えば\.{forcecjktoken}の状態で欧文バイト列を\.{scantokens}すると和文になる
\footnote{\.{scantokens}は,引数のトークン列を脱トークン化して,
改めて字句解析対象となる文字列として読み込む展開可能プリミティブである.
基本的にはトークン列を一旦(仮想的な)ファイルに書き出して
それをすぐに読み込んだのと同じになるが,
%
https://qiita.com/zr_tex8r/items/0cc96144dd46c212a989
「引数を文字列化→bufferに書き戻し→それを入力として扱う」という動作手順のうち
bufferに書き戻す時点で和欧文の区別が失われる.
実際に一旦ファイルに書いて読み込む場合は,欧文バイトは
|^^|形式で書き出されて欧文のままになるので,それとは異なる.}.
% [TODO] -translate-file=cp8bit なら 8bit 全部が printable になるので ^^ab 形式にはならない.
\end{dangerous}
\begin{dangerous}
\TeX~Live 2021では,ファイルのエンコードUTF-8,内部コードEUC-JPの場合に例えば
\begin{verbatim}
\def\fuga{^^c3^^bf 耽}\fuga
\meaning\fuga
\end{verbatim}
と入力すると,一行目は\def\fuga{^^c3^^bf 耽}「\code{\fuga}」であるのに対し
二行目は「\code{macro:->耽 耽}」となっていた(\char\euc"C3BFはEUC-JPで
\hex{C3BF}である.|^^c3^^bf|の代わりに直接\code{ÿ}と入力しても同様).
また
\begin{verbatim}
\catcode"C3=11 \catcode"BF=11
\def\耽{P} \def\^^c3^^bf{Q}
\end{verbatim}
としたときの|\meaning\耽|は「|macro:->Q|」であった.
改修後の\TeX~Live 2022では,一つ目の例は
\def\fuga{^^c3^^bf 耽}「\code{\meaning\fuga}」% 和欧文が区別される
であるし,二つ目の例は
\catcode"C3=11 \catcode"BF=11
\def\耽{P} \def\^^c3^^bf{Q}
「\code{\meaning\耽}」% 和欧文が区別されるので "P" になるはず
となる.
%%%
% [動作チェック!]
% 上の行の説明文では |\耽| と |\^^c3^^bf| が区別される TL2022 以降を期待している!
\def\XXXX{P}\unless\ifx\耽\XXXX\ptErr{Check above: pTeX 4.x assumed}\fi
%%%
\end{dangerous}
% メモ:上の例は「^^c5^^bf <=> 顛」でもよかったのだが,
% マニュアルの欧文フォント newtx/newpx で表示可能な文字にした.
% 外部ファイル出力の変化例:
% \label{ß}% % TL2021: <C3>^^9f => TL2022: ^^c3^^9f
% \label{^^c3^^9f}% % TL2021: <C3>^^9f => TL2022: ^^c3^^9f
% \label{ÿ}% % TL2021: 耽 => TL2022: ^^c3^^bf
% \label{^^c3^^bf}% % TL2021: 耽 => TL2022: ^^c3^^bf
\section{和文文字の出力}\label{sec:outchar}
\TeX の実行プロセッサは展開不能トークンを実行し,
組版結果を出力リストとして構築していく.
このとき,文字トークンは\emph{文字ノード}に変換される.
また,文字コードの数値から文字ノードを生成できる
\.{char} <character code>や,その短縮形<control sequence>を
定義する\.{chardef} <control sequence>=<character code>も
同様に文字ノードを生成する.
この仕組みは\pTeX 系列でも同じであり,
ただし日本語の文字を出力するために和文文字ノードを使用する.
% TeX Wiki「TeX入門/マクロの作成」より整形
% \TeX は最初に垂直モードで始まり,
% 展開不能トークンに従って処理を進めていく.
% 垂直モードでは,処理する要素がボックスや罫線であれば
% 次々に垂直方向に積み下げながら要素の高さや深さを積算していく.
% 決まった長さになるとページ分割し,そこまでの要素を
% DVIファイルの1ページ分として出力するためのoutputルーチンを起動する.
% これは|\output|というトークンリストレジスタに保存されたトークン列を
% 命令として実行する.
% 垂直モードでの処理中に「水平方向の要素」を見つけると,
% 自動的に水平モードに移行して行の作成作業に入る.
% ここで「水平方向の要素」と,文字トークンなど行中に配置すべきものである.
% 水平モードでは,文字や罫線を水平に並べながら幅を積算していき,
% 決まった長さになると行分割し,一行分をボックスにまとめて
% 外側の垂直ボックスに並べていく.
% 行分割しても段落が続く限り次の行を作り続け,
% 段落終了を意味する|\par|命令や空行を見つけると,
% 段落最後の行を作って元の垂直モードに復帰する.
欧文文字ノードは1つの\node{char_node}に
フォントと文字コードの情報を格納している.
和文文字ノードは内部的には連続する2つの\node{char_node}を用いて
\begin{itemize}
\item 1つ目にフォントと文字タイプの情報
\item 2つ目に文字コードの情報(\upTeX ではさらに\.{kcatcode}の情報も)
\end{itemize}
を格納している\footnote{ここで,
\pTeX では(和文文字トークンと同様)和文文字ノードに
\.{kcatcode}の情報が保存されず,必要に応じて
(=後述の\.{jcharwidowpenalty}挿入時)再計算される.
\upTeX では(こちらも和文文字トークンと同様)和文文字ノードに
\.{kcatcode}の情報が保存される(=後述の\.{jcharwidowpenalty}挿入のため).}.
% jtex.tex の「TFMファイルとcharノード」を簡略化
% [TODO] upTeX での説明は合っているか?
% eptex_resume.pdf によると TeX--XeT の upTeX 対応で
% * pTeX では和文1文字が内部では2つのノードで表現されていることを前提にした.
% * upTeX のUnicode拡張によって1文字3ノードとかになっていないか心配したが
% どうやらそのような事態は起こっていないように思えた.
% と書かれているので,合っていると思われるが….
\subsection{文字ノードの生成}\label{sec:kchar}
実際に文字ノードが生成する状況は以下である.
\begin{itemize}
\item 欧文文字トークンは欧文フォントを使用した\emph{欧文文字ノード}になる.
\item 和文文字トークンは和文フォントを使用した\emph{和文文字ノード}になる.
\item \.{char}, \.{chardef}は文字コード0--255からは\emph{欧文文字ノード}を,
それ以外の文字コードからは\emph{和文文字ノード}を生成する
\footnote{\.{char}/\.{chardef}は文字トークンを経由しないので,
\upTeX においても\.{kcatcode}は基本的に関係ない.
ただし\upTeX~u2.00以降では,文字コード256--0x2E7Fについても,
\.{kcatcode}=14に設定されている場合に限って\emph{欧文文字ノード}を生成する.
\ref{sec:uptex_extension}節を参照のこと}.
\end{itemize}
ここで,\upTeX では\.{char}, \.{chardef}の挙動が問題になる.
これらは文字コードの数値から直接文字ノードを生成するが,
\pTeX および\upTeX の内部レガシーでは
欧文文字と和文文字の有効な文字コードが重ならないので,
生成すべき文字ノードの種類が文字コードによって一意に定まっていた.
ところが\upTeX の内部Unicodeでは,0--255の値が
欧文文字と和文文字のいずれの文字コードとしても有効であり,
\.{char}, \.{chardef}はそのうち欧文文字ノードを選択していることを意味する.
文字トークンに限っても128--255の値はいずれも有効であるのに,
このままでは,和文文字トークンから出力できる文字コード128--255の
和文文字ノードを,文字コードの数値からは直接出力できないことになる.
そこで,\upTeX では新たに「必ず和文文字ノードを生成するプリミティブ」を
追加している.必要に駆られた128--255のみならず,便宜のため
文字コード0--127に対しても機能する.また内部コードによらず利用可能である.
\begin{cslist}
\csitem[\.{kchar} <character code>(\emph{\upTeX のみ})]
\.{char}の和文固定版で,
文字コード<character code>から和文文字ノードを生成する.
\csitem[\.{kchardef} <control sequence>=<character code>(\emph{\upTeX のみ})]
\.{chardef}の和文固定版で,
\.{kchar} <character code>の短縮形として<control sequence>を定義する.
\end{cslist}
\subsection{和文フォント}
\label{sec:jfont}
\TeX は組版を行うとき,文字の情報をTFMファイルから参照する.
\pTeX 系列も同様で,欧文文字についてはTFMファイルを参照するが,
和文文字についてはJFMファイルを参照する.
ファイル名はどちらも\code{フォント名.tfm}である.
TFMファイルには,大別すると
\begin{itemize}
\item それぞれの文字に関する事柄
(各文字の幅,高さ,深さなど)
\item そのTFMファイルに収められている文字に共通する事柄
(文字の傾き,デザインサイズ,そのフォントの基準値(em, ex)など)
\item 特定の文字の組み合わせのときの事柄
(合字やカーニングなど)
\end{itemize}
の3種類の情報が設定されている.
JFMファイルもTFMファイルと同様の情報を持つが,
\begin{itemize}
\item 日本語の文字は数が多いので,
文字を単位とするのではなく,共通する性質を持つ文字を
一つにまとめてタイプ別の設定を行う
\item 横組み用と縦組み用の区別がある
\end{itemize}
という点が異なる.JFMフォーマットの詳細は,
この文書と同じディレクトリにある\cite{jfm}を参照されたい.
% [TODO] 一つの文書で用いることができるフォント数の上限は?
\begin{cslist}
\csitem[\.{jfont}, \.{tfont}]
欧文フォントを定義したり,現在の欧文フォントを取得したりする\.{font}の和文版である.
一応\.{jfont}が「和文の横組用フォント」の,\.{tfont}が「和文の縦組用フォント」のために
用いる命令である.
\begin{itemize}
\item フォントを定義する際は,欧文フォント・和文の横組用フォント・
和文の縦組用フォントのいずれも
\.{tfont}, \.{jfont}, \.{tfont}のどれを用いても定義できる
(要求された実際のTFM/JFMに応じて,自動的にアサインされる).
書式については後述.
\item \.{the}等で「現在のフォント」を取得する際には,
\.{jfont}で「和文の横組用フォント」を,
\.{tfont}で「和文の縦組用フォント」を返す.
\item \.{nullfont}は全ての文字が未定義な「空フォント」を指すが,
これは欧文フォントであり,和文版\.{nullfont}という概念は存在しない.
これは,\pTeX では「全ての和文フォントには,和文文字コードとして有効な
全ての文字が存在する」という扱いになっているためである.
\end{itemize}
\end{cslist}
\begin{dangerous}
細かい話をすれば,\pTeX のini modeでのフォーマット作成時に和文フォントを
何も選択しなければ,|\fontname\jfont|が|nullfont|となり,
また和文文字を入力してもノードは作られない\footnote{ただし,
$\.{tracinglostchars}>0$でも
\code{Missing character: There is no あ in font nullfont!}のような
警告は出ない.}ので,
「和文版\.{nullfont}が選択されている」と言えなくもない.
ただ,いったん実際の和文フォントを選択した後に
「和文版\.{nullfont}を選択する」という制御綴は作れないと思われる.
% つまり,tikzpicture環境のように|\selectfont|を\.{nullfont}に
% 再定義した状態では,和文文字だけ消えずに残る.
%
https://tex.stackexchange.com/questions/18602/
%
https://twitter.com/doraTeX/status/1098584763277824000
%
https://twitter.com/zr_tex8r/status/1098594165573722112
\end{dangerous}
なお,\pTeX~4.1.0以降では\.{font}, \.{jfont}, \.{tfont}のいずれも
フォントを定義する際の書式が拡張されている.
\begin{itemize}
\item \TeX82書式:
\.{font}<control sequence><equals><file name><at clause>
\item (u)\pTeX 書式:
\.{font} [<in spec>] <control sequence><equals><file name><at clause>
\end{itemize}
なお,ここで
\begin{itemize}
\item <in spec> $\longrightarrow$ |in| <encoding>
\item <at clause> $\longrightarrow$ |at| <dimen> $\OR$ |scaled| <number> $\OR$ <optional spaces>
\end{itemize}
であり,追加された<in spec>は
「和文フォントを定義したJFMがJISエンコードであるかUnicodeエンコードであるか」
を明示的に指定する場合に用いる.指定可能な<encoding>は|jis|, |ucs|に限られる.
この書式を用いることで,例えば
\begin{itemize}
\item \pTeX(内部コード|euc|または|sjis|)でも
\verb|\font in ucs \myfontA=upjisr-h|により\upTeX 用JFMである
|upjisr-h.tfm| (UCS-encoded)を,
\item \upTeX(内部コード|uptex|すなわちUnicode)でも
\verb|\font in jis \myfontB=min10|により\pTeX 用JFMである
|min10.tfm| (JIS-encoded)を,
\end{itemize}
それぞれ(エンジン内部でJIS⇔Unicode変換を行いながら)読み込んで
正しくグルー・カーンを挿入できるし,DVIへの出力時にも(逆変換により)
指定されたエンコードで文字を出力する
\footnote{この新書式を導入した目的は,
将来\upTeX の内部コードがUnicode固定になった場合に
字幅やグルー・カーンが定義された\pTeX 用JFM/VFセットを
\upTeX 用に用意しなおさなくても済むようにするためである\cite{tjb149}.}.
% 明示指定されたエンコードが実際のJFMに合致するかの自動判定は行わない.
% また,\pTeX での in jis 指定・\upTeX での in ucs 指定は冗長であると
% ともに,現在の実装コードでは文字クラス(char\_type)の検索が遅くなる.
% これは\pTeX の実装はJFMフォーマットの仕様の「char\_typeテーブル内には
% 文字コードの昇順で収められていなければならない」という規定を前提に
% 検索最適化されているのに対し,エンコード変換が絡むと順番が崩れるためである.
なお,<in spec>のスキャン時には展開を行わない.
これは後続の<control sequence>が未定義のときに先にエラーを発するのを防ぐためである.
\begin{dangerous}
\pTeX で\verb|\font in ucs ...|により\upTeX 用JFMを読み込んでも,
JIS~X~0208外の文字が出力できるわけではない.
また,\upTeX で
\begin{verbatim}
\kcatcode"D8=16\relax % JIS範囲外の文字(Latin-1 Supplement)を和文扱いに
\font in jis\x=jis \x <文字> % 例えば U+00D8 など
\end{verbatim}
のようにJISエンコードのフォント指定下で範囲外の文字を使うと,
DVI出力中(|\shipout|時)に
\begin{verbatim}
Character <文字> ("D8) cannot be typeset in JIS-encoded JFM jis,
so I use .notdef glyph instead.
\end{verbatim}
という警告\footnote{この警告も\.{tracinglostchars}に従う.
Missing character警告と違ってノードは破棄されないのでlostという
名称は微妙だが….また,JIS範囲外の警告が発生するタイミングは
Missing character警告(ノード生成失敗時に発生)とは異なるので,
|\shipout|時の\.{tracinglostchars}の値に依ることになる.}が発生し,
DVIには豆腐(\verb|set2 0|)が書かれる.
\end{dangerous}
\begin{dangerous}
なお,\TeX82における読込済フォントの判定
(「同じTFMファイル名」かつ「同じサイズ」)は
(u)\pTeX でも変更していないため,
エンコード無指定・\verb|in jis|指定・\verb|in ucs|指定だけを変えて
複数回読み込もうとしても,新しいフォント識別子(font identifier)は
発行されないし,最初のエンコードが常に使われる.
\begin{verbatim}
%#!ptex
\font\xA=min10
\font in jis\xB=min10 % => min10 は無指定時のエンコードのまま
\font in ucs\xC=min10 % => min10 は無指定時のエンコードのまま
\end{verbatim}
\begin{verbatim}
%#!ptex
\font in ucs\yA=umin10
\font\yB=umin10 % => umin10 は Unicode のまま
\font in jis\yC=umin10 % => umin10 は Unicode のまま
\end{verbatim}
\end{dangerous}
\begin{dangerous}
欧文フォントに対する<in spec>は意味を持たないので,単に無視される.
また\.{font}, \.{jfont}, \.{tfont}の直後が|in|でないか
<encoding>が|jis|, |ucs|以外の場合は
\begin{verbatim}
! Missing control sequence inserted.
\end{verbatim}
というエラーが発生する(\TeX82と同じ挙動).
\upTeX~u2.00では,
欧文文字をUnicode 1文字に対し1トークンとして扱う機能が追加された(\ref{sec:uptex_ofm}節)が,
それに伴い<in spec>の書式も拡張された.
指定可能な<encoding>は|t1|, |ts1|, |ly1|, |t5|, |l7x|, |t2a|, |t2b|, |t2c|, |lgr|である.
レガシーエンコーディングの欧文TFMに対してこの指定をすると,
内部コードがUnicodeである欧文文字トークンとレガシーエンコーディングのTFMの情報との相互変換が機能する.
\end{dangerous}
\begin{cslist}
\csitem[\.{ifjfont} <\,font>, \.{iftfont} <\,font>]
\.{ifjfont}は<font>が和文の横組用フォントかどうか,
\.{iftfont}は和文の縦組用フォントかどうかを判定する.
2020-02-05のコミット(r53681)で追加され,
\TeX~Live 2020の\pTeX~(p3.8.3)で利用可能である.
これにより,例えば\.{HOGE}が和文フォントか否かは
\begin{verbatim}
\ifjfont\HOGE
(和文の横組用フォント)
\else\iftfont\HOGE
(和文の縦組用フォント)
\else
(欧文フォント)
\fi
\end{verbatim}
として判定できる.
\end{cslist}
\begin{dangerous}
上述の通り,欧文フォント・和文の横組用フォント・
和文の縦組用フォントのいずれも\.{font}一つで定義可能だが,
定義したフォントが実際にどの種類だったかを知る手段は
バージョンp3.8.2までの\pTeX には存在しなかった.
%
https://github.com/texjporg/tex-jp-build/pull/97
\end{dangerous}
\begin{dangerous}
ちなみに,\epTeX, \eupTeX には\.{iffontchar}プリミティブが存在する.
しかし,<\,font>が和文フォントか否かを判定するために
\code{\.{iffontchar}~<\,font>~256}などと第二引数に256以上の値を指定することはできない.
なぜなら,欧文フォントに対し第二引数に0--255以外の値を指定すると
``\verb|! Bad character code (...).|''エラーが発生するからである.
\end{dangerous}
\begin{cslist}
\csitem[\.{jfam}=<number>]
現在の和文数式フォントファミリの番号を格納する
\footnote{\pTeX,~\upTeX では0--15の範囲が許される.
\epTeX, \eupTeX では欧文の\.{fam}と共に0--255に範囲が拡張されている.}.
現在の欧文数式ファミリの番号を格納する\.{fam}と原理的に同じ番号を指定することは
原理的には可能だが,数式ファミリは和文・欧文共用であるので実際には
異なる値を指定することになる.
欧文フォントが設定されている数式ファミリの番号を\.{jfam}に指定し,
数式中で和文文字を記述すると
\begin{verbatim}
! Not two-byte family.
\end{verbatim}
というエラーが発生する.逆に,和文フォントが設定されているファミリの番号を
|\fam|に指定し,数式中に欧文文字を記述すると
\begin{verbatim}
! Not one-byte family.
\end{verbatim}
というエラーが発生する.
\csitem[\.{ptextracingfonts} (integer)]
|\tracingoutput=1|のときに意味を持つパラメータで,
これは元来|\shipout|時にログに出るものであるから,
「|\shipout|時点での値」によって以下の情報を表示する.
\pTeX~4.1.0で導入された.
\begin{itemize}
\item 値を1以上に設定すると,\pdfTeX の|\pdftracingfonts|と同じ書式で
フォント名とサイズを表示する(font expansionには非対応).
% LuaTeX にも \tracingfonts はあるが LaTeX の \tracingfonts と衝突
% XeTeX の \XeTeXtracingfonts は読込フォントの所在ディレクトリを返す別物
\item 値を2以上に設定すると,追加で(u)\pTeX 特有の以下の情報を表示する.
\begin{itemize}
\item 和文フォント(JFM)の横組(|/YOKO|)・縦組(|/TATE|)の区別
\item 明示的なエンコード指定(\verb|in jis| → |+JIS| / \verb|in ucs| → |+Unicode|)
\end{itemize}
\end{itemize}
書式は以下のようになる.
\begin{itemize}
\item 欧文フォントの場合
\footnote{サイズがTFMデザインサイズと同じ場合は|@サイズ|が省略される.}
$\rightarrow$ |ファイル名@サイズ|
\item 和文フォントの場合
\footnote{サイズについては欧文フォントと同様.
和文フォントでは|/YOKO|又は|/TATE|のいずれか一方が\emph{常に}表示される.
またエンコード無指定の場合は|+エンコード|が省略される.}
$\rightarrow$ |ファイル名@サイズ/組方向+エンコード|
\end{itemize}
\csitem[\.{ptexfontname}]
\pTeX~4.1.0で導入された.
欧文フォントに対しては\.{fontname}と類似だが,
フォントサイズの表示が|... at ...pt|ではなく|
[email protected]|の書式となる.
また,和文フォントに対しては追加情報として以下も表示する.
\begin{itemize}
\item 和文フォント(JFM)の場合は横組・縦組の情報を表示
\item 明示的に\verb|in jis|/\verb|in ucs|が指定された場合に限ってエンコードを表示
\end{itemize}
書式は\.{ptextracingfonts}と同じであるが,その値は\.{ptexfontname}の出力に影響しない.
ここでは例を示そう.
\begin{itemize}
\item \verb|\font\x=cmr10 at 7pt| → {\font\x=cmr10 at 7pt \code{\ptexfontname\x}}
\item \verb|\font\x=nmin10| → {\font\x=nmin10 \code{\ptexfontname\x}}
\item \verb|\font\x=min10 at 8pt| → {\font\x=min10 at 8pt \code{\ptexfontname\x}}
\item \verb|\font in jis \x=ngoth10 at 6pt| → {\font in jis \x=ngoth10 at 6pt \code{\ptexfontname\x}}
\item \verb|\font in ucs \x=utgoth10| → {\font in ucs \x=utgoth10 \code{\ptexfontname\x}}
\end{itemize}
これにより
「そのフォントがJISコードとUnicodeのどちらでDVI出力されるか」
を知ることができるし,
TFMファイル名には現れることがない|/|が含まれるかどうかで
「和文フォントかどうか」
を判定することもできる.
\end{cslist}
\section{\pTeX 系列の組版処理}
和文文字を単に出力できるだけでは,日本語の組版としてまともにならない.
\pTeX 系列は,禁則を考慮した行分割処理,
和文文字と欧文文字のスペーシングといった日本語特有の組版機能を有している.
% jtex.tex の「ラインブレーク」を簡略化
\subsection{禁則}
\label{sec:kinsoku}
欧文と和文の処理で見かけ上最も大きな違いは,行分割処理であろう.
\begin{itemize}
\item 欧文中での行分割は,ハイフネーション処理等の
特別な場合を除いて,単語中すなわち連続する文字列中は
ブレークポイントとして選択されない.
\item 和文中では禁則(行頭禁則と行末禁則)の例外を除いて,
全ての文字間がブレークポイントになり得る.
\end{itemize}
しかし,\pTeX の行分割は\TeX 内部の処理からさほど大きな変更を
加えられてはいない.というのも,\TeX の\emph{ペナルティ}\footnote{%
ペナルティとは,行分割時やページ分割時に
「その箇所がブレークポイントとしてどの程度適切であるか」を示す
一般的な評価値である(適切であれば負値,不適切であれば正値
とする).絶対値が10000以上のペナルティは無限大として扱われる.}%
という概念を和文の禁則処理にも適用しているためである.
行頭禁則と行末禁則を実現する方法として,\pTeX では「禁則テーブル」が
用意されている.このテーブルには
\begin{itemize}
\item 禁則文字
\item その文字に対応するペナルティ値
\item ペナルティの挿入位置
(その文字の前に挿入するか後に挿入するかの別)
\end{itemize}
を登録でき,\pTeX は文章を読み込むたびにその文字が
テーブルに登録されているかどうかを調べ,登録されていれば
そのペナルティを文字の前後適切な位置に挿入する.
禁則テーブルに情報を登録する手段として,
以下のプリミティブが追加されている.
\begin{cslist}
\csitem[\.{prebreakpenalty} <character code>=<number>]
指定した文字の前方にペナルティを挿入する.
正の値を与えると行頭禁則の指定にあたる.
例えば|\prebreakpenalty`。=10000|とすれば,句点の
直前に10000のペナルティが付けられ,行頭禁則文字の対象となる.
\csitem[\.{postbreakpenalty} <character code>=<number>]
指定した文字の後方にペナルティを挿入する.
正の値を与えると行末禁則の指定にあたる.
例えば|\postbreakpenalty`(=10000|とすれば,始め丸括弧の
直後に10000のペナルティが付けられ,行末禁則文字の対象となる.
\end{cslist}
\.{prebreakpenalty}, \.{postbreakpenalty}は
和文文字,欧文文字の区別無しに指定できる.
ただし,欧文文字に設定されたこれらのペナルティが実際に挿入されるのは
以下の場合に限られる(つまり,欧文組版だけの範囲では挿入されない).
\begin{itemize}
\item 当該の欧文文字の直後が和文文字(前方に禁則ペナルティを伴っても構わない)の
場合に限り,その欧文文字に設定された\.{postbreakpenalty}を挿入する.
\item 当該の欧文文字の直前が和文文字(後方に禁則ペナルティを伴っても構わない)の
場合に限り,その欧文文字に設定された\.{prebreakpenalty}を挿入する.
\end{itemize}
\iffalse %%%%% [TODO]
\begin{dangerous}
上記の「欧文文字に設定された禁則ペナルティが挿入される状況」は
欧文文字と和文文字の境界であり,
ベースライン補正(\ref{sec:baselineshift}節を参照)を実現する
\node{disp_node}の挿入箇所でもある.
ベースライン補正がゼロでないとき,\node{penalty_node}と\node{disp_node}の
挿入順序は以下のようにしている. % tex-jp-build@2c83eb0
\begin{itemize}
\item 欧文→和文文字間: \node{disp_node} → \node{penalty_node} (\.{postbreakpenalty}) の順
\item 和文→欧文文字間: \node{penalty_node} (\.{prebreakpenalty}) → \node{disp_node} の順
\end{itemize}
\end{dangerous}
\fi %%%%%
\begin{dangerous}
禁則ペナルティはリスト構築中に自動的に挿入されるので,\.{showlists}で
\begin{verbatim}
\penalty 10000(for kinsoku)
\end{verbatim}
のように表示される.
また,和文文字の後方に挿入された\.{postbreakpenalty}は
\.{lastpenalty}で取得できるし,\.{unpenalty}で取り除くこともできる
\footnote{以前の\pTeX では,\.{unpenalty}したはずの
和文文字の後方の\.{postbreakpenalty}が復活してしまう場合があったが,
2017-04-06のコミット(r43707)で修正された\cite{tjb11}.}.
% ただ,JFMグルーが後方に挿入される和文文字では上手くいかない.
%
https://github.com/texjporg/tex-jp-build/issues/67
しかし,上述の通り,欧文文字に設定された\.{postbreakpenalty}は
後に和文文字が連続して初めて挿入されるため,
\.{lastpenalty}で取得できないし,\.{unpenalty}で取り除くこともできない.
\.{prebreakpenalty}は和文・欧文によらず,その直後に文字ノードを伴うため,
原理的に\.{lastpenalty}で取得できないし,\.{unpenalty}で取り除くこともできない.
\end{dangerous}
同一の文字に対して\.{prebreakpenalty}と\.{postbreakpenalty}の両方を
同時に与えるような指定はできない
(もし両方指定された場合,後から指定されたものに置き換えられる).
禁則テーブルには1,024文字分の領域しかないので,
禁則ペナルティを指定できる文字数は最大で1,024文字までである
\footnote{最大1,024文字となったのは\TeX~Live 2025 (r73803)以降.
なお,\TeX~Live 2022までは256文字までの領域しかなく,
\TeX~Live 2023 (r65246--65248)で1,024文字に拡張しようとしたが
不完全で動作していなかったので,\TeX~Live 2025 (r73803)で再修正した.}.
禁則テーブルからの登録の削除は以下の時に行われる\cite{tjb26,tjb57}:
\begin{itemize}
\item ペナルティ値0をグローバルに(つまり,|\global|を用いて)
設定した場合.
\item ペナルティ値0をローカルに設定した場合でも,その設定が
最も外側のグループ(\eTeX 拡張でいう|\currentgrouplevel|が0)の場合
\footnote{禁則テーブルのある場所がローカルで0に設定されても,その場所に
別の禁則ペナルティ設定がグローバルで行われることのないように,
最外グループ以外での0設定ではテーブルから削除されない.}.
\end{itemize}
\begin{cslist}
\csitem[\.{jcharwidowpenalty}=<number>]
パラグラフの最終行が「す。」のように孤立するのを防ぐための
ペナルティを設定する.
% このペナルティは,
% 「段落が和文文字の1つ以上の連続%
% \footnote{%
% 正確には,和文文字を1つ以上含むような
% 「和文文字,ペナルティ,グルー,カーン,文中数式の境界,\node{mark_node},
% \node{adjust_node}, \node{whatsit_node}, \node{disp_node}」の1つ以上の連続.
% ただし,アクセント本体は無視される.
% }で終わる場合,
% その中の最後にある\.{kcatcode}が16(漢字)または17(仮名)の文字%
% \footnote{%
% \pTeX の初期値では,1,~2,~7--8区\emph{以外}に含まれる文字.
% }の直前」に挿入される.
% % 警告:現行の pTeX では,この仕様に沿っていません(欧文が絡んだ場合).
% % 仕様を明確に決めるとしたらこんな感じになるしょうか.
% %
% また,その位置がすでにペナルティであった場合は,\.{jcharwidowpenalty}の値が合算される.
\end{cslist}
\subsection{文字間のスペース}
欧文では単語毎にスペースが挿入され,その量を調整することにより行長が調整される.
一方,和文ではそのような調整ができる箇所がほぼ存在しない代わりに,
ほとんどの場合は行長を全角幅の整数倍に取ることで,
(和文文字だけの行では)綺麗に行末が揃うようにして組まれる.
ただし,禁則処理が生じたり,途中に欧文が挿入されたりした場合はやはり調整が必要となる.
そこで一般に行われるのが,追い込み,欧文間や和欧文間のスペース量の調整,追い出しなどの
処理である.これらを自動で行うため,\pTeX には下記の機能が備わっている.
\begin{enumerate}
\item 連続する和文文字間に自動的にグルー(伸縮する空白)を挿入\label{kanjiskip}
\item 和欧文間に(ソース中に空白文字を含めずとも)自動的にグルーを挿入\label{xkanjiskip}
\item 和文の約物類にグルーもしくはカーンを設定\label{jfmglue}
\end{enumerate}
上記のうち,\ref{kanjiskip}と\ref{xkanjiskip}についてはそれぞれ
\.{kanjiskip}, \.{xkanjiskip}というパラメータを設けている.
\ref{jfmglue}については,\TeX が使うフォントメトリック (TFM) を拡張した
\pTeX 専用の形式,JFMフォーマットによって実現している.
[TODO] JFMグルーの挿入規則について
\begin{itemize}
\item メトリック由来空白の挿入処理は展開不能トークンが来たら中断
(欧文TFMのカーニングや合字処理と同様)
\item 展開不能トークンや欧文文字は「文字クラス0」扱い.「\verb|)\relax(+|の例
\item 禁則ペナルティ(\.{prebreakpenalty}や\.{postbreakpenalty})と
が同じ箇所に発行される場合は
「禁則ペナルティ→JFM由来空白」の順に発行される.
\iffalse %%%%% [TODO]
\item より一般に,禁則ペナルティ,JFM由来空白,ベースライン補正,
欧文TFM由来カーンが同じ箇所に発行される場合は
次の順になる(\ref{sec:kinsoku}節の注意の一般化).% tex-jp-build/f6f500d or 9e7e21aa
\begin{itemize}
\item 和文→欧文:禁則ペナルティ→JFM由来空白→ベースライン補正→%
欧文TFM由来カーン
\item 欧文→和文:ベースライン補正→禁則ペナルティ→JFM由来空白
\footnote{[TODO] \TeX~Live~2019の\pTeX~3.8.2では,欧文TFM由来カーンは欧文→和文の
切替時には挿入されない.}% tex-jp-build/78c8605 で解決
\end{itemize}
\fi %%%%%
\item もし水平ボックス(|\hbox|)や|\noindent|で開始された段落がJFM由来グルーで始まった
場合は,そのグルーは取り除かれる(カーンは除かれない).
また水平ボックスがJFM由来グルーで終了した場合は,そのグルーは自然長・伸び量・縮み量の
すべてが0となる.
\end{itemize}
\begin{cslist}
\csitem[\.{kanjiskip}=<skip>]
連続する和文文字間に標準で入るグルーを設定する.段落途中でこの値を変えても影響はなく,
段落終了時の値が段落全体にわたって用いられる.
\end{cslist}
\begin{dangerous}
和文文字を表すノードが連続した場合,その間に\.{kanjiskip}があるものとして行分割や
ボックスの寸法計算が行われる.\.{kanjiskip}の大部分はこのように暗黙のうちに挿入
されるものであるので,|\lastskip|などで取得することはできないし,
|\showlists|や|\showbox|でも表示されない.
その一方で,ノードの形で明示的に挿入される\.{kanjiskip}も存在する.
このようになるのは次の場合である:
\begin{itemize}
\item 水平ボックス(|\hbox|)が和文文字で開始しており,そのボックスの直前が
和文文字であった場合,ボックスの直前に\.{kanjiskip}が挿入される.
\item 水平ボックス(|\hbox|)が和文文字で終了しており,そのボックスの直後が
和文文字であった場合,ボックスの直後に\.{kanjiskip}が挿入される.
\item 連続した和文文字の間にペナルティがあった場合,暗黙の\.{kanjiskip}が
挿入されないので明示的にノードが作られる.
\end{itemize}
なお,水平ボックスであっても|\raise|, |\lower|で上下位置をシフトさせた場合は
上記で述べた\.{kanjiskip}を前後に挿入処理の対象にはならない.
\end{dangerous}
\begin{dangerous}
しばしば
\medskip
\begin{minipage}{.6\linewidth}
\begin{verbatim}
\hbox to 15zw{%
\kanjiskip=0pt plus 1fil
あ「い」うえ,お}
\end{verbatim}
\end{minipage}\hfill
\begin{minipage}{.3\linewidth}
\hbox to 15zw{%
\kanjiskip=0pt plus 1fil
あ「い」うえ,お}
\end{minipage}
\noindent
のように\.{kanjiskip}に無限の伸長度を持たせることで均等割付を行おうとする
コードを見かけるが,連続する和文文字の間にはメトリック由来の空白と
\.{kanjiskip}は同時には入らないので,上に書いたコードは不適切である
\footnote{実際,開き括弧の前・閉じ括弧(全角コンマを含む)の後には
JFMグルーが入っているので半角しかない.
}.
\end{dangerous}
\begin{cslist}
\csitem[\.{xkanjiskip}=<skip>]
和文文字と欧文文字の間に標準で入るグルーを設定する.
段落途中でこの値を変えても影響はなく,
段落終了時の値が段落全体にわたって用いられる.
\end{cslist}
\begin{dangerous}
\.{kanjiskip}と異なり,\.{xkanjiskip}はノードの形で挿入される.
この挿入処理は段落の行分割処理の直前や,|\hbox|を閉じるときに行われるので,
「どこに\.{xkanjiskip}が入っているか」を知るためには現在の段落や|\hbox|を
終了させる必要がある.
\end{dangerous}
\begin{cslist}
\csitem[\.{xspcode} <8-bit number>=<0--3>]
コード番号が<8-bit number>の欧文文字の周囲に\.{xkanjiskip}が
挿入可能が否かを0--3の値で指定する.それぞれの意味は次の通り:
\begin{description}
\item[0] 欧文文字の前側,後側ともに\.{xkanjiskip}の挿入を禁止する.
\item[1] 欧文文字の前側にのみ\.{xkanjiskip}の挿入を許可する.後側は禁止.
\item[2] 欧文文字の後側にのみ\.{xkanjiskip}の挿入を許可する.前側は禁止.
\item[3] 欧文文字の前側,後側ともに\.{xkanjiskip}の挿入を許可する.
\end{description}
\pTeX の標準値は,数字0--9と英文字A--Z, a--zに対する値は3(両側許可),
その他の文字に対しては0(両側禁止).
\csitem[\.{inhibitxspcode} <kanji code>=<0--3>]
コード番号が<kanji code>の和文文字の周囲に\.{xkanjiskip}が
挿入可能が否かを0--3の値で指定する.それぞれの意味は次の通り:
\begin{description}
\item[0] 和文文字の前側,後側ともに\.{xkanjiskip}の挿入を禁止する.
\item[1] 和文文字の後側にのみ\.{xkanjiskip}の挿入を許可する.前側は禁止.
\item[2] 和文文字の前側にのみ\.{xkanjiskip}の挿入を許可する.後側は禁止.
\item[3] 和文文字の前側,後側ともに\.{xkanjiskip}の挿入を許可する.
\end{description}
この\.{inhibitxspcode}の設定値の情報は1,024文字分のテーブルに格納されている
\footnote{最大1,024文字となったのは\TeX~Live 2025 (r73803)以降.
なお,\TeX~Live 2022までは256文字分のテーブルしかなく,
\TeX~Live 2023 (r65246--65248)で1,024文字に拡張しようとしたが
不完全で動作していなかったので,\TeX~Live 2025 (r73803)で再修正した.}.
未登録時は3(両側許可)であるとみなされ,またグローバルに3を代入するか,あるいは
最も外側のグループで3を代入するとテーブルからの削除が行われる
(禁則テーブルからの削除と同様の規則).
\end{cslist}
\begin{dangerous}
\.{xspcode}と\.{inhibitxspcode}では,一見すると
設定値1と2の意味が反対のように感じるかもしれない.しかし,実は両者とも
\begin{quote}
1: 「和文文字→欧文文字」の場合のみ許可.「欧文文字→和文文字」の場合は禁止.\\
2: 「欧文文字→和文文字」の場合のみ許可.「和文文字→欧文文字」の場合は禁止.
\end{quote}
となっている.
\end{dangerous}
\begin{cslist}
\csitem[\.{autospacing}, \.{noautospacing}]
連続する和文文字間に,標準で\.{kanjiskip}で指定されただけのグルーを
挿入する(\.{autospacing})か挿入しない(\.{noautospacing})を設定する.
段落途中でこの値を変えても影響はなく,段落終了時の値が段落全体にわたって用いられる.
\csitem[\.{autoxspacing}, \.{noautoxspacing}]
和文文字と欧文文字の間に,標準で\.{xkanjiskip}で指定されただけのグルーを
挿入する(\.{autoxspacing})か挿入しない(\.{noautoxspacing})を設定する.
段落途中でこの値を変えても影響はなく,段落終了時の値が段落全体にわたって用いられる.
\end{cslist}
どちらの設定も標準では有効(\.{autospacing}, \.{autoxspacing})である.
\begin{dangerous}
すでに述べたように,\.{kanjiskip}の一部と\.{xkanjiskip}はノードの形で挿入される.
\.{noautospacing}や\.{noautoxspacing}を指定しても,このノードの形での挿入自体は行われる
(ただノードが\.{kanjiskip}や\.{xkanjiskip}の代わりに長さ0のグルーを表すだけ).
これにより,例えば\.{noautoxspacing}状況下で「|あa|」と
入力しても,間に長さ0のグルーがあるため「あ」と「a」の間で改行可能となることに注意.
\end{dangerous}
\begin{cslist}
\csitem[\.{showmode}]
\.{kanjiskip}の挿入や\.{xkanjiskip}の挿入が有効になっているか否かを
\begin{verbatim}
> auto spacing mode;
> no auto xspacing mode.
\end{verbatim}
という形式(上の例では\.{autospacing}かつ\.{noautoxspacing}の状況)で端末やログに表示する.
\csitem[\.{inhibitglue}]
この命令が実行された位置において,メトリック由来の空白の挿入を禁止する.以下の点に注意.
\begin{itemize}
\item メトリック由来の空白が挿入されないだけであり,
その代わりに\.{kanjiskip}や\.{xkanjiskip}が挿入されることは禁止していない.
\item 本命令は現在のモードが(非限定,限定問わず)水平モードのときしか効力を発揮しない
(数式モードでも効かない).
段落が和文文字「\verb|【|」で始まり,その文字の直前にメトリック由来の空白が入ることを抑止
したい場合は,次のように一旦段落を開始してから\.{inhibitglue}を実行する必要がある.
\begin{verbatim}
\leavevmode\inhibitglue 【
\end{verbatim}
\end{itemize}
以前の\pTeX では「この命令が実行された位置」が何を指すのか大雑把でわかりにくかったが,
\TeX~Live 2019の\pTeX~3.8.2以降では,明確に\emph{新たなノードが追加されない限り},と
定めた\cite{tjb28,forum_2566}.すなわち,
\begin{enumerate}
\item \.{inhibitglue}は,ノード挿入処理を行う命令
(|\null|,~|\hskip|, |\kern|, |\vrule|,~\dots)が後ろに来た場合は無効化される.
\item 一方,|\relax|やレジスタへの代入などのノードを作らない処理では無効化されない.
\item \.{inhibitglue}の効果は別レベルのリストには波及しない.
\end{enumerate}
\end{cslist}
\begin{dangerous}
以上の説明の具体例を以下に示す:
\medskip\noindent
\begin{minipage}[t]{.8\linewidth}
\begin{verbatim}
)\vrule(\\
)\vrule\inhibitglue(\\
)\inhibitglue\vrule(\\
)\inhibitglue\relax(\\
)\relax\inhibitglue(\\ % 「)」「\relax」間で二分空きが入る
あ\setbox0=\hbox{\inhibitglue}(
\end{verbatim}
\end{minipage}\hfill
\begin{minipage}[t]{.1\linewidth}
)\vrule(\\
)\vrule\inhibitglue(\\
)\inhibitglue\vrule(\\
)\inhibitglue\relax(\\
)\relax\inhibitglue(\\
あ\setbox0=\hbox{\inhibitglue}(
\end{minipage}
\end{dangerous}
\begin{dangerous}
p\LaTeX~2017-10-28以降では,\.{inhibitglue}の短縮として|\<|が次のように
定義されている(|\protected|は\eTeX 拡張の機能だが,現在では\LaTeX 自体が
\eTeX 拡張を要求している).
\begin{verbatim}
\protected\def\<{\ifvmode\leavevmode\fi\inhibitglue}
\end{verbatim}
\end{dangerous}
\begin{cslist}
\csitem[\.{disinhibitglue}]
\.{inhibitglue}の効果を無効化(つまり,メトリック由来の空白の挿入を許可)する.
\pTeX~3.8.2で新しく追加された.
\end{cslist}
\subsection{組方向}
% ptexdoc.tex の「ディレクション」を簡略化
従来の\TeX では,字送り方向が水平右向き(→),行送り方向が垂直下向き(↓)
に固定されていた.\pTeX では,\TeX の状態として“組方向(ディレクション)”
を考え,ディレクションによって字送り方向と行送り方向を変えることにしてある.
なお,行は水平ボックス(horizontal box),ページは垂直ボックス(vertical box)である
という点は,\pTeX でも従来の\TeX と同様である.
\pTeX のサポートする組方向は\emph{横組},\emph{縦組},そして
\emph{DtoU方向}\footnote{下から上(Down to Up)であろう.}の3つである.
また数式モード中で作られたボックスは数式ディレクションというまた別の状態になる.
横組での数式ディレクション(横数式ディレクション)と
DtoU方向での数式ディレクションはそれぞれ非数式の場合と区別はないが,
縦組での数式ディレクション(\emph{縦数式ディレクション})では横組を時計回りに
90度回転させたような状態となる.
従って,\pTeX では縦数式ディレクションまで含めると合計4種類の組方向がサポートされていると
いえる(\autoref{tab-dir}).
\begin{table}[tbp]
\caption{\pTeX のサポートする組方向}
\label{tab-dir}
\centering\small
\def\mathmode{}
\def\obox#1{%
\setbox0=\hbox{\yoko\hbox{#1%
\large\tbaselineshift0pt%
\vrule height 25pt width 0.4pt depth 15pt\kern-.2pt%
\raise25pt\hbox to 0pt{\hss\composite{*r^@{>>}}\hss}%
\raise-15pt\hbox to 0pt{\hss\composite{*l^@{>|}}\hss}\kern.2pt%
\vrule height.2pt depth.2pt width 60pt\hbox to 0pt{\hss\composite{*d^@{>}}\hss}\kern-60pt
\mathmode\hbox to 60pt{\,銀は、Ag\hss}\mathmode}}%
\raise\dimexpr 0.5\dp0-0.5\ht0\box0%
}
\begin{tabular}{>{\bfseries}lcccc}
\toprule
&横組&縦組&DtoU方向&縦数式ディレクション\\
\midrule
命令&|\yoko|&|\tate|&|\dtou|&---\\
字送り方向&水平右向き(→)&垂直下向き(↓)&垂直上向き(↑)&垂直下向き(↓)\\
行送り方向&垂直下向き(↓)&水平左向き(←)&水平右向き(→)&水平左向き(←)\\
\parbox[t]{6zw}{使用する和文フォント}&横組用(\.{jfont})&縦組用(\.{tfont})&
\multicolumn{2}{c}{%
横組用(\texttt{\string\jfont})の$90^\circ$回転}\\[\smallskipamount]
組版例 &\obox{\yoko}&\obox{\tate}&\obox{\dtou}&\def\mathmode{$}\obox{\tate}\\
\noalign{\medskip}
\bottomrule
\end{tabular}
\end{table}
以下が,組方向の変更や現在の組方向判定に関わるプリミティブの一覧である.
\begin{cslist}
\csitem[\.{tate}, \.{yoko}, \.{dtou}]
組方向をそれぞれ縦組,横組,DtoU方向に変更する.
カレントの和文フォントは縦組では縦組用フォント,
横組およびDtoU方向では横組用フォントになる.
組方向の変更は,原則として作成中のリストやボックスに何のノードも作られていない
状態でのみ許される.より詳細には,
\begin{itemize}
\item 制限水平モード(|\hbox|),内部垂直モード(|\vbox|)では,
上記に述べた原則通り.
\begin{verbatim}
\hbox{\hsize=20em\tate ……}
\end{verbatim}
のように,ノードが作られない代入文などは組方向変更前に実行しても良い.
違反すると次のようなエラーが出る.
\begin{verbatim}
! Use `\tate' at top of list.
\end{verbatim}
\item 非制限水平モード(行分割される段落)や,
数式モード(文中数式,ディスプレイ数式問わず)
での実行は禁止.
\item 外部垂直モードの場合は,次の2点が同時に満たされる場合のみ実行可能である
\footnote{%
\TeX は,外部垂直モードでボックスその他のノードを追加する際に,まず
そのノードをrecent contributionsというリストの末尾に追加し,
その後recent contributionsの中身が徐々にcurrent pageという別のリストに移される
という処理を行っている.
そのため,単純にcurrent pageまたはrecent contributionsという1つのリストを
調べるだけでは「ページが空」か正しく判断できない.
}.
\begin{itemize}
\item current pageの中身にはボックス,罫線(|\hrule|),
insertion~(|\insert|)はない.
言い換えれば,current pageの中身はあっても
マーク(|\mark|)かwhatsitのみ
\footnote{current pageの中身にグルー,カーン,ペナルティがあるのは,
それらの前にボックス,罫線,insertionが存在する場合にのみである.}.
\item recent contributionsの中身にもボックス,罫線,
insertionはない.
\end{itemize}
違反すると次のようなエラーが出る.
\begin{verbatim}
! Use `\tate' at top of the page.
\end{verbatim}
\end{itemize}
また,ボックスの中身を|\unhbox|, |\unvbox|等で取り出す
場合は,同じ組方向のボックス内でなければならない
\footnote{数式ディレクションか否かは異なっていても良い.}.
違反した場合,
\begin{verbatim}
! Incompatible direction list can't be unboxed.
\end{verbatim}
なるエラーが出る.
\end{cslist}
\begin{dangerous}
|\discretionary|命令では
|\discretionary|\code{\{<pre>\}\{<post>\}\{<nobreak>\}}と3つの引数を
指定するが,この3引数の中で組方向を変更することはできない(常に周囲の組方向が使われる).
\end{dangerous}
\begin{cslist}
\csitem[\.{iftdir}, \.{ifydir}, \.{ifddir}, \.{ifmdir}]
現在の組方向を判定する.\.{iftdir}, \.{ifydir}, \.{ifddir}はそれぞれ
縦組,横組,DtoU方向であるかどうかを判定する(数式ディレクションであるかは問わない).
一方,\.{ifmdir}は数式ディレクションであるかどうかを判定する.
従って,\autoref{tab-dir}に示した4つの状況のどれに属するかは以下のようにして判定できることになる.
\begin{verbatim}
\iftdir
\ifmdir
(縦数式ディレクション)
\else
(通常の縦組)
\fi
\else\ifydir
(横組)
\else
(DtoU方向)
\fi
\end{verbatim}
\csitem[\.{iftbox} <number>, \.{ifybox} <number>, \.{ifdbox} <number>, \.{ifmbox} <number>]
<number>番のボックスの組方向を判定する.<number>は有効なboxレジスタでなければならない.
バージョンp3.7までの\pTeX では,ボックスが一旦ノードとして組まれてしまうと,
通常の縦組で組まれているのか,それとも縦数式ディレクションで組まれているのか
という情報が失われていた.しかし,それでは後述の「ベースライン補正の戻し量」を
誤り,欧文の垂直位置が揃わないという問題が生じた\cite{tatemath}.
この問題を解決する副産物として,バージョンp3.7.1で\.{ifmbox}プリミティブが実装された.
\end{cslist}
\subsection{ベースライン補正}
\label{sec:baselineshift}
和文文字のベースラインと欧文文字のベースラインが一致した状態で組むと,
行がずれて見えてしまう場合がある.特に縦組の状況が典型的である
(\autoref{tab-dir}の「組版例」参照).
この状況を解決するため,\pTeX では欧文文字のベースラインを行送り方向に移動させる
ことができる:
\begin{cslist}
\csitem[\.{tbaselineshift}=<dimen>, \.{ybaselineshift}=<dimen>]
指定した箇所以降の欧文文字のベースラインシフト量を格納する.両者の使い分けは
\begin{description}
\item[\.{tbaselineshift}]
縦組用和文フォントが使われるとき(つまり組方向が縦組のとき),
\item[\.{ybaselineshift}]
横組用和文フォントが使われるとき(横組,DtoU方向,縦数式ディレクション)
\end{description}
となっている.
どちらの命令においても,
正の値を指定すると行送り方向(横組ならば下,縦組ならば左)にずらすことになる.
\end{cslist}
\begin{dangerous}
\node{disp_node}%%% [TODO]
\end{dangerous}
欧文文字だけでなく,文中数式(|$...$|)もベースライン補正の対象である.
文中数式は全体に\.{tbaselineshift}(もしくは\.{ybaselineshift})だけの
ベースライン補正がかかるが,それだけでは
\begin{quote}
数式中のボックスの欧文は(文中数式全体にかかる分も合わせて)
二重にベースライン補正がされる
\end{quote}
という問題が起きてしまう.この問題を解決するための命令が以下の3つの命令であり,
\pTeX~3.7\footnote{\TeX~Live 2016,厳密には2016-03-05のコミット(r39938).}で追加された.
\begin{cslist}
\csitem[\.{textbaselineshiftfactor}=<number>,
\.{scriptbaselineshiftfactor}=<number>]\vspace{-\itemsep}
\csitem[\.{scriptscriptbaselineshiftfactor}=<number>]
文中数式全体にかかるベースライン補正量に対し,
文中数式内の明示的なボックスを逆方向に移動させる割合を指定する.
1000が1倍(ベースライン補正をちょうど打ち消す)に相当する.
プリミティブが3つあるのは,数式のスタイルが
|\textstyle|以上(|\displaystyle|含む),|\scriptstyle|,
|\scriptscriptstyle|のときにそれぞれ
適用される値を変えられるようにするためである.
既定値はそれぞれ1000(1倍),700(0.7倍),500(0.5倍)である.
\end{cslist}
\TeX~Live 2015以前の動作に戻すには,上記の3プリミティブに全て0を指定すれば良い.
\begin{dangerous}
\.{scriptbaselineshiftfactor}を設定するときには,|\scriptstyle|下で追加するボックス内の
ベースライン補正量をどうするかを常に気にしないといけない.
例えば次のコードを考える:
\begin{verbatim}
\ybaselineshift=10pt\scriptbaselineshiftfactor=700
漢字pqr$a\hbox{xあ}^{%
b\hbox{\scriptsize yう}
\hbox{\scriptsize\ybaselineshift=7pt zえ}
}$か%$
\end{verbatim}
組版結果は以下のようになる:
\begin{quote}
\ybaselineshift=10pt\scriptbaselineshiftfactor=700
漢字pqr$a\hbox{xあ}^{%
b\hbox{\scriptsize yう}
\hbox{\scriptsize\ybaselineshift=7pt zえ}
}$か%$
\end{quote}
この例で,ボックス|\hbox{\scriptsize yう}|内ではベースライン補正量は10\,ptのままである
\footnote{|\scriptsize|などのフォントサイズ変更命令では,標準では|\ybaselineshift|の値は
変更しない(|\tbaselineshift|の値はその都度変更する).}.
それが添字内に配置された場合,このボックスは
\[
(\text{文中数式全体のシフト量})
\times\frac{\text{\texttt{\string\scriptbaselineshiftfactor}}}{1000}
= 7\,\mathrm{pt}
\]
だけ上に移動するので,結果として「y」は添字内に直書きした「$b$」と上下位置が
$10\,\mathrm{pt}-7\,\mathrm{pt}=3\,\mathrm{pt}$だけ上に配置されてしまっている.
なお,\.{scriptscriptbaselineshiftfactor}についても全く同様の注意が当てはまる.
\end{dangerous}
\section{その他の補助機能}
\subsection{文字コード変換,漢数字}
\label{sec:convert}
先述(\ref{sec:getcode}節)の通り,
和文文字の文字コードを数値で指定するには内部コードで表現する必要があるが,
それはEUC-JP/Shift-JIS/Unicodeと様々である.
異なるエンコード間でも同じ文字を数値で直接表現できるように,
文字コード変換を行うプリミティブが用意されている.
また,漢数字を出力するプリミティブも用意されている\footnote{%
実は\.{kansuji}, \.{kansujichar}プリミティブはp3.1.1でいったん削除され,
p3.1.2で復活したという経緯がある.}.
これらのプリミティブも\code{ptexenc}を使用しているので,
Unicodeとレガシーエンコードの間の変換では表\ref{table:jis_uni_var}に従う.
% jtexdoc.tex の「追加されたプリミティブ」を簡略化
\begin{cslist}
\csitem[\.{kuten} <16-bit number>]
区点コードから内部コードへの変換を行う.
16進4桁の上2桁が区,下2桁が点であると解釈する.
たとえば,|\char\kuten"253C|は,「\char\kuten"253C」(37区60点)である.
\csitem[\.{jis} <16-bit number>, \.{euc} <16-bit number>, \.{sjis} <16-bit number>]
それぞれJISコード,EUCコード,Shift-JISコードから内部コードへの変換を行う.
たとえば,|\char\jis"346E|,|\char\euc"B0A5|,|\char\sjis"8A79|は,
それぞれ「\char\jis"346E」,「\char\euc"B0A5」,「\char\sjis"8A79」である.
\csitem[\.{ucs} <number>]
Unicodeから内部コードへの変換を行う.
もともと\upTeX で実装されていたが,\pTeX~3.10.0で取り入れた.
\csitem[\.{toucs} <number>]
内部コードからUnicodeへの変換を行う.\pTeX~3.10.0で追加した.
\csitem[\.{tojis} <number>]
内部コードからJISコードへの変換を行う.\pTeX~4.1.0で追加した.
\end{cslist}
文字コードとして不正な値を与えても
``\verb|! Bad character code (...).|''エラーは発生しない(下記参照).
なお,JISコード,EUCコード,Shift-JISコードについて扱えるのは
JIS~X~0208の範囲に限られる(\ref{sec:ptexchar}節でも述べた通り.
すなわちJIS~X~0213には非対応).
\begin{dangerous}
\pTeX~3.9.1以前では,不正な文字コードを与えたときの挙動が
不統一で,特に以下の値を返すケースもあった:
\begin{itemize}
\item 区点コード表のJIS~X~0208における最初の未定義位置
(JIS 0x222F, EUC 0xA2AF, SJIS 0x81AD)…
和文文字コードとして有効で,JIS~X~0213では定義されている.
% 発生状況:従来のUCS2toJIS(0)
\item 区点コード表の1区0点
(JIS 0x2120, EUC 0xA1A0, SJIS 0x813F)…
文字コードとして無効.
% 発生状況: JIStoSJIS(不正)
\item $-1$…文字コードとして無効.
% 発生状況:KUTENtoJIS(不正)→JIStoEUC(-1)
\end{itemize}
\pTeX~3.10.0以降では,% \.{ucs}と\.{toucs}を追加したと同時に,
不正な文字コードを容易に判別できるように以下の仕様にした:
% これは\pTeX~4.1.0で追加した\.{tojis}も同様である.
\begin{itemize}
\item 文字コード変換が\emph{不要}なケース\footnote{内部eucにおける\.{euc},
内部sjisにおける\.{sjis},および\upTeX で内部uptexにおける\.{ucs}と
\.{toucs}がこれに該当する.}…恒等変換となる.
不正な文字コードを与えてもそのまま通る.(これは従来どおりの挙動)
\item 文字コード変換が\emph{必要}なケース…
不正な文字コードを与えると$-1$を返す.(返り値を統一)
\end{itemize}
%%%
%
% pTeX-3.10.0 での実装メモ (2021-06-29 @aminophen)
%
https://github.com/texjporg/tex-jp-build/pull/121
%
% * ptexenc (ptexenc.c, kanjicnv.c, unicode.c) の関数
% => 文字コード変換が不要な場合は恒等変換.
% 必要な場合で不正な文字コードなら 0 を返す.
% * ptex-base.ch の実装
% => ptexenc に従う.ただし \jis, \sjis, \euc, \kuten, \ucs, \toucs の
% 返り値が 0 の場合は -1 を表示.
% * uptex-m.ch の実装
% => ptexenc および ptex-base.ch に従う.ただし,内部コード uptex の時の
% \ucs0 と \toucs0 は(ptex-base.ch が無条件に -1 を表示しようとするが,
% ここは恒等変換とすべきなので)0 を表示.
%
%%%
\end{dangerous}
\begin{cslist}
\csitem[\.{kansuji} <number>, \.{kansujichar} <0--9>=<kanji code>]
\.{kansuji}は,続く数値<number>を漢数字の文字列で出力する.
出力される文字は\.{kansujichar}で指定できる(デフォルトは「〇一二三四五六七八九」).
たとえば
\begin{verbatim}
\kansuji 1978年
\end{verbatim}
は「\kansuji 1978年」と出力され,
\begin{verbatim}
\kansujichar1=`壱
\kansujichar2=\euc"C6F5\relax
\kansujichar3=\jis"3B32\relax
\kansuji 1234
\end{verbatim}
は「{\kansujichar1=`壱 \kansujichar2=\euc"C6F5\relax
\kansujichar3=\jis"3B32\relax \kansuji 1234}」と出力される.
なお,\.{kansuji}に続く数値<number>が負の場合は,空文字列になる
(ちょうど\.{romannumeral}にゼロまたは負の値を与えた場合と同様).
\end{cslist}
\begin{dangerous}
\.{kansujichar}で指定できるのは「和文文字の内部コードとして有効な値」であり,
例えば\pTeX で|\kansujichar1=`A|のように無効な値(\pTeX において|`A|は
欧文文字コードであり,和文文字コードではない)を指定すると
\begin{verbatim}
! Invalid KANSUJI char ("41).
\end{verbatim}
というエラーが発生する\footnote{内部Unicodeの\upTeX では0--127も含め,
Unicodeの文字コードすべてが和文文字コードとして有効であり
(\.{kchar}で任意の文字コードを和文文字ノードに変換して出力できる),
基本的にこのエラーは発生しない.}.
また,\.{kansujichar}の引数に許される値は0--9に限られ,
例えば|\kansujichar10=`拾|とすると
\begin{verbatim}
! Invalid KANSUJI number (10).
\end{verbatim}
というエラーが発生する.
% エラーからのリカバリで,他の\TeX82プリミティブが
% I changed this one to zero.
% とするのに対し,\kansujichar では
% I'm skipping this control sequences.
% とスキップされ,値の代入は行われない.
\end{dangerous}
\begin{dangerous}
\.{kansujichar}は整数値パラメータであるが,p3.8.2までは
「代入できるが取得はできない」という挙動であった
(例えば|\count255=\kansujichar1|はエラー).
\pTeX~3.8.3で取得もできるように修正された\cite{tjb93}が,
以前の\pTeX も考慮すると,値の取得は以下のようにするのが安全である:
|\count255=\expandafter`\kansuji1|
% \count123=\kansujichar45 のように \kansujichar の引数が不正な場合は,
% ! Invalid KANSUJI number (45).
% のエラーを出し,リカバリは \kansujichar を無視した \count123=45 と同義になる.
% これは \kansujichar の代入時の挙動に合わせたものである.
\end{dangerous}
\begin{dangerous}
以上のプリミティブ(\.{kansujichar}を除くすべて)は
展開可能(expandable)であり,
内部整数を引数にとるが,実行結果は\emph{文字列}であることに注意
(\TeX82の\.{number}, \.{romannumeral}と同様).
以下の例は内部コード
\ifnum\jis"2121="3000 Unicode\else
\ifnum\jis"2121="A1A1 EUC-JP\else
\ifnum\jis"2121="8140 Shift-JIS\else\ptErr{Check here}\fi\fi\fi の場合.
\medskip\noindent
\begin{minipage}{.6\linewidth}
\begin{verbatim}
\newcount\hoge
\hoge="2423
\the\hoge, \kansuji\hoge\\
\jis\hoge, \char\jis\hoge\\
\kansuji1701
\end{verbatim}
\end{minipage}
\begin{minipage}{.3\linewidth}
\newcount\hoge
\hoge="2423
\the\hoge, \kansuji\hoge\\
\jis\hoge, \char\jis\hoge\\
\kansuji1701
\end{minipage}\medskip
\begin{itemize}
\item \.{kuten}, \.{jis}, \.{euc}, \.{sjis}, \.{ucs}, \.{toucs}, \.{tojis}
→ 変換結果をカテゴリーコード12の欧文文字トークン列で返す.
\item \.{kansuji}
→ 変換結果を和文文字トークン列で返す\footnote{例外的に,
内部Unicodeの\upTeX で0--127の文字コードを\.{kansujichar}で指定した
場合のみ,\.{kansuji}で生成されるトークンはカテゴリーコード12の
欧文文字トークンになる\cite{tjb36}.
% 文字コードが0--127の和文文字トークンは存在しない,という一貫性.
% \.{kchar}が和文文字トークンを経ずに直接和文文字ノードになるのとは異なる.
また,\upTeX では生成する和文文字トークンに
その時点での和文カテゴリーコードが与えられるが,
もし\.{kcatcode}が15ならば18扱いになる(\.{forcecjktoken}と同様).}.
\end{itemize}
\medskip
以上の挙動から,\.{kansuji}を
「整数値をその符号値をもつ和文文字トークンに変換する」という目的に
用いることもでき,
これは時に“\.{kansuji}トリック”と呼ばれる.例えば
\begin{verbatim}
\kansujichar1=\jis"2422 \edef\X{\kansuji1}
\end{verbatim}
としておけば,|\expandafter\meaning\X|は「\texttt{%
\kansujichar1=\jis"2422 \edef\X{\kansuji1}%
\expandafter\meaning\X}」であるし,
\begin{verbatim}
\begingroup \kansujichar5=\jis"467C\relax \kansujichar6=\jis"4B5C\relax
\expandafter\gdef\csname\kansuji56\endcsname{test}
\endgroup
\end{verbatim}
とすれば,|\日本|という和文の制御綴をASCII文字だけで定義できる.
\end{dangerous}
\subsection{長さ単位}
\pTeX では\TeX82に加えて以下の単位が使用可能である:
\begin{cslist}
\csitem[\texttt{zw}\index{zw=\texttt{zw}}]
現在の和文フォント(通常の縦組のときは縦組用フォント,それ以外のときは横組用フォント)
における「全角幅」.例えばこの文書の本文では
$1\,\mathrm{zw} = \makeatletter\strip@pt\dimexpr 1zw\,\mathrm{pt}$である.
\csitem[\texttt{zh}\index{zh=\texttt{zh}}]
現在の和文フォント(通常の縦組のときは縦組用フォント,それ以外のときは横組用フォント)
における「全角高さ」.例えばこの文書の本文では
$1\,\mathrm{zh} = \makeatletter\strip@pt\dimexpr 1zh\,\mathrm{pt}$である.
\end{cslist}
\begin{dangerous}
より正確に言えば,\texttt{zw}, \texttt{zh}はそれぞれ
標準の文字クラス(文字クラス0)に属する和文文字の幅,高さと深さの和を表す.
{\makeatletter\jfont\test=min10\test\xdef\mzw{\strip@pt\dimexpr1zw}\xdef\mzh{\strip@pt\dimexpr1zh}}%
ただ,\pTeX の標準和文フォントメトリックの一つである\texttt{min10.tfm}では,
$1\,\mathrm{zw}=\mzw\,\mathrm{pt}$, $1\,\mathrm{zh}=\mzh\,\mathrm{pt}$と
なっており,両者の値は一致していない.
JISフォントメトリックでも同様の寸法となっている.
一方,実際の表示に使われる和文フォントの多くは,$1\,\mathrm{zw}=1\,\mathrm{zh}$,
すなわち正方形のボディに収まるようにデザインされているから,これと合致しない.
したがって,単位\texttt{zh}はあまり意味のある値とはいえない.
なお,\Pkg{japanese-otf}(OTFパッケージ)が用いているフォントメトリックは
$1\,\mathrm{zw}=1\,\mathrm{zh}$である.
\end{dangerous}
\begin{cslist}
\csitem[\texttt{Q}\index{Q=\texttt{Q}}, \texttt{H}\index{H=\texttt{H}}]
両者とも$0.25\,\mathrm{mm}$~($7227/10160\,\mathrm{sp}$)を意味する.
写植機における文字の大きさの単位であるQ数(級数)と,字送り量や行送り量の単位である歯数に由来する.
\end{cslist}
\subsection{バージョン番号}
コミュニティ版の\pTeX 系列独自で,\TeX~Live 2018以降に
バージョン番号を返す機能を(\eTeXpre)(u)\pTeX に追加した.
\begin{cslist}
\csitem[\.{ptexversion}, \.{ptexminorversion}, \.{ptexrevision}]
\pTeX のバージョン番号はp$x{.}y{.}z$の形式となっており,それらを取得するための命令である.
\.{ptexversion}, \.{ptexminorversion}は
それぞれ$x$,~$y$の値を内部整数で返し,\.{ptexrevision}はその後ろの「${.}z$」を文字列で返す.
従って,全部合わせた\pTeX のバージョン番号は
\begin{verbatim}
\number\ptexversion.\number\ptexminorversion\ptexrevision
\end{verbatim}
で取得できる.\pTeX~3.8.0で導入された.
\end{cslist}
この追加と同時に,(\eTeXpre)\upTeX では以下が追加されている.
\begin{cslist}
\csitem[\.{uptexversion}, \.{uptexrevision}(\emph{\upTeX のみ})]
\upTeX のバージョン番号はu$x{.}y$の形式となっており,
それらを取得するための命令である.
\.{uptexversion}は$x$の値を内部整数で返し,
\.{uptexrevision}はその後ろの「${.}y$」を文字列で返す.
\end{cslist}
さらに\eTeXpre(u)\pTeX には\.{epTeXversion}プリミティブがある
(\texttt{./eptexdoc.pdf}を参照).
\medskip
この文書は\eTeXpre\ifx\kchardef\undefined\else u\fi\pTeX で処理しているので,
バージョン番号全体を表示すると
\begin{quote}
\texttt{This is
\ifx\eTeXversion\undefined\else e-\fi
\ifx\enablecjktoken\undefined\else u\fi
pTeX p\the\ptexversion.\the\ptexminorversion\ptexrevision
\ifx\enablecjktoken\undefined\else -u\the\uptexversion\uptexrevision\fi
\ifx\epTeXversion\undefined\else -\the\epTeXversion
-\the\eTeXversion\eTeXrevision\fi}
\end{quote}
となる.最後の「-\the\eTeXversion\eTeXrevision」は\eTeX のバージョン番号である.
\newpage
%%%%%
\part{オリジナルの\TeX 互換プリミティブの動作}
オリジナルの\TeX に存在したプリミティブの2バイト以上のコードへの
対応状況を説明する.
% 海外の LaTeX パッケージ作者にとってはこちらの情報が大事なはず.
\section{和文に未対応のプリミティブ}
以下のプリミティブでは,文字コードに指定可能な値は0--255の範囲に限られている:
\begin{quote}
|\catcode|,
|\sfcode|,
|\mathcode|,
|\delcode|,
|\lccode|,
|\uccode|
\end{quote}
違反すると
\begin{verbatim}
! Bad character code (...).
\end{verbatim}
というエラーが発生する(|...|はその文字コード).
\begin{dangerous}
以前の\pTeX では,
これらの命令の文字コード部分に和文文字の内部コードを指定することもでき,
その場合は「引数の上位バイトの値に対する操作」として扱われていた:
\begin{verbatim}
\catcode"E0=1 \message{\the\catcode"E0E1}% ==> 1
\end{verbatim}
しかしこの挙動は2016-09-06のコミット(r41998)により禁止され,
\TeX~Live 2017の\pTeX~(p3.7.1)で反映されている.
\end{dangerous}
また,下記のプリミティブは名称が|\...char|であるが,値は0--255の範囲のみ
有効であり,256以上あるいは負の値を指定すると無効である
(オリジナルの\TeX 同様,エラーにはならない).
\begin{quote}
|\endlinechar|,
|\newlinechar|,
|\escapechar|,\\
|\defaulthyphenchar|,
|\defaultskewchar|
\end{quote}
% 他にもあるか?
\section{和文に対応したプリミティブ}
\begin{cslist}
\csitem[\.{char} <character code>,
\.{chardef} <control sequence>=<character code>]
先に\ref{sec:outchar}節でも述べた通り,
引数として0--255に加えて和文文字の内部コードも指定できる.
和文文字の内部コードを指定した場合は和文文字を出力する.
\csitem[\.{font}, \.{fontname}, \.{fontdimen}]
\.{tfont}については\ref{sec:jfont}節を参照.
|\fontname|は和文フォントからもフォント名を取得でき,
|\fontdimen|は和文フォントのパラメータ表(JFMで定義される\node{param}テーブル)からも
値を取得できる.
% [TODO] pTeX が内部処理で param テーブルを使うことはある?
% 少なくとも,zw と zh は使われていないんですよね?
\csitem[\.{accent} <character code>=<character>]
|\accent|プリミティブにおいても,アクセントの部分に和文文字の内部コードを指定できるほか,
アクセントのつく親文字を和文文字にすることもできる.
\begin{itemize}
\item 和文文字をアクセントにした場合,その上下位置が期待されない結果になる
可能性が大きい.
これは,アクセントの上下位置補正で用いる|\fontdimen5|の値が和文フォントでは
特に意味を持たない\footnote{欧文フォントではx-heightである.}ためである.
\item 和文文字にアクセントをつけた場合,
\begin{itemize}
\item 前側にはJFMグルーや\.{kanjiskip}は挿入されない
(ただし\.{xkanjiskip}は挿入されうる).
\item 後側にはJFMグルーは挿入されない
(ただし\.{kanjiskip}, \.{xkanjiskip}は挿入されうる).
\end{itemize}
\end{itemize}
\csitem[\.{if} <token$_1$> <token$_2$>, \.{ifcat} <token$_1$> <token$_2$>]
文字トークンを指定する場合,その文字コードはオリジナルの\TeX では0--255のみが許されるが,
\pTeX では和文文字トークンも指定することができる.
\.{if}による判定では,欧文文字トークン・和文文字トークンともに
その文字コードが比較される.
\.{ifcat}による判定では,欧文文字トークンについては\.{catcode},
和文文字トークンについては\.{kcatcode}が比較される.
% [TODO] TeX Live 2018 の upTeX では,
% ^^ab 形式での文字コード指定は欧文扱いされるので,
% \ifcat 判定では \catcode が読み出される.
% 例えば \showthe\kcatcode`^^b0 では 18 が返るが,
% 和文扱いはされないことに注意.
%
https://github.com/texjporg/tex-jp-build/issues/68
\end{cslist}
\begin{dangerous}
\TeX bookには,オリジナルの\TeX における\.{if}と\.{ifcat}の説明として
\begin{quote}
If either token is a control sequence,
\TeX\ considers it to have character code 256 and category code 16,
unless the current equivalent of that control sequence
has been |\let| equal to a non-active character token.
\end{quote}
とある.すなわち
\begin{quote}
\.{if}や\.{ifcat}の判定では(実装の便宜上)
コントロールシークエンスは文字コード256,
カテゴリーコード16を持つとみなされる
\end{quote}
というのである.ところが,tex.webの実装はこの通りでなく,
コントロールシークエンスをカテゴリーコード0とみなしている.
そのため,\pTeX 系列において和文文字トークンの\.{kcatcode}の値が
16である場合も,\.{ifcat}判定でコントロールシークエンスと混同されることはない.
一方,文字コードについては,確かにtex.webは\.{if}判定において
コントロールシークエンスを256とみなしている.しかし,\upTeX では
文字コード256の和文文字と衝突するので,2019-05-06のコミット(r51021)で
「原理的に文字コードが取り得ない値」に変更した\cite{tjb68}.
\end{dangerous}
\newpage
%%%%%
\part{\pTeX の出力するDVIフォーマット}
\pTeX が出力するDVIファイルは,欧文の横組のみを行っていれば
オリジナルの\TeX が出力するDVIファイルと全く同様に解釈できる.
一方,\pTeX で和文文字を出力する場合,および組方向変更を行う場合は
以下のDVI命令が使用される.
|set2|,|set3|は\cite{dvistd0}で定義されているが,
オリジナルの\TeX では使われていない.
|dir|は\cite{dvistd0}で定義されておらず,\pTeX の独自拡張である.
\begin{itemize}
\item |set2| (129)\quad $\mathit{c}[2]$\\
コード番号が$c$ ($\mathtt{0x100} \le c < \mathtt{0x10000}$)の
文字を印字し,参照点を移動する.
\pTeX ではJISコード,\upTeX ではUCS-2が用いられる.
\item |set3| (130)\quad $\mathit{c}[3]$\\
コード番号が$c$ ($\mathtt{0x10000} \le c < \mathtt{0x1000000}$)の
文字を印字し,参照点を移動する.
\upTeX ではUCS-4の下位3バイトが用いられる(\pTeX では現れない).
\upTeX~u1.35以降では,合成文字用拡張文字コードも用いられる(\ref{sec:uptex_ivs}節).
\item |dir| (255)\quad $\mathit{d}[1]$\\
組方向を変更する.$\mathit{d}[1]=0$が横組,
$\mathit{d}[1]=1$が縦組,$\mathit{d}[1]=3$がDtoU組を示す.
\end{itemize}
\pTeX が出力するDVIファイルのプリアンブル部のフォーマットIDは,
オリジナルの\TeX と同じく常に2である.
一方,ポストアンブル部の|post_post|命令に続くフォーマットIDは
\pTeX でも通常2であるが,\pTeX の拡張DVI命令である|dir|が
使用されている場合のみ3にセットされる.
% [TODO] 書き方を工夫したい.
|\special|命令の文字列は内部コードで符号化されたバイト列として書き出される.
\begin{thebibliography}{99}
\bibitem{topic} Victor Eijkhout, \textit{\TeX\ by Topic, A \TeX nician's Reference},
Addison-Wesley, 1992.\\
\url{
https://www.eijkhout.net/texbytopic/texbytopic.html}
\bibitem{jfm} ASCII Corporation \& Japanese \TeX\ Development Community, 「JFMファイルフォーマット」,
\texttt{./jfm.pdf}
\bibitem{tatemath} aminophen, 「縦数式ディレクションとベースライン補正」,
2016/09/05,\\
\url{
https://github.com/texjporg/platex/issues/22}
\bibitem{tjb26} h-kitagawa, 「禁則テーブル,\.{inhibitxspcode}情報テーブルからのエントリ削除」,
2017/09/10,\\
\url{
https://github.com/texjporg/tex-jp-build/pull/26}
\bibitem{tjb57} Man-Ting-Fang, \textit{[upTeX] Unexpected behaviour in kinsoku processing},
2018/04/13,\\
\url{
https://github.com/texjporg/tex-jp-build/issues/57}
\bibitem{tjb11} aminophen, 「pTeX の後禁則ペナルティ」,
2017/04/05,\\
\url{
https://github.com/texjporg/tex-jp-build/issues/11}
\bibitem{tjb28} h-kitagawa, 「[ptex] \.{inhibitglue}の効力」,
2017/09/20,\\
\url{
https://github.com/texjporg/tex-jp-build/issues/28}
\bibitem{tjb36} aminophen, 「欧文文字の\.{kansujichar},\.{inhibitxspcode}」,
2017/11/26,\\
\url{
https://github.com/texjporg/tex-jp-build/issues/36}
\bibitem{tjb93} aminophen, 「[ptex] reading \.{kansujichar}」,
2019/10/14,\\
\url{
https://github.com/texjporg/tex-jp-build/issues/93}
\bibitem{tjb37} aminophen, 「和文のコントロールシンボル」,
2017/11/29,\\
\url{
https://github.com/texjporg/tex-jp-build/issues/37}
\bibitem{tjb46} t-tk, 「[upTeX+dvipdfmx] 異体字セレクタ、Unicode合成文字」,
2018/01/28,\\
\url{
https://github.com/texjporg/tex-jp-build/issues/46}
\bibitem{tjb55} aminophen, 「[(u)pTeX] 内部コードの -kanji-internal オプション」,
2018/04/03,\\
\url{
https://github.com/texjporg/tex-jp-build/issues/55}
\bibitem{forum_2566} aminophen, 「\TeX~Live 2019 での \.{inhibitglue} の挙動変更【予定】」,
2019/02/06,\\
\url{
https://okumuralab.org/tex/mod/forum/discuss.php?d=2566}
\bibitem{tjb68} aminophen, 「upTeX の |\if| と |\ifcat|」,
2019/01/17,\\
\url{
https://github.com/texjporg/tex-jp-build/issues/68}
\bibitem{man4} aminophen, 「pTeX の和文文字トークンのカテゴリーコード」,
2019/04/22,\\
\url{
https://github.com/texjporg/ptex-manual/issues/4}
\bibitem{tjb87} h-kitagawa, 「[ptex] [和字]+[ブレース]で終わっている行の行端の扱い」,
2019/08/05,\\
\url{
https://github.com/texjporg/tex-jp-build/issues/87}
\bibitem{tjb81} h-kitagawa, 「バイト列と和文文字トークンの区別」,
2019/06/08,\\
\url{
https://github.com/texjporg/tex-jp-build/issues/81}
\bibitem{tjb142} t-tk, 「[ptexenc] 入力ファイルの文字コードの自動判定」,
2022/06/05,\\
\url{
https://github.com/texjporg/tex-jp-build/issues/142}
\bibitem{tjb149} aminophen, 「[upTeX] JIS-encoded TFM」,
2022/10/15,\\
\url{
https://github.com/texjporg/tex-jp-build/issues/149}
\bibitem{dvistd0} TUG DVI Standards Working Group,
\textit{The DVI Driver Standard, Level 0}.\\
\url{
https://ctan.org/pkg/dvistd}
\bibitem{tjb167} h-kitagawa, 「[XeTeX] BMP超のコントロールシンボル」,
2024/02/25,\\
\url{
https://github.com/texjporg/tex-jp-build/issues/167}
\bibitem{tjb170} t-tk, 「[upTeX] ofm読み込みと符号位置 256 以上の欧文文字トークン・ノード」,
2024/08/18,\\
\url{
https://github.com/texjporg/tex-jp-build/issues/170}
\bibitem{ivd220913} Ideographic Variation Database,
2022/09/13,\\
\url{
https://www.unicode.org/ivd/data/2022-09-13/}
\bibitem{emseq160} Emoji Sequence Data,
2024/05/01,\\
\url{
https://www.unicode.org/Public/emoji/16.0/emoji-sequences.txt}
\end{thebibliography}
\newpage
\printindex
\end{document}