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.

Suppose you have the following layout: example of multi-page inserts

The gray area represents normal text. The orange area consists of one or more text boxes (inserts) of given height. Some textbook layouts present advanced or secondary text material in such framed boxes, possibly spanning several pages.

A couple of years ago I developed, in collaboration with Massimiliano Dominici, a package called longmedal to handle this need to have some text flow on the upper part of consecutive pages. The package is discussed in this article on ArsTeXnica, the Italian TeX User Group Journal (in Italian). An incomplete English translation of the manual is found here.

Ever since the package mdframed came out I've been thinking to make this question: Is it possible to exploit the mdframed text splitting algorithm to achieve the layout presented above?

In practice, the trick should be taking the boxes produced internally by mdframed and putting them into consecutive empty figures. The top-fraction of the page occupied by the single figure should be a configuration parameter the user can play with.

share|improve this question
    
I think you can do this. My problem I don't know how can I print the output always on top. –  Marco Daniel Aug 6 '12 at 17:42
    
@MarcoDaniel Probably with \begin{figure}[H] ... \end{figure}, setting \topfraction appropriately. Also, I guess the package afterpage could help here. –  agodemar Aug 6 '12 at 17:49
    
afterpage sounds good. I will try it. –  Marco Daniel Aug 6 '12 at 17:51
add comment

1 Answer

up vote 8 down vote accepted

First of all my file which I used:

\documentclass{article}
\usepackage[framemethod=tikz,middlelinecolor=red,middlelinewidth=2pt,,everyline=true]{mdframed}
\usepackage{kantlipsum}
\usepackage{afterpage}
\input{mdframedaddon}
\mdfsetup{setheight=true,settoheight=.5\textheight}
\setcounter{totalnumber}{1}
\setcounter{topnumber}{1}
\begin{document}
\kant[1]
\kant[2]
\begin{mdframed}
\kant[2]
\kant[1]
\kant[2]
\kant[2]
\kant[1]
\kant[2]
\end{mdframed}
\kant[1]

\kant[2]

\kant[3]

\kant[4]
\end{document}

The result can be seen below.

I added to new keys which are called by:

\mdfsetup{setheight=true,settoheight=.5\textheight}

The output is done by the following definition:

\renewrobustcmd*\mdf@makebox@out[2][\linewidth]{%
\begin{figure}[t]
 \noindent\hb@xt@\z@{%
    \noindent\makebox[\dimexpr #1\relax][l]{#2}%
 \hss}%
\end{figure}
}%

However this results, that you can only use h as an identifier for float environments. I am sure you will improve this.

The complete work is done in the included file mdframedaddon.tex.

This is the complete file:

\makeatletter
\mdf@dolist{\mdf@do@lengthoption}{%
   {settoheight==0.5\textheight},%
}
\mdf@dolist{\mdf@do@booloption}{%
   {setheight==false},%
}

\renewrobustcmd*\mdf@makebox@out[2][\linewidth]{%
\begin{figure}[t]
 \noindent\hb@xt@\z@{%
    \noindent\makebox[\dimexpr #1\relax][l]{#2}%
 \hss}%
\end{figure}
}%

\renewrobustcmd*\detected@mdf@put@frame{%
  \ifmdf@nobreak%Option nobreak=true?
     \def\mdf@reserved@a{\mdf@put@frame@standalone}%
  \else
     \def\mdf@reserved@a{\mdf@put@frame}%
     \ifx\@captype\@undefined
         \def\mdf@reserved@a{\mdf@put@frame}%
     \else
         \mdf@PackageInfo{mdframed inside float  ^^J
                          mdframed uses option nobreak \mdframedpackagename}%
         \def\mdf@reserved@a{\mdf@put@frame@standalone}%
     \fi
     \if@minipage%
           \mdf@PackageInfo{mdframed inside minipage  ^^J
                           mdframed uses option nobreak \mdframedpackagename}%
           \def\mdf@reserved@a{\mdf@put@frame@standalone}%
     \fi%
     \ifinner%
          \mdf@PackageInfo{mdframed inside a box ^^J
                          mdframed uses option nobreak \mdframedpackagename}%
          \def\mdf@reserved@a{\mdf@put@frame@standalone}%
     \fi%
  \fi%
  \ifbool{mdf@setheight}{\def\mdf@reserved@a{\mdf@put@frame@setheight}}{}
\mdf@reserved@a%
}

\def\mdf@put@frame@setheight{\relax%
\ifvoid\mdf@splitbox@one\relax
  \mdf@PackageWarning{The environment is empty\MessageBreak}%
  \let\mdf@reserved@a\relax%
\else
  \setlength\mdfboundingboxwidth{\wd\mdf@splitbox@one}%
     \setlength{\mdf@verticalmarginwhole@length}%
                {\dimexpr\ht\mdf@splitbox@one+\dp\mdf@splitbox@one\relax}%
      \mdf@dolist{\mdf@advancelength@verticalmarginwhole}%
                 {%
                  outerlinewidth,middlelinewidth,innerlinewidth,%
                  innertopmargin,innerbottommargin,%
                  innerlinewidth,middlelinewidth,outerlinewidth}%
      \mdf@keeplines@single%
      \ifdimless{\mdf@verticalmarginwhole@length}{\mdf@settoheight@length}%
         {%passt auf Seite%
          \begingroup\mdf@@setzref\mdf@putbox@single\endgroup%Output no break
          \let\mdf@reserved@a\relax%
         }%
         {%
          \def\mdf@reserved@a{\mdf@put@frame@i@height}%passt nicht auf Seite
         }
\fi
\mdf@reserved@a%
}


\def\mdf@put@frame@i@height{%Box must be splitted
 \setlength{\dimen@}{.5\textheight}%
 \let\mdf@reserved@a\relax
    \mdf@dolist{\mdf@advancelength@freevspace@sub}{%calculate with \dimen@
              outerlinewidth,middlelinewidth,innerlinewidth,%
              innertopmargin,splitbottomskip}%
    \ifbool{mdf@everyline}%
      {%
       \ifbool{mdf@bottomline}%
          {%
           \advance\dimen@ by -\mdf@innerlinewidth@length%
           \advance\dimen@ by -\mdf@middlelinewidth@length%
           \advance\dimen@ by -\mdf@outerlinewidth@length%
          }{}%
      }{}%
    \notbool{mdf@topline}%
       {%
        \advance\dimen@ by \mdf@innerlinewidth@length%
        \advance\dimen@ by \mdf@middlelinewidth@length%
        \advance\dimen@ by \mdf@outerlinewidth@length%
       }{}%
%    \advance\dimen@.8\pageshrink
    \ifdimless{\ht\mdf@splitbox@one+\dp\mdf@splitbox@one}{\dimen@}%
       {\mdf@PackageWarning{You got a bad break\MessageBreak
                            because the last box will be empty\MessageBreak
                           you have to change it manually\MessageBreak
                           by changing the text, the space\MessageBreak
                           or something else}%
%        \advance\dimen@ by -1.8\baselineskip\relax%needed????????????????????
       }{}%
    \setbox\mdf@splitbox@save=\vbox{\unvcopy\mdf@splitbox@one}%
    \splitmaxdepth\z@ \splittopskip\mdf@splittopskip@length%
    \mdf@ignorevbadness%
    \setbox\mdf@splitbox@two\vsplit\mdf@splitbox@one to \dimen@
    \setbox\mdf@splitbox@two\vbox{\unvbox\mdf@splitbox@two}%
    \setbox\mdf@splitbox@one\vbox{\unvbox\mdf@splitbox@one}%
    \ifvoid\mdf@splitbox@one\relax%
      \mdf@PackageWarning{You got a bad break because the splittet box
                          is empty^^J
                          You have to change the page settings^^J
                          like enlargethispage or something else^^J
                          the package increases do
                         enlargethispage{baselineskip}\MessageBreak}%
    \fi%
    \ifdim\wd\mdf@splitbox@two=\wd\mdf@splitbox@one\relax
    \else%
      \mdf@PackageInfo{You first box width is to small^^J
                       mdframed fixed it\MessageBreak}%
      \setbox\mdf@splitbox@two=\vbox%
                   {%
                    \hrule \@height\z@ \@width\mdfboundingboxwidth\relax
                    \unvcopy\mdf@splitbox@two%
                   }%
    \fi%
    \begingroup\mdf@@setzref\mdf@putbox@first\endgroup%%
    \mdf@put@frame@ii@height%
}
\def\mdf@put@frame@ii@height{%
  \setlength{\mdf@freevspace@length}{\mdf@settoheight@length}%
    \ifbool{mdf@repeatframetitle}%
      {%
       \toggletrue{mdf@notfirstframetitle}%
       \splitmaxdepth\z@ \splittopskip\z@%
       \setbox\mdf@splitbox@one=\vbox{\break\unvbox\mdf@splitbox@one}%
       \mdf@ignorevbadness%
       \setbox0=\vsplit\mdf@splitbox@one to \z@\relax%
       \setbox\mdf@splitbox@one=\vbox{\unvbox\mdf@splitbox@one}
       \setbox\mdf@splitbox@one\vbox%
          {%
           \vbox to \mdf@frametitleaboveskip@length{}
           \unvcopy\mdf@frametitlebox\relax%
           \mdf@@frametitlerule\relax%
           \unvbox\mdf@splitbox@one\relax%
          }%
       \setbox\mdf@splitbox@one=\vbox{\unvbox\mdf@splitbox@one}%
      }{}%
  \setlength{\dimen@}{\dimexpr\ht\mdf@splitbox@one+\dp\mdf@splitbox@one\relax}%
  \mdf@dolist{\mdf@advancelength@freevspace@add}%
        {%used \dimen@
         innerbottommargin,innerlinewidth,middlelinewidth,outerlinewidth,%
        }%
  \ifbool{mdf@everyline}%
    {%
     \ifbool{mdf@topline}%
      {%
       \advance\dimen@ by \mdf@innerlinewidth@length\relax%
       \advance\dimen@ by \mdf@middlelinewidth@length\relax%
       \advance\dimen@ by \mdf@outerlinewidth@length\relax%
      }{}%
    }{}%
   \notbool{mdf@bottomline}%
     {%
      \advance\dimen@ by -\mdf@innerlinewidth@length\relax%
      \advance\dimen@ by -\mdf@middlelinewidth@length\relax%
      \advance\dimen@ by -\mdf@outerlinewidth@length\relax%
      \relax%
     }{}%
   \ifdimgreater{\dimen@}{\mdf@freevspace@length}%
    {%have a middle box
     \advance\mdf@freevspace@length by -\mdf@splitbottomskip@length\relax%
     \ifbool{mdf@everyline}%
       {%
        \ifbool{mdf@topline}%
          {%
          \advance\mdf@freevspace@length by -\mdf@innerlinewidth@length\relax%
          \advance\mdf@freevspace@length by -\mdf@middlelinewidth@length\relax%
          \advance\mdf@freevspace@length by -\mdf@outerlinewidth@length\relax%
          }{}%
        \ifbool{mdf@bottomline}%
          {%
          \advance\mdf@freevspace@length by -\mdf@innerlinewidth@length\relax%
          \advance\mdf@freevspace@length by -\mdf@middlelinewidth@length\relax%
          \advance\mdf@freevspace@length by -\mdf@outerlinewidth@length\relax%
          \relax
          }{}%
       }{}%
     \setbox\mdf@splitbox@save=\vbox{\unvcopy\mdf@splitbox@one}%
     \splitmaxdepth\z@ \splittopskip\mdf@splittopskip@length%
     \mdf@ignorevbadness%
     \setbox\mdf@splitbox@two\vsplit\mdf@splitbox@one to \mdf@freevspace@length
     \setbox\mdf@splitbox@two\vbox{\unvbox\mdf@splitbox@two}
     \setbox\mdf@splitbox@one\vbox{\unvbox\mdf@splitbox@one}
     \ifvoid\mdf@splitbox@one\relax%
        \mdf@PackageWarning{You got a bad break because the splittet box is
                            empty^^J
                            You have to change the page settings^^J
                            like enlargethispage or something else^^J
                            the package increases do
                            \enlargethispage{\baselineskip}\MessageBreak}%
        \setbox\mdf@splitbox@one=\vbox{\unvcopy\mdf@splitbox@save}%
        \enlargethispage{\baselineskip}%
        \def\mdf@reserved@a{\mdf@put@frame@ii}%
     \else
      \setbox\mdf@splitbox@two=\vbox%
                   {%
                    \hrule \@height\z@ \@width\mdfboundingboxwidth\relax
                    \unvcopy\mdf@splitbox@two%
                   }%
        \begingroup\mdf@@setzref\mdf@putbox@middle\endgroup%
          \def\mdf@reserved@a{\mdf@put@frame@ii}%
        \fi
     }%End middle box case
     {%start last box case
      \ifvoid\mdf@splitbox@one
           \mdf@PackageWarning{You got a bad break\MessageBreak
                               because the last split box is empty\MessageBreak
                               You have to change the settings}%%
           \setbox\mdf@splitbox@one=\vbox%
                  {%
                   \unvbox\mdf@splitbox@one%
                   \hrule \@height\z@ \@width\mdfboundingboxwidth
                  }%
      \fi%
      \ifdimless{\ht\mdf@splitbox@one}{1sp}%
         {%
          \mdf@PackageWarning{You got a bad break\MessageBreak
                              because the last split box is empty\MessageBreak
                              You have to change the settings}%

          \let\mdf@reserved@a\relax%
          \setbox\mdf@splitbox@one=\vbox%
                 {%
                  \unvbox\mdf@splitbox@one%
                  \hrule \@height\z@ \@width\mdfboundingboxwidth
                 }%
         }{}%
      \begingroup\mdf@@setzref\mdf@putbox@second\endgroup%
      \hrule \@height\z@ \@width\hsize%
      \let\mdf@reserved@a\relax%
     }%
  \mdf@reserved@a%
}

\makeatother

And here the result:

enter image description here

share|improve this answer
    
+1, Impressive work. Is that \makeafter before \begin{document} necessary? –  agodemar Aug 10 '12 at 18:44
    
@agodemar: Thanks. I removed the useless \makeatletter –  Marco Daniel Aug 10 '12 at 19:09
    
Looking forward to seeing this addon included in some future version of mdframed. Meanwhile, I'll experiment with this code. –  agodemar Aug 10 '12 at 21:05
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.