You can use zref
with the abspos
and user
modules (e.g. load the zref-abspos
and zref-user
packages) and add a \zlabel{labelname}
to the \tikzmark
at the beginning of the paragraph as well one at the end of the paragraph. If you using an environment simply place one at begin
and end
. Then you can check at the end of the environment if the absolute page numbers of both are identical or not. For this you can use:
\ifnum\zref@extract{<begin-label>}{abspage}=\zref@extract{<end-label>}{abspage}\relax
<same page>
\else
<different page>
\fi
(Note: Maybe \zref@extractdefault
is better because you can provide a default value used for the first runs when the label is not set yet.)
See also my answer to How to draw text-anchored tikz line below text instead of above? where I do something very similar!
Here a solution I now come up with. It draws the first border half in the begin-macro if the end-macro is not at the same page. Also the case where the environment spans more than two pages, e.g. starts at page 1 and ends at page 3, is covered by extra code.
\documentclass[twoside]{book}
\usepackage{zref-abspage}
\usepackage{zref-user}
\usepackage{tikz}
\usepackage{atbegshi}
\usetikzlibrary{calc}
\makeatletter
\newcommand{\currentsidemargin}{%
\ifodd\zref@extract{textarea-\thetextarea}{abspage}%
\oddsidemargin%
\else%
\evensidemargin%
\fi%
}
\newcounter{textarea}
\newcommand{\settextarea}{%
\stepcounter{textarea}%
\zlabel{textarea-\thetextarea}%
\begin{tikzpicture}[overlay,remember picture]
% Helper nodes
\path (current page.north west) ++(\hoffset, -\voffset)
node[anchor=north west, shape=rectangle, inner sep=0, minimum width=\paperwidth, minimum height=\paperheight]
(pagearea) {};
\path (pagearea.north west) ++(1in+\currentsidemargin,-1in-\topmargin-\headheight-\headsep)
node[anchor=north west, shape=rectangle, inner sep=0, minimum width=\textwidth, minimum height=\textheight]
(textarea) {};
\end{tikzpicture}%
}
\tikzset{tikzborder/.style={line width=1mm,red,double=blue}}
\newcounter{tikzborder}
\newcounter{tikzborderpages}
\newenvironment{tikzborder}[1][]{%
\medskip\par
% Allow user to overwrite the used style locally
\ifx&\else
\tikzset{tikzborder/.style={#1}}%
\fi
\settextarea
\stepcounter{tikzborder}%
\tikz[overlay,remember picture] \coordinate (tikzborder-\thetikzborder);% Modified \tikzmark macro
\zlabel{tikzborder-begin-\thetikzborder}%
% Test if end-label is at the same page and draw first half of border if not
\ifnum\zref@extract{tikzborder-begin-\thetikzborder}{abspage}=\zref@extract{tikzborder-end-\thetikzborder}{abspage} \else
\begin{tikzpicture}[overlay,remember picture]
\draw [tikzborder]
let \p0 = (textarea.north west), \p1 = (tikzborder-\thetikzborder), \p2 = (textarea.south east) in
(\x0-\fboxsep-.5\pgflinewidth,\y2-\fboxsep-.5\pgflinewidth)
|-
(\x2+\fboxsep+.5\pgflinewidth,\ht\strutbox+\fboxsep+.5\pgflinewidth)
--
(\x2+\fboxsep+.5\pgflinewidth,\y2-\fboxsep-.5\pgflinewidth)
;
\end{tikzpicture}%
% If it spreads over more than two pages:
\setcounter{tikzborderpages}{\numexpr-\zref@extract{tikzborder-begin-\thetikzborder}{abspage}+\zref@extract{tikzborder-end-\thetikzborder}{abspage}}
\ifnum\value{tikzborderpages}>1
\AtBeginShipoutNext{\tikzborderpage}%
\fi
\fi
}{%
\zlabel{tikzborder-end-\thetikzborder}%
% Test if begin-label is at the same page and draw while border if so
\ifnum\zref@extract{tikzborder-begin-\thetikzborder}{abspage}=\zref@extract{tikzborder-end-\thetikzborder}{abspage}
\begin{tikzpicture}[overlay,remember picture]
\draw [tikzborder]
let \p0 = (textarea.north west), \p1 = (tikzborder-\thetikzborder), \p2 = (textarea.south east) in
(\x0-\fboxsep-.5\pgflinewidth,\y1+\ht\strutbox+\fboxsep+.5\pgflinewidth)
|-
(\x2+\fboxsep+.5\pgflinewidth,-\dp\strutbox-\fboxsep-.5\pgflinewidth)
|-
(\x0-\fboxsep-.5\pgflinewidth,\y1+\ht\strutbox+\fboxsep+.5\pgflinewidth)
-- cycle
;
\end{tikzpicture}%
% Otherwise draw second half of border
\else
\settextarea
\begin{tikzpicture}[overlay,remember picture]
\draw [tikzborder]
let \p0 = (textarea.north west), \p1 = (tikzborder-\thetikzborder), \p2 = (textarea.south east) in
(\x0-\fboxsep-.5\pgflinewidth,\y0+\fboxsep+.5\pgflinewidth)
|-
(\x2+\fboxsep+.5\pgflinewidth,-\dp\strutbox-\fboxsep-.5\pgflinewidth)
--
(\x2+\fboxsep+.5\pgflinewidth,\y0+\fboxsep+.5\pgflinewidth)
;
\end{tikzpicture}%
\fi
\par\medskip
}
\newcommand{\tikzborderpage}{%
\settextarea
\begin{tikzpicture}[overlay,remember picture]
\draw [tikzborder]
([shift={(-\fboxsep-.5\pgflinewidth, \fboxsep+.5\pgflinewidth)}]textarea.north west)
--
([shift={(-\fboxsep-.5\pgflinewidth,-\fboxsep-.5\pgflinewidth)}]textarea.south west)
;
\draw [tikzborder]
([shift={( \fboxsep+.5\pgflinewidth, \fboxsep+.5\pgflinewidth)}]textarea.north east)
--
([shift={( \fboxsep+.5\pgflinewidth,-\fboxsep-.5\pgflinewidth)}]textarea.south east)
;
\end{tikzpicture}%
\addtocounter{tikzborderpages}{-1}%
\ifnum\value{tikzborderpages}>1
\AtBeginShipoutNext{\tikzborderpage}%
\fi
\vspace{-\baselineskip}% Compensate for the generated extra line at begin of the page. No idea why exactly this happens. Also \baselineskip seems not to be 100% right.
}
\makeatother
\usepackage{lipsum}
\newcommand\xlipsum[1][]{{\let\par\relax\lipsum*[#1]}}
\begin{document}
\begin{tikzborder}
\xlipsum[1]
\end{tikzborder}
\lipsum[2-4]
\begin{tikzborder}
\xlipsum[1]
\end{tikzborder}
\lipsum[2-4]
\begin{tikzborder}
\xlipsum[1-9]
\end{tikzborder}
\lipsum[2-4]
\begin{tikzborder}
\xlipsum[1-20]
\end{tikzborder}
\end{document}
(The frame is not displayed fully right in the picture because of the low resolution etc.
Click to enlarge)