6

I'm trying to write Latex documents that will automatically satisfy government requirements for labeling certain classes of information:
- Each paragraph starts with a label indicating its importance.
- The header and footer of each page include a label indicating the most important paragraph on that page (even if it started on the previous page).

This is the closest I have come:

\documentclass[12pt]{report}
\usepackage{fancyhdr}
\usepackage{ifthen}
\usepackage{afterpage}
\usepackage{color}
\usepackage{lipsum}

\setlength\parskip{.6\baselineskip}
\setlength\parindent{0pt}
\setlength\headheight{15pt}
\setlength\textheight{21\baselineskip}
\newcommand\pageimport{TRIVIAL}
\newcommand\paraimport{TRIVIAL}

\pagestyle{fancy}
\lhead{}\chead{\leftmark}\rhead{}
\lfoot{}\cfoot{\leftmark}\rfoot{\thepage}

\newcommand{\IMP}[1]{\renewcommand\paraimport{IMPORTANT}
  \renewcommand\pageimport{IMPORTANT}
  \markboth{\pageimport}{\paraimport}
  \afterpage{\renewcommand\pageimport{\protect\paraimport}\markboth{\protect\paraimport}{}}
\textcolor{red}{(I)  #1}\renewcommand\paraimport{TRIVIAL}}

\newcommand{\TRI}[1]{\renewcommand\paraimport{TRIVIAL}
  \markboth{\pageimport}{\paraimport}
  \afterpage{\renewcommand\pageimport{\protect\paraimport}\markboth{\protect\paraimport}{}}
(U)  #1\renewcommand\paraimport{TRIVIAL}}

\begin{document}
\immediate\typeout{a. pageimport = \pageimport\space  paraimport = \paraimport}
\TRI{\lipsum[1]}
\TRI{\lipsum[2]}
\TRI{\lipsum[3]}
\immediate\typeout{b. pageimport = \pageimport\space  paraimport = \paraimport}
\IMP{\lipsum[4]}
\immediate\typeout{c. pageimport = \pageimport\space  paraimport = \paraimport}
\TRI{\lipsum[5]}
\TRI{\lipsum[6]}
\TRI{\lipsum[7]}
\TRI{\lipsum[8]}
\immediate\typeout{d. pageimport = \pageimport\space  paraimport = \paraimport}
\IMP{\lipsum[9]}
\immediate\typeout{e. pageimport = \pageimport\space  paraimport = \paraimport}
\TRI{\lipsum[10]}
\TRI{\lipsum[11]}
\TRI{\lipsum[12]}
\end{document}

(I've changed the labels here to avoid causing needless alarm. For convenience, I have also set the "important" text in red.) My idea is to keep the "importance" of each paragraph in \paraimport. That gets reset at the end of each paragraph. The header and footer get their labels from \pageimport, which records the highest importance on the current page. At the end of each page, \pageimport gets reset to the value of \paraimport.

This document has one "important" paragraph on page 2, and another that starts on page 4 and ends on page 5. All the paragraphs are correctly labeled. The first two pages have the right labels, but pages 3 and 6 should be marked "trivial". The tracing statements before and after each "important" paragraph show that \pageimport is not getting reset at the pagebreaks.

I suspect I'm moving something fragile, but rewriting the \afterpage commands as

\afterpage{\renewcommand\pageimport{\protect\paraimport}\markboth{\protect\paraimport}{}}

makes no difference.

I've seen secret.sty, but it's attacking a different problem. I have not been able to adapt it for page marking.

I'd appreciate any suggestions.

1
  • Welcome to TeX.SX! I think,\afterpage is not sufficient here. In my impression there must be check about the last 'state' (TRIVIAL/IMPORTANT)
    – user31729
    Commented Apr 16, 2016 at 14:25

3 Answers 3

2

Here is a solution.

The key point is to reset left and right marks

\afterpage{%
\renewcommand\paraimport{TRIVIAL}%
\markboth{\paraimport}{\paraimport}

Note We need only one command \paraimport

Update the idea is to redefine \parimport and \markboth inside paragraphs i.e. just after (I).

Updated MWE

\documentclass[12pt]{report}
\usepackage{fancyhdr}
\usepackage{afterpage}
\usepackage{color}
\usepackage{lipsum}

\setlength\parskip{.6\baselineskip}
\setlength\parindent{0pt}
\setlength\headheight{15pt}
\setlength\textheight{21\baselineskip}


\pagestyle{fancy}
\lhead{}\chead{\leftmark}\rhead{}
\lfoot{}\cfoot{\leftmark}\rfoot{\thepage}

\newcommand\paraimport{TRIVIAL}
\markboth{\paraimport}{\paraimport}

\newcommand{\IMP}[1]{%
\textcolor{red}{(I)
\renewcommand\paraimport{IMPORTANT}%
\markboth{\paraimport}{\paraimport}%
 #1}%
\afterpage{%
\renewcommand\paraimport{TRIVIAL}%
\markboth{\paraimport}{\paraimport}}%
}

\newcommand{\TRI}[1]{(U)  #1}

\begin{document}
\TRI{\lipsum[1]}
\TRI{\lipsum[2]}
\TRI{\lipsum[3]}
\IMP{\lipsum[4]}
\TRI{\lipsum[5]}
\TRI{\lipsum[6]}
\TRI{\lipsum[7]}
\TRI{\lipsum[8]}
\IMP{\lipsum[9]}
\TRI{\lipsum[10]}
\TRI{\lipsum[11]}
\TRI{\lipsum[12]}
\end{document}
7
  • Thanks - that does fix the MWE. But I'd really like to know why it works. Commented Apr 17, 2016 at 21:54
  • Unfortunately there is still a flaw. My MWE included cases where the pagebreak occurred within a "trivial" paragraph or within an "important" one. If I shorten the pages by one line using "\setlength\textheight{20\baselineskip}", then a pagebreaks occur just before an "important" paragraph, which triggers a bug: If a page starts with an "important" paragraph, then the previous page is also marked "important". Apparently by the time TeX decides to insert the pagebreak, \paraimport and \leftmark have already been set. Any ideas how to handle that case? Commented Apr 17, 2016 at 22:24
  • I just found another similar topic "Content Aware Headers and Footers" at tex.stackexchange.com/questions/97891/…. Unfortunately the solution by @Eric has the same flaw: If a page starts with a higher classification than anything on the previous page, the previous page gets marked with the higher classification. Commented Apr 17, 2016 at 23:08
  • I update the answer fixing the bug. I will try to explain how later.
    – touhami
    Commented Apr 18, 2016 at 5:56
  • I think I see how your fix works. By waiting until a few characters in the new paragraph have been scanned, we ensure that TeX has made its pagebreak decisions before we reset the headers and footers. Thanks! Commented Apr 18, 2016 at 10:26
1

The question is a bit old, but it still comes up high on a web search. I was trying to adapt the solution for multiple importance levels and came across this answer to check if a paragraph spans a page break. My solution is to set a counter and increment the counter if a paragraph has a higher importance level than the current paragraph. If the last paragraph on the page spans the page break, I set the page level on the next page to the current level and repeat the process. What I came up with is

\documentclass{article}

\usepackage{afterpage}
\usepackage{lipsum}
\usepackage{fancyhdr}
\pagestyle{fancy}
\fancyhf{}

\newcounter{pagelevel}
\newcounter{currentlevel}

\usepackage{atbegshi}
\usepackage{zref-user}
\usepackage{zref-abspage}

\newcounter{clscnt}
\makeatletter
% When we ship out the page, check if the paragraph spans the break.
\AtBeginShipout{%
    \ifnum\zref@extract{markingenv-begin-\theclscnt}{abspage}
            =\zref@extract{markingenv-end-\theclscnt}{abspage}
        \setcounter{pagelevel}{0}%
    \else
        \setcounter{pagelevel}{\thecurrentlevel}%
    \fi
}
\makeatother

\newcommand{\marking}[2]{%
    \stepcounter{clscnt}%
    \zlabel{markingenv-begin-\theclscnt}%
    (#1 --- \thepagelevel)
    \ifnum #1 > \thepagelevel%
        \setcounter{pagelevel}{#1}%
        \chead{Level \thepagelevel}%
    \fi%
    \setcounter{currentlevel}{#1}
    #2
    \zlabel{markingenv-end-\theclscnt}%
}

\newcommand{\VI}[1]{\marking{3}{(V) #1}}
\newcommand{\IMP}[1]{\marking{2}{(I) #1}}
\newcommand{\TRI}[1]{\marking{1}{(U) #1}}

\begin{document}
\TRI{\lipsum[1]\par}
\TRI{\lipsum[2]\par}
\TRI{\lipsum[3]\par}
\IMP{\lipsum[4]\par}
\TRI{\lipsum[5]\par}
\TRI{\lipsum[6]\par}
\TRI{\lipsum[7]\par}
\TRI{\lipsum[8]\par}
\IMP{\lipsum[9]\par}
\TRI{\lipsum[10]\par}
\TRI{\lipsum[11]\par}
\TRI{\lipsum[12]\par}
\TRI{\lipsum[13]\par}
\TRI{\lipsum[14]\par}
\TRI{\lipsum[15]\par}
\VI{\lipsum[16]\par}
\IMP{\lipsum[17]\par}
\TRI{\lipsum[18]\par}
\TRI{\lipsum[19]\par}
\TRI{\lipsum[20]\par}
\TRI{\lipsum[21]\par}
\TRI{\lipsum[22]\par}
\TRI{\lipsum[23]\par}
\TRI{\lipsum[24]\par}
\TRI{\lipsum[25]\par}
\TRI{\lipsum[26]\par}
\TRI{\lipsum[27]\par}
\TRI{\lipsum[28]\par}
\TRI{\lipsum[29]\par}
\end{document}

I modified the example to explicitly show the page level and paragraph level. Note that pages 3 and 4 correctly have the heading set to level 3 and the heading is reset to 1 on pages 5 and 6.


Edit: I've been tinkering with and extending this solution to make it into a package.

1
  • 1
    I've noticed this logic is not perfect. In fact, it will occasionally fail to capture a paragraph that spans pages (and appears fails when a float is involved). Commented Apr 6, 2022 at 2:18
0

It seems as though the most complicated part of this problem is the case when a paragraph continues through a page break. Perhaps the easiest thing to do is to prevent paragraphs from doing so:

\widowpenalties 1 10000
\raggedbottom

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .