2016年7月30日

e-pTeX(というかe-pLaTeX)用にも割注書いてみた……けどまだ未完.\vsplitでUnderfullが出る.最新(2016/07/29以降)のe-pTeXで動くはず.使い方は次の通り.

  • \warichu:割注を表示する.改行位置などは自動で計算される.複数回のコンパイルが必要.
  • \warichu*:割注を表示する.改行位置は\\で指定する.二行への分割処理は自動でされるが,&がある場合はその場所で分割される.

例えば\warichu{割注のテスト}とか\warichu*{割注のテ\\ スト}とか\warichu*{割注 & のテ\\ スト}とかみたいに使う.

\documentclass{tarticle}
\usepackage{minijs}
\usepackage[savepos]{zref}
\makeatletter
\AtBeginDvi{\pdfpageheight=\paperheight \pdfpagewidth=\paperwidth}
\newcount\jlreq@rest@linewidth@count
\jlreq@rest@linewidth@count=0
% 計算結果を返すための変数
\newdimen\jlreq@resultdimen
\newbox\jlreq@resultbox

\newdimen\jlreq@tempdima
\newdimen\jlreq@tempdimb
\newdimen\jlreq@tempdimc

% この命令以降,次にこの命令を実行する前まで\jlreq@rest@linewidthで
% この場所における残り長さが取得できる.
\newcommand{\jlreq@savepos@for@rest@linewidth}{%
  \advance\jlreq@rest@linewidth@count by 1\relax
  \zsavepos{jlreq@rest@width.pos.\the\jlreq@rest@linewidth@count}%
  \zref@labelbyprops{jlreq@rest@width.page.\the\jlreq@rest@linewidth@count}{page}%
}

% 現在行の残りを得る.zpos(x/y)を元に計算するだけ.
\newcommand{\jlreq@rest@linewidth}{%
  \dimexpr
    \linewidth + \@totalleftmargin + 1in
    \iftdir
      + \topmargin + \headheight + \headsep + \voffset
      + \zposy{jlreq@rest@width.pos.\the\jlreq@rest@linewidth@count} sp
      \ifdim\pdfpagewidth=0pt
        - \paperheight
      \else
        - \pdfpageheight
      \fi
    \else
      + \hoffset - \zposx{jlreq@rest@width.pos.\the\jlreq@rest@linewidth@count} sp
      \ifodd\zref@extractdefault{jlreq@rest@width.page.\the\jlreq@rest@linewidth@count}{page}{\c@page}%
        + \oddsidemargin
      \else
        + \evensidemargin
      \fi
    \fi
  \relax
}

\newcommand{\jlreq@warichu@kakkofontsize}{%
  \fontsize{\numexpr \warichusize * 2\relax pt}{\numexpr \warichusize * 2\relax pt}%
  \selectfont
}

\newcommand{\jlreq@warichu@fontsize}{%
  \fontsize{\warichusize pt}{\warichusize pt}%
  \selectfont
}

\newcommand{\warichusize}{6} % 割注の文字サイズ

% 割注を入れるための命令.\warichu{割注}で使う.
% 改行位置は自動で計算されるが,常に正しいとは限らない.
% \warichu*は自動で改行されない.\\で改行位置を指定する.
\newif\ifjlreq@inwarichu
\jlreq@inwarichufalse
\newcommand{\warichu}{%
  \ifjlreq@inwarichu\ClassError{tjlreq}{\string\warichu\space can't be nested!}\fi
  \jlreq@inwarichutrue
  \@ifstar\jlreq@warichu@noauto\jlreq@warichu@auto}

\newcommand*{\jlreq@warichu@auto}[1]{%
  % 割注初め括弧の前の場所を保存
  \jlreq@savepos@for@rest@linewidth
  % \jlreq@tempdimbに,現在行の残り長さを入れる
  \jlreq@tempdimb=\jlreq@rest@linewidth
  % 括弧の分を引いたものが,割注の使える長さ
  \setbox\@tempboxa=\hbox{\jlreq@warichu@kakkofontsize\inhibitglue(\inhibitglue}%
  \addtolength{\jlreq@tempdimb}{-\wd\@tempboxa}%
  {\jlreq@warichu@kakkofontsize\inhibitglue (}%
  % 普通に並べた長さを計測し,その半分から始める
  \setbox\@tempboxa=\hbox{\jlreq@warichu@fontsize #1}%
  \jlreq@tempdimc=\wd\@tempboxa
  \divide\jlreq@tempdimc by 2\relax
  % \@tempcntbに,この長さで計測した場合の行数を入れる
  \ifdim\jlreq@tempdimc<\jlreq@tempdimb\@tempcntb=2\relax
  \else
    \jlreq@tempdima=\dimexpr\jlreq@tempdimc - \jlreq@tempdimb\relax
    \divide\jlreq@tempdima\linewidth
    \@tempcntb=\number\jlreq@tempdima
    \multiply\@tempcntb by 2\relax
    \advance\@tempcntb by 4\relax
  \fi
  % \jlreq@parshapeargに\parshapeに指定する書式の最後以外を入れる.
  \ifnum\@tempcntb>2\relax
    \edef\jlreq@parshapearg{0pt \the\jlreq@tempdimb\space 0pt \the\jlreq@tempdimb}%
    \@tempcnta=4\relax
    \@whilenum\@tempcnta<\@tempcntb\do{%
      \edef\jlreq@parshapearg{\jlreq@parshapearg\space 0pt \the\linewidth\space 0pt \the\linewidth}%
      \advance\@tempcnta by 2\relax
    }%
    \setlength{\jlreq@tempdimc}{\dimexpr\jlreq@tempdimc - \jlreq@tempdimb - \linewidth * \numexpr(\@tempcntb - 4)/2\relax\relax}%
  \else
    \def\jlreq@parshapearg{}%
  \fi
  % 行数を伸ばしつつ良いところを探していく
  \@whilenum\@tempcntb<1001\do{%
    \ifnum\@tempcntb>2\jlreq@tempdimb=\linewidth\fi
    \edef\@tempb{\the\@tempcntb}%
    \jlreq@warichu@determinelength{#1}{\jlreq@parshapearg}{\@tempb}{\jlreq@tempdimc}{\jlreq@tempdimb}%
    \@tempcntb=\@tempb
    \ifnum\@tempcntb>999\relax% ループが長すぎる
      \global\setbox\jlreq@resultbox=\voidb@x%
      \@tempcntb=1001\relax
    \fi
    \ifvoid\jlreq@resultbox\else% 成功
      \edef\jlreq@warichu@lines{\the\@tempcntb}% 行数を保存
      \@tempcntb=1001\relax
    \fi
    \advance\@tempcntb by 2\relax
    \edef\jlreq@parshapearg{\jlreq@parshapearg 0pt \the\jlreq@tempdimb 0pt \the\jlreq@tempdimb}%
  }%
  \ifvoid\jlreq@resultbox
    \ClassWarning{tjlreq}{\string\warichu\space failed, may be a bug}%
  \else
    \begingroup
    \@tempcnta=0\relax
    \splittopskip=0pt\relax
    \splitmaxdepth=\maxdimen
    % 現在行の残り長さを思い出す
    \jlreq@tempdimb=\jlreq@rest@linewidth
    \setbox\@tempboxa=\hbox{\jlreq@warichu@kakkofontsize\inhibitglue(\inhibitglue}%
    \addtolength{\jlreq@tempdimb}{-\wd\@tempboxa}%
    \setbox\@tempboxa=\box\jlreq@resultbox
    \@whilenum\@tempcnta<\jlreq@warichu@lines\do{%
      \ifnum\@tempcnta>0\relax\\\fi
      % \jlreq@tempdimaに今の行の長さを入れる
      \ifnum\@tempcnta<\numexpr\jlreq@warichu@lines - 2\relax
        \ifnum\@tempcnta=0\jlreq@tempdima=\jlreq@tempdimb
        \else\jlreq@tempdima=\linewidth\fi
      \else
        \jlreq@tempdima=-1pt\relax
      \fi
      {%
        \jlreq@warichu@fontsize
        \setbox\jlreq@tempboxa=\vsplit\@tempboxa to 2\baselineskip
        \jlreq@getlastbox{\jlreq@tempboxa}%
        \setbox\jlreq@tempboxb=\box\jlreq@resultbox
        \jlreq@getlastbox{\jlreq@tempboxa}%
        \setbox\jlreq@tempboxa=\box\jlreq@resultbox
        \ifdim\jlreq@tempdima>0pt\relax
          \raise-.5zw\hbox to \jlreq@tempdima{\vbox{%
            \hbox to \jlreq@tempdima{\unhbox\jlreq@tempboxa}%
            \hbox to \jlreq@tempdima{\unhbox\jlreq@tempboxb}}}%
        \else
          \raise-.5zw\hbox{\vbox{%
            \hbox{\unhbox\jlreq@tempboxa}%
            \hbox{\unhbox\jlreq@tempboxb}}}%
        \fi
      }%
      \advance\@tempcnta by 2\relax
    }%
    \endgroup
  \fi
  \jlreq@warichu@endwarichu
}

\newcommand*{\jlreq@warichu@noauto}[1]{%
  {\jlreq@warichu@kakkofontsize
  \inhibitglue (}%
  \jlreq@warichu@noauto@#1\\\jlreq@endmark\jlreq@endmark
  \jlreq@warichu@endwarichu
}

\def\jlreq@warichu@noauto@#1\\#2#3\jlreq@endmark{%
  \jlreq@warichu@noauto@@#1&\jlreq@endmark\jlreq@endmark
  \ifx#2\jlreq@endmark\def\jlreq@next{}\else\linebreak\def\jlreq@next{\jlreq@warichu@noauto@#2#3\jlreq@endmark}\fi
  \jlreq@next
}

\def\jlreq@warichu@noauto@@#1&#2#3\jlreq@endmark{%
  \ifx#2\jlreq@endmark
    \setbox\@tempboxa=\hbox{\jlreq@warichu@fontsize #1}%
    \jlreq@tempdimc=\wd\@tempboxa
    \divide\jlreq@tempdimc by 2\relax
    \jlreq@warichu@determinelength{#1}{}{2}{\jlreq@tempdimc}{\maxdimen}%
    \ifvoid\jlreq@resultbox\else
      {%
        \jlreq@warichu@fontsize\raise-.5zw\hbox{\box\jlreq@resultbox}%
      }%
    \fi
    \def\jlreq@next{}%
  \else
    \def\jlreq@next{\jlreq@warichu@noauto@@@{#1}#2#3}%
  \fi
  \jlreq@next
}

\def\jlreq@warichu@noauto@@@#1#2&\jlreq@endmark{%
  {\jlreq@warichu@fontsize\raise-.5zw\hbox{\vbox{\hbox{#1}\hbox{#2}}}}%
}

\newcommand{\jlreq@warichu@endwarichu}{%
  \jlreq@inwarichufalse
  {\jlreq@warichu@kakkofontsize\hbox{)}}%
}

\newbox\jlreq@tempboxa
\newbox\jlreq@tempboxb
% \jlreq@warichu@determinelength{テキスト}{\parshape指定}{成功行数}{最小長さ}{最大長さ}
% \jlreq@resultboxに整形結果を返す.見つからなかったらvoid
\newcommand{\jlreq@warichu@determinelength}[5]{%
  \@tempcnta=0\relax
  \jlreq@tempdima=#4\relax
  % 最後の行を少しずつ伸ばしていく
  \@whilenum\@tempcnta<1000\do{%
    \ifnum\@tempcnta>999\relax% ループが長すぎる
      \global\setbox\jlreq@resultbox=\voidb@x%
      \@tempcnta=1001\relax
    \else
      \setbox\@tempboxa=\vbox{%
        \vbadness=10000\hbadness=10000\vfuzz=\maxdimen\hfuzz=\maxdimen
        \jlreq@warichu@fontsize
        \parindent=0pt\leftskip=0pt\rightskip=0pt\relax
        \parshape #3 #2 0pt \the\jlreq@tempdima 0pt \the\maxdimen
        #1\par\global\@tempcntb=\prevgraf}%
    \fi
    \jlreq@getlastbox{\@tempboxa}%
    \setbox\jlreq@tempboxa=\box\jlreq@resultbox
    \ifnum\@tempcntb<#3\relax% 行数が達していないならOK
      \global\setbox\jlreq@resultbox=\vbox{\jlreq@warichu@fontsize
        \unvbox\@tempboxa\hbox{\unhbox\jlreq@tempboxa\unskip\unskip\unpenalty}%
        \@whilenum\@tempcntb<#3\do{\hbox{}\advance\@tempcntb by 1}}%
      \@tempcnta=1001\relax
    \else
      % そうでない場合は最後の二行の長さを比較する
      \jlreq@getlastbox{\@tempboxa}%
      \setbox\jlreq@tempboxb=\box\jlreq@resultbox
      \ifdim\wd\jlreq@tempboxa>\wd\jlreq@tempboxb
        \advance\jlreq@tempdima by 0.3pt\relax
      \else
        % 後ろが短いのでOK
        \global\setbox\jlreq@resultbox=\vbox{\jlreq@warichu@fontsize
          \unvbox\@tempboxa\box\jlreq@tempboxb\box\jlreq@tempboxa}%
        \jlreq@resultdimen=\jlreq@tempdima
        \@tempcnta=1001\relax
      \fi
    \fi
    \ifdim\jlreq@tempdima>#5\relax
      \global\setbox\jlreq@resultbox=\box\voidb@x%
      \@tempcnta=1001\relax
    \fi
    \advance\@tempcnta by 1\relax
  }%
}

% vbox #1の最後を\jlreq@resultboxに入れる
% #1の最後の行は消える
\newcommand{\jlreq@getlastbox}[1]{%
  \setbox#1=\vbox{\jlreq@warichu@fontsize\unvbox#1\relax
    \unskip\unskip\unpenalty\global\setbox\jlreq@resultbox=\lastbox}%
  \ifhbox\jlreq@resultbox
    \global\setbox\jlreq@resultbox=\hbox{%
      \jlreq@warichu@fontsize
      \unhbox\jlreq@resultbox\unskip\unskip\unpenalty}%
  \else
    \global\setbox\jlreq@resultbox=\box\voidb@x
  \fi
}
\makeatother
\begin{document}
これは割注\warichu{割注、ゲットだぜ!}のテストです。
\end{document}

0 件のコメント:

コメントを投稿

コメントの追加にはサードパーティーCookieの許可が必要です