Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

How to disable pagebreak on \hline in longtable?

This is an example illustrating my problem:

\documentclass[12pt,a4paper,oneside]{letter}

\usepackage{longtable}

\begin{document}

\begin{longtable}{ | p{5cm} | }
\hline
Table header\\*
\hline
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris pharetra
porttitor turpis, id egestas neque congue in. Nam sed lorem lorem, ac
tristique tellus. Nunc ornare feugiat orci, a blandit turpis facilisis ut.
Aenean pharetra ornare ante. Sed tempus leo in dolor eleifend placerat.
Integer at enim augue. Ut nisl tortor, interdum ac porttitor ac, sagittis
quis libero. Vivamus nibh metus, ornare vel pulvinar nec, fringilla nec
orci. Maecenas mollis nulla a nibh fringilla nec convallis augue varius.
Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere  
cubilia Curae. \\
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris pharetra
porttitor turpis, id egestas neque congue in. Nam sed lorem lorem, ac
tristique tellus. Nunc ornare feugiat orci, a blandit turpis facilisis ut.
Aenean pharetra ornare ante. Sed tempus leo in dolor eleifend placerat. 
Integer at enim augue. Ut nisl tortor, interdum ac porttitor ac, sagittis
quis libero. Vivamus nibh metus, ornare vel pulvinar nec, fringilla nec   
orci. Maecenas mollis nulla a nibh fringilla nec convallis augue varius.  
Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere  
cubilia Curae. \\
\hline
Table header\\*
\hline
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris pharetra
porttitor turpis, id egestas neque congue in. Nam sed lorem lorem, ac   
tristique tellus. Nunc ornare feugiat orci, a blandit turpis facilisis ut.
Aenean pharetra ornare ante. Sed tempus leo in dolor eleifend placerat.   
Integer at enim augue. Ut nisl tortor, interdum ac porttitor ac, sagittis 
quis libero. Vivamus nibh metus, ornare vel pulvinar nec, fringilla nec   
orci. Maecenas mollis nulla a nibh fringilla nec convallis augue varius.  
Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere 
cubilia Curae. \\
\hline
\end{longtable}

\end{document}

I'd like to have second header on page 3. I do not control table contents, so I can not do page breaks manually.

share|improve this question
    
Just as an aside, you should look at the booktabs package for typesetting tables. It works with longtable. –  TH. Dec 4 '10 at 22:57
add comment

2 Answers 2

up vote 6 down vote accepted

The longtable package redefines \hline to allow pagebreaks by introducing penalties like \penaly-\@lowpenalty in the code. If I understand correctly, what you want is a variant of \hline which does not introduce any break point. To do this, you can just copy the code used to redefine \hline in longtable.sty and use it define a \nobreakhline variant macro in which the penalties have been changed to 10000 so as to prevent all pagebreaks. This gives the following code:

\documentclass[12pt,a4paper,oneside]{letter}

\usepackage{longtable}

\makeatletter
\def\nobreakhline{%
  \noalign{\ifnum0=`}\fi
    \penalty\@M
    \futurelet\@let@token\LT@@nobreakhline}
\def\LT@@nobreakhline{%
  \ifx\@let@token\hline
    \global\let\@gtempa\@gobble
    \gdef\LT@sep{\penalty\@M\vskip\doublerulesep}% <-- change here
  \else
    \global\let\@gtempa\@empty
    \gdef\LT@sep{\penalty\@M\vskip-\arrayrulewidth}% <-- change here
  \fi
  \ifnum0=`{\fi}%
  \multispan\LT@cols
     \unskip\leaders\hrule\@height\arrayrulewidth\hfill\cr
  \noalign{\LT@sep}%
  \multispan\LT@cols
     \unskip\leaders\hrule\@height\arrayrulewidth\hfill\cr
  \noalign{\penalty\@M}%
  \@gtempa}
\makeatother

\begin{document}

\begin{longtable}{ | p{5cm} | }
\hline
Table header\\*
\nobreakhline
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris pharetra
porttitor turpis, id egestas neque congue in. Nam sed lorem lorem, ac
tristique tellus. Nunc ornare feugiat orci, a blandit turpis facilisis ut.
Aenean pharetra ornare ante. Sed tempus leo in dolor eleifend placerat.
Integer at enim augue. Ut nisl tortor, interdum ac porttitor ac, sagittis
quis libero. Vivamus nibh metus, ornare vel pulvinar nec, fringilla nec
orci. Maecenas mollis nulla a nibh fringilla nec convallis augue varius.
Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere  
cubilia Curae. \\
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris pharetra
porttitor turpis, id egestas neque congue in. Nam sed lorem lorem, ac
tristique tellus. Nunc ornare feugiat orci, a blandit turpis facilisis ut.
Aenean pharetra ornare ante. Sed tempus leo in dolor eleifend placerat. 
Integer at enim augue. Ut nisl tortor, interdum ac porttitor ac, sagittis
quis libero. Vivamus nibh metus, ornare vel pulvinar nec, fringilla nec   
orci. Maecenas mollis nulla a nibh fringilla nec convallis augue varius.  
Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere  
cubilia Curae. \\
\hline
Table header\\*
\nobreakhline
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris pharetra
porttitor turpis, id egestas neque congue in. Nam sed lorem lorem, ac   
tristique tellus. Nunc ornare feugiat orci, a blandit turpis facilisis ut.
Aenean pharetra ornare ante. Sed tempus leo in dolor eleifend placerat.   
Integer at enim augue. Ut nisl tortor, interdum ac porttitor ac, sagittis 
quis libero. Vivamus nibh metus, ornare vel pulvinar nec, fringilla nec   
orci. Maecenas mollis nulla a nibh fringilla nec convallis augue varius.  
Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere 
cubilia Curae. \\
\hline
\end{longtable}

\end{document}

Here is the detail of how the previous code works. It's between \makeatletter and \makeatother because it's internal code containing the @ character. The code is in two parts: it starts by defining the \nobreakhline which then calls another macro, \LT@@nobreakhline. The macro begins with

\def\nobreakhline{%
  \noalign{\ifnum0=`}\fi

The \ifnum..\fi is a trick to make TeX that think that braces are correctly paired when they are not. It it thus equivalent to \noalign{, the closing brace being in the line beginning by \ifnum in the second macro. The macro then sets a penalty and calls the second macro thanks to a \futurelet:

    \penalty\@M
    \futurelet\@let@token\LT@@nobreakhline}

This \futurelet is here to look ahead the \nobreakhline macro; as we will see, the behavior will not be the same if it's followed by another \hline or not.

We not get to the definition of \LT@@nobreakhline. It begins by an if test:

\def\LT@@nobreakhline{%
  \ifx\@let@token\hline
    \global\let\@gtempa\@gobble
    \gdef\LT@sep{\penalty\@M\vskip\doublerulesep}% <-- change here

The test consists at looking if the next token is \hline or not. If it is, then the macro \@gtempa is set to \@gobble. As its name suggest, the \@gobble macros just gobbles the token following it. The macro \@gtempa is defined here but used at the end of \LT@@nobreakhline and so this means that \LT@@nobreakhline will gobble the \hline just following it, which avoids \hline to be typesetted twice. After setting \@gtempa, the macro \LT@sep is also set. That's the part which I changed from the original longtable.sty code: the penalty is changed from -\@medpenalty (which is something like -151, depending on the documentclass) to \@M (which is a shortcut for 10000); this prevents any break to occur where the penalty is issued.

We now get to the else part of the conditional:

  \else
    \global\let\@gtempa\@empty
    \gdef\LT@sep{\penalty\@M\vskip-\arrayrulewidth}% <-- change here
  \fi

It has the same structure as the then part, except that it occurs only if our macro \nobreakhline is not followed by \hline and sets the ending macro \@gtempa to be noting (\@empty) meaning nothing special will be done at the end of \LT@@nobreakhline; there is also a penalty change to prevent breaking; this time the penalty was -\@lowpenalty (about -51) and is changed to 10000 as before. The next line is the "closing brace" mentioned before:

  \ifnum0=`{\fi}%

The next lines of codes typesets the rule:

  \multispan\LT@cols
     \unskip\leaders\hrule\@height\arrayrulewidth\hfill\cr

Then the macro \LT@sep defined earlier is used, and it has the effect of preventing any breaks:

  \noalign{\LT@sep}%

Then there's another rule which is typesetted (it could probably be deleted from the code as we don't allow breaks any more, but it's harmless as it overlaps with the previous rule thanks to the negative \vskip in \LT@sep):

  \multispan\LT@cols
     \unskip\leaders\hrule\@height\arrayrulewidth\hfill\cr

Finally, the macro ends with a penalty (to avoid another breaking point) and then the ending macro \@gtempa defined earlier is issued:

  \noalign{\penalty\@M}%
  \@gtempa}
share|improve this answer
add comment

The solution of Philippe Goutet does not work well with colortbl package and setting the color of the horizontal line with \arrayrulecolor. Here is the solution that should work with colortbl:

\makeatletter
\def\nobreakhline{%
\noalign{\ifnum0=`}\fi
 \penalty\@M
\futurelet\@let@token\LT@@nobreakhline}
\def\LT@@nobreakhline{%
\ifx\LT@next\hline
  \global\let\LT@next\@gobble
 \ifx\CT@drsc@\relax
   \gdef\CT@LT@sep{%
     \noalign{\penalty\@M\vskip\doublerulesep}}%
 \else
   \gdef\CT@LT@sep{%
     \multispan\LT@cols{%
       \CT@drsc@\leaders\hrule\@height\doublerulesep\hfill}\cr}%
 \fi
\else
 \global\let\LT@next\empty
 \gdef\CT@LT@sep{%
   \noalign{\penalty\@M\vskip-\arrayrulewidth}}%
\fi
\ifnum0=`{\fi}%
\multispan\LT@cols
 {\CT@arc@\leaders\hrule\@height\arrayrulewidth\hfill}\cr
\CT@LT@sep
\multispan\LT@cols
 {\CT@arc@\leaders\hrule\@height\arrayrulewidth\hfill}\cr
\noalign{\penalty\@M}%
\LT@next}
\makeatother
share|improve this answer
    
Welcome to TeX.sx! –  Peter Jansson Apr 10 '13 at 10:18
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.