\prebreakpenalty が効く時と効かない時がある

\prebreakpenalty が効く時と効かない時がある

- 村上 TomOne の投稿
返信数: 13
upLaTeX + jlreq にて、行頭禁則文字設定を行いました。
しかし、効く文字と効かない文字があるようです。

ーぁ々はちゃんと効いて行頭に来るのですが、
ぃァなどは効かず、2文字目に来ます。
何か設定がおかしいのでしょうか?

さっきTeX Live 2020から2021に上げ、さらにアップデートも行いました。

===================================================
\RequirePackage{plautopatch}
\documentclass[uplatex,dvipdfmx,tate,book,
paper=a6,
jafontscale=0.962216,
jafontsize=12Q,
baselineskip=19H,
line_length=42zw,
number_of_lines=17,
headfoot_verticalposition=4mm,
open_bracket_pos=nibu_tentsuki,hanging_punctuation]{jlreq}


\usepackage{bxpapersize}


%禁則処理

% 例えば、行頭に "」" のみとなる場合、
% "かな」" と2文字追い出されるのを "な」" とする

\jcharwidowpenalty=0

% 行頭禁則文字設定。
\prebreakpenalty`ー=0

% 行頭禁則文字設定。効いてない?
\prebreakpenalty`ぁ=0
\prebreakpenalty`ぃ=0
\prebreakpenalty`ぅ=0
\prebreakpenalty`ぇ=0
\prebreakpenalty`ぉ=0
\prebreakpenalty`っ=0
\prebreakpenalty`ゃ=0
\prebreakpenalty`ゅ=0
\prebreakpenalty`ょ=0
\prebreakpenalty`ゎ=0%\jis"246E
\prebreakpenalty`ァ=0
\prebreakpenalty`ィ=0
\prebreakpenalty`ゥ=0
\prebreakpenalty`ェ=0
\prebreakpenalty`ォ=0
\prebreakpenalty`ッ=0
\prebreakpenalty`ャ=0
\prebreakpenalty`ュ=0
\prebreakpenalty`ョ=0
\prebreakpenalty`ヮ=0%\jis"256E
\prebreakpenalty`ヵ=0%\jis"2575
\prebreakpenalty`ヶ=0%\jis"2576
\prebreakpenalty`々=0


\begin{document}

\noindent\null
12345678901234567890123456789012345
6789012ーあいうえお

\noindent\null
12345678901234567890123456789012345
6789012ぁあいうえお

\noindent\null
12345678901234567890123456789012345
6789012ぃあいうえお


\noindent\null
12345678901234567890123456789012345
6789012々あいうえお


\end{document}

===================================================
村上 TomOne への返信

Re: \prebreakpenalty が効く時と効かない時がある

- ut の投稿

なさりたいことの趣旨を私が正しく理解できているのかどうか、
いささか怪しいのですけれど、既に行頭禁則に設定されている文字を、
禁則からはずしたい、ということでしょうか?

とりあえず、ペナルティの値を調整してみましたら、以下のようになりました:
(私の手元の jlreq.cls は Document Class: jlreq 2020/05/01 jlreq なので
最新ではないと思いますが)


\documentclass[uplatex,dvipdfmx,tate,book,
paper=a6,
jafontscale=0.962216,
jafontsize=12Q,
baselineskip=19H,
line_length=42zw,
number_of_lines=17,
headfoot_verticalposition=4mm,
open_bracket_pos=nibu_tentsuki,hanging_punctuation]{jlreq}

\usepackage{bxpapersize}

\begin{document}

\noindent\null
12345678901234567890123456789012345
6789012ー」いうえお

\noindent\null
12345678901234567890123456789012345
6789012ぁ」いうえお

\noindent\null
12345678901234567890123456789012345
6789012ぃ」いうえお

\noindent\null
12345678901234567890123456789012345
6789012々」いうえお

\bigskip

\prebreakpenalty`ー=-500
\prebreakpenalty`ぁ=-500
\prebreakpenalty`ぃ=-500
\prebreakpenalty`々=-500

\noindent\null
12345678901234567890123456789012345
6789012ー」いうえお

\noindent\null
12345678901234567890123456789012345
6789012ぁ」いうえお

\noindent\null
12345678901234567890123456789012345
6789012ぃ」いうえお

\noindent\null
12345678901234567890123456789012345
6789012々」いうえお

\end{document}

ut への返信

Re: \prebreakpenalty が効く時と効かない時がある

- 村上 TomOne の投稿
ありがとうございます。
拗促音も行頭に来て欲しかったので、\rebreakpenaltyを0にしました。
これを負数にする発想はなかったので試してみましたが、今度は行頭に来すぎました。

upTeXにバグがあるようで、検証を真似して
\the\prebreakpenalty`ぃ
としたら10000が入っていて、上に来ないはずです。
一旦諦めて、修正を待つことにします。
村上 TomOne への返信

Re: \prebreakpenalty が効く時と効かない時がある

- ut の投稿

> 今度は行頭に来すぎました。

ペナルティ -500 というのは値が大きすぎたのかも知れません。

例えば、(多くの cls ファイル同様)jlreq.cls では:

  \@lowpenalty  51
  \@medpenalty  151
  \@highpenalty 301

となっているので、このあたりの値を利用するのがスマートだったのかも、
と事後的に思い直しました。

> \the\prebreakpenalty`ぃ
> としたら10000が入っていて、

それは、jlreq.cls で行頭禁則に設定されてるからだと思うのですけれど。

# from: jlreq.cls
# \jlreq@setprebreakpenalty{\jlreq@charlist@smallkana}{10000}

いずれにせよ、upTeX に何か修正が入るのかも知れませんね…。


ut への返信

Re: \prebreakpenalty が効く時と効かない時がある

- 村上 TomOne の投稿
jlreq.cls自体で10000としていても、プリアンブルで0と再設定したのならば、
0になるのを期待しました。そしたら、0だったり10000だったり。
-100にしたらちゃんと-100だったようで、行頭に来すぎました。
なので0が丁度良いかなと。

じきにバグは直ると思いますが、今作ってる本を再版する時は組み直しに。

村上 TomOne への返信

Re: \prebreakpenalty が効く時と効かない時がある

- はやて (h20y6m) の投稿

upTeX がなんか変……

% This is upTeX, Version 3.141592653-p3.9.0-u1.27 (utf8.uptex) (TeX Live 2021/W32TeX) (preloaded format=uptex)
\showthe\prebreakpenalty`ぃ % > 150.
\prebreakpenalty`ぃ=0
\showthe\prebreakpenalty`ぃ % > 0.  ← OK
\prebreakpenalty`ぃ=123
\showthe\prebreakpenalty`ぃ % > 123. ← OK
\prebreakpenalty`ぁ=0
\showthe\prebreakpenalty`ぃ % > 123.
\prebreakpenalty`ぃ=0
\showthe\prebreakpenalty`ぃ % > 123. ← あれ?
\prebreakpenalty`ぃ=234
\showthe\prebreakpenalty`ぃ % > 234. ← OK
\prebreakpenalty`ぃ=0
\showthe\prebreakpenalty`ぃ % > 123. ← えっ!?
\prebreakpenalty`ぁ=345
\showthe\prebreakpenalty`ぃ % > 123.
\prebreakpenalty`ぃ=0
\showthe\prebreakpenalty`ぃ % > 0. ← OK
\bye
はやて (h20y6m) への返信

Re: \prebreakpenalty が効く時と効かない時がある

- ut の投稿

私の手元は W32TeX [2020/07/19] なのですが、私の手元でも、uptex で試してみますと、
はやてさんが示されたようになりますね(見やすいように若干編集してます):

This is upTeX, Version 3.14159265-p3.8.3-u1.26 (utf8.uptex) (TeX Live 2020/W32TeX)
(preloaded format=uptex 2020.7.14) 
**test
(./test.tex

\showthe\prebreakpenalty`ぃ
> 150.

\prebreakpenalty`ぃ=0
\showthe\prebreakpenalty`ぃ
> 0.

\prebreakpenalty`ぃ=123
\showthe\prebreakpenalty`ぃ
> 123.

\prebreakpenalty`ぁ=0
\showthe\prebreakpenalty`ぃ
> 123.

\prebreakpenalty`ぃ=0
\showthe\prebreakpenalty`ぃ
> 123.

\prebreakpenalty`ぃ=234
\showthe\prebreakpenalty`ぃ
> 234.

\prebreakpenalty`ぃ=0
\showthe\prebreakpenalty`ぃ
> 123.

\prebreakpenalty`ぁ=345
\showthe\prebreakpenalty`ぃ
> 123.

\prebreakpenalty`ぃ=0
\showthe\prebreakpenalty`ぃ
> 0.


ちなみに、ptex で試すと、正しい結果が得られます:

This is pTeX, Version 3.14159265-p3.8.3 (utf8.sjis) (TeX Live 2020/W32TeX)
(preloaded format=ptex 2020.7.14)
**test2
(./test2.tex

\showthe\prebreakpenalty`ぃ
> 150.

\prebreakpenalty`ぃ=0
\showthe\prebreakpenalty`ぃ
> 0.

\prebreakpenalty`ぃ=123
\showthe\prebreakpenalty`ぃ
> 123.

\prebreakpenalty`ぁ=0
\showthe\prebreakpenalty`ぃ
> 123.

\prebreakpenalty`ぃ=0
\showthe\prebreakpenalty`ぃ
> 0.

\prebreakpenalty`ぃ=234
\showthe\prebreakpenalty`ぃ
> 234.

\prebreakpenalty`ぃ=0
\showthe\prebreakpenalty`ぃ
> 0.

\prebreakpenalty`ぁ=345
\showthe\prebreakpenalty`ぃ
> 0.

\prebreakpenalty`ぃ=0
\showthe\prebreakpenalty`ぃ
> 0.

ut への返信

Re: \prebreakpenalty が効く時と効かない時がある

- aminophen の投稿
euptex -ini -etex で \tracingassigns1 を使って調べてみると,
ptex-base.ch の get_kinsoku_pos 関数がおかしいようです。

pTeX で露見せず upTeX で露見したのはたまたまで,
ハッシュ関数の値が pTeX ではたまたま衝突しないから。

=====
%#!euptex -ini -etex
% This is upTeX, Version 3.141592653-p3.9.0-u1.27 (utf8.uptex)
% (TeX Live 2021/W32TeX) (preloaded format=uptex)
\tracingonline1
\tracingassigns1

% 最優先hashはコードポイントから一意に決まる値(jtex.pdfも参照)
\prebreakpenalty`、=10000 % code=12289, 最優先hash=1
\prebreakpenalty`。=10000 % code=12290, 最優先hash=2
\prebreakpenalty`ぁ=150 % code=12353, 最優先hash=1だが埋まってしまったので3に分配
\prebreakpenalty`ぃ=150 % code=12355, 最優先hash=3だが埋まってしまったので4に分配

\showthe\currentgrouplevel % > 0.
\showthe\prebreakpenalty`ぃ % > 150.

\prebreakpenalty`ぃ=0 % changing hash=4
\showthe\prebreakpenalty`ぃ % > 0. ← OK(hash=4読出)

\prebreakpenalty`ぃ=123 % changing hash=4
\showthe\prebreakpenalty`ぃ % > 123. ← OK(hash=4読出)

\prebreakpenalty`ぁ=0 % changing hash=3
\showthe\prebreakpenalty`ぃ % > 123. ← OK(hash=4読出)

% この時点で "ぁ" が消えてhash=3が空いている。
% 一方,"ぃ"はフォールバックしたhash=4に格納されている。

\prebreakpenalty`ぃ=0 % reassigning hash=3 (!!) ← 本来hash=4を更新すべき
\showthe\prebreakpenalty`ぃ % > 123. ← 正しくは0だが,hash=4読出

\prebreakpenalty`ぃ=234 % changing hash=3
\showthe\prebreakpenalty`ぃ % > 234. ← OK(hash=3読出)

\prebreakpenalty`ぃ=0 % changing hash=3
\showthe\prebreakpenalty`ぃ % > 123. ← 正しくは0だが,hash=4読出

\prebreakpenalty`ぁ=345 % changing hash=3
\showthe\prebreakpenalty`ぃ % > 123. ← 正しくは0だが,hash=4読出

% この時点で "ぁ" が再びhash=3を埋めている。

\prebreakpenalty`ぃ=0 % changing hash=4
\showthe\prebreakpenalty`ぃ % > 0. ← OK(hash=4読出)

\end
=====
村上 TomOne への返信

Re: \prebreakpenalty が効く時と効かない時がある

- aminophen の投稿
少しだけユーザ向けの解説をしておくと,
禁則テーブルに元々「非ゼロ」の値が入っているところを「ゼロ」に更新する処理は特別で,
禁則テーブルからエントリを「削除する」(値をゼロに更新するのではない)という挙動にしています。
これは TeX Live 2018 以降の pTeX 系列でそのような挙動にしたのですが,
(参考 https://github.com/texjporg/tex-jp-build/pull/26 )
したがって,値をゼロにしなければこの問題は起きません。
例えば0でなく1のように極めて小さな値を入れて試してみるのは手です。
aminophen への返信

Re: \prebreakpenalty が効く時と効かない時がある

- 村上 TomOne の投稿
ありがとうございます。
試してみましたが、1だと行頭に来ず、-1だと行頭に来すぎました。
0が正しく扱えるまで待つしかなさそうです。


\prebreakpenalty`ぁ=0
\the\prebreakpenalty`ぁ

\noindent\null
12345678901234567890123456789012345
6789012ぁあいうえお % 行頭に来て欲しい OK

\noindent\null
12345678901234567890123456789012345
678901ぁあいうえお % 行末に来て欲しい OK

\prebreakpenalty`ぁ=1
\the\prebreakpenalty`ぁ

\noindent\null
12345678901234567890123456789012345
6789012ぁあいうえお % 行頭に来て欲しいけど、2字目

\prebreakpenalty`ぁ=-1
\the\prebreakpenalty`ぁ

\noindent\null
12345678901234567890123456789012345
678901ぁあいうえお % 行末に来て欲しいけど、行頭

村上 TomOne への返信

Re: \prebreakpenalty が効く時と効かない時がある

- aminophen の投稿
正攻法は「ptex, uptex, eptex, euptex のソースコードを修正してバイナリを更新する」ですが
通常 TeX Live ではそのようなバイナリ修正は年に一度なのでほぼ一年後…。

% 修正コードの実験として,開発版win32バイナリは
% https://github.com/texjporg/tex-jp-build/issues/113
% に置いてみてはいますが…(ptex-new-2.zip の中)

それをせずに挙動を修正しようとすると…かなり苦しいですが,不可能ではないようです。

要は「禁則テーブルからの削除を行わなければよい」ので,
「元々禁則テーブルに自分の意図するもの以外が無ければよい」ことになります。

[1] フォーマット作成時に読まれる禁則ファイルを texmf-dist から探してとってくる。

* pLaTeX の場合:kinsoku.tex
* upLaTeX の場合:ukinsoku.tex

を kpsewhich で探してきて,カレントディレクトリにコピーする。

[2] 取ってきたファイルを編集して,所望のペナルティを全てそのファイル内で設定する。
→これを「改変版 (u)kinsoku.tex」と呼ぶ。

[3] 改変版 (u)kinsoku.tex がカレントディレクトリにある状態で

* pLaTeX なら "fmtutil-sys --byfmt platex"
* upLaTeX なら "fmtutil-sys --byfmt uplatex"

というコマンドにより,フォーマットを再作成する。

[4] jlreq.cls などのクラスやパッケージが禁則ペナルティを変更するのを禁止するため,
プリアンブル冒頭に

\newcount\dummykinsoku
\let\ORIprebreakpenalty\prebreakpenalty
\let\ORIpostbreakpenalty\postbreakpenalty
\def\prebreakpenalty{\expandafter\dummykinsoku\romannumeral-}
\def\postbreakpenalty{\expandafter\dummykinsoku\romannumeral-}

と書き,プリアンブル末尾(あるいは禁則ペナルティを変更するパッケージの後)に

\let\prebreakpenalty\ORIprebreakpenalty
\let\postbreakpenalty\ORIpostbreakpenalty

で復帰させる。参考:
https://zrbabbler.hatenablog.com/entry/20110331/1301596818

(極めて変態な技ですね…。)

※ 書いてみて思ったけど,やっぱり,特別にバイナリ更新をお願いするのが良いですね…。
aminophen への返信

Re: \prebreakpenalty が効く時と効かない時がある

- 村上 TomOne の投稿
C:\texlive\2021\bin\win32 のコピーとった後、
ptex-new-2.zip の中身を上書きして、

$ mktexlsr
$ fmtutil-sys --all

したら動きました。求める組版になったようです。
対応ありがとうございました。

村上 TomOne への返信

Re: \prebreakpenalty が効く時と効かない時がある

- aminophen の投稿
> 修正コードの実験

先日出した修正案で問題なさそうでしたので r59700 でコミットしました。
r59701 で pTeX version p3.9.1 に上げています。