TeX Live 2014 では,\inhibitglue に関する仕様の変更が取り込まれました。
pTeX 系列のエンジン(pTeX/e-pTeX/upTeX/e-upTeX)の全てに影響します。
これは,既存ソースの組版結果が変わる重大な変更ですので,今回の変更に至る過去の経緯,および新仕様の取り扱い上の注意点について述べておこうと思います。
背景 - pTeX のバグ
ASCIIのpTeXの仕様書には,次のように書かれています。
\inhibitglue
和文フォントのメトリック情報から、自動的に挿入されるグルーの挿入を禁止します。 このプリミティブを挿入した箇所にのみ有効です。
このように,\inhibitglue は「挿入した箇所のみに有効」と明記されています。
しかし,(TeX Live 2013 以前では)実際にはそうではなく,「次に初めて和文文字が現れた箇所で有効」という挙動をします。この「\inhibitglue の影響の染み出し」は,非和文文字が続く限り,段落をまたいでどこまでも波及します。
実例1
ソース
\documentclass{jsarticle} \begin{document} \setlength\parindent{0zw} \everypar{} hoge:「ほげ」 hoge\inhibitglue hoge hoge:「ほげ」 \end{document}
実例2
例えば,「日本語組版処理の要件」の行頭の始め括弧類の配置方法の(a)「改行行頭の字下げは全角アキ,折返し行頭は天付き」を実現するために,
\setlength\parindent{1zw} \everypar{\inhibitglue}
としてしまうと,段落冒頭に和文文字がない場合,意図しないところで \inhibitglue が効いてしまいます。
ソース
\documentclass{jsarticle} \begin{document} \setlength\parindent{1zw} \everypar{\inhibitglue} \noindent ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 「ほげ」はサンプルプログラムなどで利用される「メタ構文変数」である。「ほげ」が使われた場合,それが「意味のない名前」であることが明らかとなる。 % ↑「改行行頭の字下げは全角アキ,折返し行頭は天付き」のテスト hoge:「ほげ」 和文hoge:「ほげ」 \end{document}
過去の経緯と対策 (TeX Live 2013 以前)
この \inhibitglue 問題は,これまでも何度も話題になってきました。
- TeX Q&A 53900, 53901, 53902, 53903, 53904, 53905, 53906
- jsclasses の更新記録の [2000-11-17]
- 奥村先生のツイート (2013/03/01)
このバグを回避するために,様々な対策がとられてきました。
jsarticle における \@inhibitglue
先程の「改行行頭の字下げは全角アキ,折返し行頭は天付き」を実現するために,jsarticle.cls では,直接 \everypar{\inhibitglue} とするのではなく,次のような細工がなされています。
\def\@inhibitglue{% \futurelet\@let@token\@@inhibitglue} \def\@@inhibitglue{% \ifx\@let@token「 \inhibitglue \else \ifx\@let@token( \inhibitglue \else \ifx\@let@token『 \inhibitglue \else \ifx\@let@token[ \inhibitglue \fi \fi \fi \fi} \let\everyparhook=\@inhibitglue \AtBeginDocument{\everypar{\everyparhook}}
これは,段落冒頭の文字を \futurelet でチェックして,それが開き括弧類である場合に限って \inhibitglue を挿入しようというものです。
強制改行後の処理の変更
TeX Q&A の 53900 のパターンの問題を解決するために,53909 では,強制改行後の処理を「空白トークンを読み飛ばして \@inhibitglue」とするように変更して対処されています。
\inhibitglue が効いていればリセット
このように,不用意に \inhibitglue を発行すると,思わぬ所で効いてしまい危険でした。
発行する側が注意していればよいのですが,「他人の作ったマクロが \inhibitglue を発行している可能性がある」というような状況下では,「\inhibitglue の影響をリセットさせる」という処理が必要になる場面もあります。
そうしたとき,ややトリッキーですが,次のようにすることで,そこまでに効いている \inhibitglue の影響をリセットさせるというテクニックもありました。
{\setbox0\vbox{あ}}
TeX Live 2014 での修正
TeX Q&A で上記問題が話題になったとき,北川さんが修正パッチを作ってくださいましたが,TeX Live には長らく取り込まれないままでした。
ですが,\inhibitglue 問題が昨年話題になったときにNorbertさんに伝わったためか,TeX Live 2014 では,めでたく北川さんによる\inhibitglue の修正が取り込まれました!
これにより,\inhibitglue が,本来のASCIIの仕様書通りに,「挿入した箇所にのみ有効」となりました。
TeX Live 2013 以前で必要であった上記の様々な工夫は,もはや不要となりました。
例えば \everypar も単に
\everypar{\inhibitglue}
として問題なくなります。(従来の \futurelet を用いたままでも特に問題はありませんが。)
新仕様での注意点
ただし,新仕様での注意点があります。\inhibitglue が垂直モード中で効かないという点です。
実例1
ソース
\everypar が空の状態のとき,手動で \inhibitglue を挿入しようとしたソースです。
\documentclass{jsarticle} \begin{document} \setlength\parindent{0zw} \everypar{} ■■■■■■ 「ほげ」%% \everypar が空なので行頭二分アキになる \inhibitglue 「ほげ」%% 行頭天ツキにしたい \leavevmode\inhibitglue 「ほげ」%% 行頭天ツキにしたい \end{document}
実例2
- \parbox の中では \everypar が空にリセットされる。
- \centering の下での強制改行 \\ では \par が発行されて一度(内部)垂直モードに移行する。
ということの影響により,強制改行や \par の直後に開き括弧類がある場合の挙動に注意が必要です。TeX Live 2013 以前と 2014 以降では組版結果が変わってきます。
ソース
幅4zwの \parbox に中央揃えで文字を配置しようとした例です。
\documentclass{jsarticle} \setlength\fboxsep{0pt} \newcommand{\centerbox}[1]{\fbox{\parbox{4zw}{\centering#1}}} \begin{document} \centerbox{% ほげ\\ 「ほげ」\par 「ほげ」 } \centerbox{% ほげ\\ \inhibitglue 「ほげ」\par \inhibitglue 「ほげ」 } \centerbox{% ほげ\\ \leavevmode\inhibitglue 「ほげ」\par \leavevmode\inhibitglue 「ほげ」 } \end{document}
参考:LuaTeX-ja の場合
LuaTeX-ja の場合,そもそも,段落冒頭の開き括弧類の前の部分には,(デフォルトでは)JFM由来のグルーは挿入されません。したがって,\everypar{\inhibitglue} というような対処も不要となります。
ただし,「垂直モードでの \inhibitglue は効かない」という点は TeX Live 2014 以降のpTeXと同様です。これは,次の例のように \everypar に文字を入れてみると見えてきます。
ソース
\documentclass{ltjsarticle} \usepackage[ipaex]{luatexja-preset} \begin{document} \setlength\parindent{1\zw} \noindent ■■■■■■ \everypar{} 「ほげ」 \inhibitglue 「ほげ」 \leavevmode\inhibitglue 「ほげ」 \noindent 「ほげ」 \noindent\inhibitglue 「ほげ」 \noindent ■■■■■■ \everypar{★} 「ほげ」 \inhibitglue 「ほげ」 \leavevmode\inhibitglue 「ほげ」 \noindent 「ほげ」 \noindent\inhibitglue 「ほげ」 \end{document}