CTeX-org / forum

A temporarily alternate forum of `bbs.ctex.org`
https://t.me/chinesetex
Apache License 2.0
210 stars 16 forks source link

我想将某些内容固定排版在偶数页的页面底部,但使用\ifodd\value{page}进行判断时在某些情形下会失效 #288

Open djunhao opened 1 year ago

djunhao commented 1 year ago

检查

编译环境

我的问题:

我希望将一些内容排版在偶数页的页面底部,使用了_\ifodd\value{page}_来判断当前页是否奇数页。如果是,则创建一个新页面来排版需要置底的内容。但是,实践时发现,有时会碰到排版无法达到预期目的的情况。 经过多次尝试,目前发现以下三种种情况会导致置底内容无法排版在偶数页:

  1. 正文内容刚好排满偶数页;
  2. 当前正文在偶数页,且剩余高度不足于用来排版置底内容;
  3. 奇数页字数很少(文字少于一行。只要有第二行文字,置底内容就能正常排版在新建的偶数页。)

出现以上任意一种情形时,置底内容将会直接在下一页排版(奇数页)。以下代码展示了第三种情形:

示例代码

\documentclass[fontset=windows,linespread=1.5625]{ctexart}
\usepackage[a4paper,twoside,top=35mm,bottom=35mm,left=28mm,right=26mm,showframe]{geometry}
\usepackage{zhlipsum}
\newcommand{\makenotes}
{
\par
\ifodd\value{page}
\clearpage
\thispagestyle{empty}%
\hbox{}
\fi
% \null
% \vfill
\vspace*{\fill}
\noindent
\begin{tabular}{l}
\hline
《史记·十二本纪·项羽本纪》 \\
\hline
\end{tabular}
}
\begin{document}
\zihao{3}\fangsong
\zhlipsum[1-5][name=xiangyu]
\makenotes
\end{document}

请问各位老师、前辈,以上代码是哪里出错了吗?

Sophanatprime commented 1 year ago

LaTeX 在执行到 \ifodd 时,还不知道自己要不要换页,所以 \value{page} 还是没换页时候的值。 应该告诉 LaTeX 还需要多少空间,在 LaTeX 决定要不要换页之后,才能得到想要的 \value{page}

\documentclass[fontset=windows,linespread=1.5625]{ctexart}
\usepackage[a4paper,twoside,top=35mm,bottom=35mm,left=28mm,right=26mm,showframe]{geometry}
\usepackage{zhlipsum}
\usepackage{needspace}

\newsavebox\makenotesbox
\newcommand{\makenotestext}
  {\begin{tabular}[b]{l}
     \hline
    《史记·十二本纪·项羽本纪》 \\
     \hline
   \end{tabular}}
\newcommand{\makenotes}
  {
    \par 
    \sbox{\makenotesbox}{\parbox[b]{\textwidth}{\makenotestext}}
    \needspace{%
      \ifdim\dp\makenotesbox>\maxdepth
        \dimexpr\ht\makenotesbox+\dp\makenotesbox-\maxdepth\relax
      \else \ht\makenotesbox\fi}
    \ifodd\value{page}
      \ifdim\pagegoal=\maxdimen \hbox{}\thispagestyle{empty}\fi
      \clearpage
      \thispagestyle{empty}%
      \hbox{}
    \fi
%   \null
%   \vfill
    \vspace*{\fill}
    \noindent \usebox{\makenotesbox}\newpage
  }

\begin{document}
\zihao{3}\fangsong
\zhlipsum[1-5][name=xiangyu]
\makenotes
\end{document}
muzimuzhi commented 1 year ago

使用 \value{page} 获得的不一定是当前页数,于是对它的奇偶判断也会出错。比如,用在一个跨页的段落里时,不论插入 \value{page} 的位置对应输出后换页前还是换页后的部分,\value{page} 获得的总是换页前的页数。

这里需要「仅在 shipout/输出一页 时展开」,对应的就是 \write(见 TeX by Topic, sec. 12.6.3 Expansion and \write),缺点是需要第二次编译。这就是 ifoddpage 包封装的 \ifoddpage

PS:texlive 2023 开始,\special 获得了一个新的关键词 shipout\special shipout<general text> 可以和 \write 一样,仅在 shipout 时展开 <general text>。详见 https://tug.org/texlive/doc/texlive-en/texlive-en.html#x1-920009.2https://tex.stackexchange.com/q/681452

Sophanatprime commented 1 year ago

在OP这种问题下,如果仅仅使用 \label 这类技术,最坏情况需要编译 n+1 次,而不是固定的两次吧,而且估计编译次数超过2次的概率比平时大。和 needspace 配合使用的话,当然是更好的选择。(除非取消某些页的 shipout,不用写入辅助文件的方式应该也行吧。)

\special 里好像不能放盒子?

djunhao commented 1 year ago

谢谢 @Sophanatprime 前辈提供的解决方案。 谢谢 @muzimuzhi 老师提供的信息,我好好研究一下。主要是本人的水平很菜,有些很简单的问题可能也需要很长时间看文档、搜索示例才能弄明白。汗!