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.

I need to define a macro or do some special action every time a new page is encountered. In some sense I want to "number" tikzpictures but have all the tikzpictures on the same page contain the same number. (It's more complex than this but it is just a simple example)

Basically all I want to do is define a macro at the start of every new page. I'll use that macro to in my tikzpictures to do some special things and they may delete the macro depending on something(which is why I need to set it on each new page so it get's reset each page).

The macro needs to be defined at the start of every new page before any tex in my document is executed.

Basically I want to avoid having to add the macro in the document myself for each new page(which is hard to control and clutters up the thing).

My case: I have several tikspictures scattered throughout my document but some are on the same page.

I want the first one on the page to have special treatment(like put a caption on it). BUT I may add or remove text which may change the ordering and I don't want to have to update the code.

For example,

-New Page
Text
Img1 *
Img2 
-New Page
Img3 *
Text
Img4
Img5
-New Page
Img6 *

Because Img 1 3 and 6 are the first on the page I want to do something to them. BUT I do not want to hard code this because it may easily change(when I add text it may push put some images on a new page, i.e.,

-New Page
Text
Img1 *
-New Page
Img2 
Img3 *
Text
Img4
-New Page
Img5
Img6 *

and notice how * does not correspond to the first image on the page(like I want it). i.e., this is what will happen if you hard code the things I want to do.

Also, Because tex first has to calculate image bbox to determine if it is on the current page or not I need code that will work since my images will depend on if they are the first image on the page or not.

My "Special" action is only horizontally centering the image and so shouldn't effect layout.

The issue stems from

tikzpicture alignment and centering

and I'm trying to streamline and automate the process. I need to apply the master and slave pattern in the way I have describe. The first image on the page should get the master style and the remaining should get the slave BUT not hard coded since it causes the problem I gave above.

(Note how Jake's answer has hard coded master and slave. This causes major problems if you add text which pushes some images on a new page. (since the first image on the page should be master but by hard coded it you could get a slave as the first image)

share|improve this question
1  
This is possible but not that simple. If I understand you correctly it's similar to things I did in the past, either with the atbegshi or everypage package. Have a look at the following Qs and As: Installing background and foreground page layers with TikZ (both the question and answers), tex.stackexchange.com/a/19481/2975, tex.stackexchange.com/a/21522/2975 and tex.stackexchange.com/a/24279/2975. –  Martin Scharrer Apr 3 '12 at 16:16
    
This seems possible. However, you need to be more specific in your needs, since the current general description makes any generic solution (or answer) useless. For example, the first "simple example" has a definite answer, but you mention that things are "more complex." –  Werner Apr 3 '12 at 16:17
    
I also started to transform my above linked code into two packages, which however aren't finished yet. Just in case they or their code is useful for you: bitbucket.org/martin_scharrer/tikzpagelayers and bitbucket.org/martin_scharrer/tikzpagenodes. However, there are some issues with transparencies and maybe pattern which I didn't fixed yet. –  Martin Scharrer Apr 3 '12 at 16:20
    
@Werner Well, If you read what I said I gave the general case and a specific instance of that general case. Sure there are many ways to do things but as I said, I want to simply declare a new macro per new page at the top of it. If you give me the way to do that efficiently I should be able to take it from there. –  Uiy Apr 3 '12 at 16:52
3  
What you ask for can't be done exactly in tex as macro expansion happens long before pagination, it is quite easy, especially if producing big things like pictures or tables for macros to produce enough material to fill more than one page so the output routine cuts then in to pages later, and the macros have no knowledge of the final page at the time they are expanded. It is possible to take a best guess (based on the value of \thepage) and detect when it is wrong and adjust in a later run. see for example footnpag.sty which resets the footnote counter each page, so has exactly this problem. –  David Carlisle Apr 3 '12 at 17:08
show 3 more comments

2 Answers

up vote 10 down vote accepted

You still need to do it in two passes.

Consider a single long paragraph that takes a page or two. all macros in the paragraph are fully expanded before line breaking is considered, and only after line breaks are decided the output routine is triggered to consider page breaking.

The page breaking never affects the line breaking decisions, and the line breaker never affects the macro expansion. So no part of the macro expansion can be affected by the page breaking.

What you can do is get each picture to do a \label{uniquelabel} then it can (on a later run of latex) inspect \pageref{uniquelable} and \pageref{the-label-of-previous-figure} to see if you are the first on the page.

so in the example below, the first example on every page gets a modified formatting saying "first on page"

enter image description here

\documentclass{article}
\textheight15\baselineskip
\newcounter{pcount}
\makeatletter
\newenvironment{test}{%
\refstepcounter{pcount}%
\par\bigskip
\edef\this{\expandafter\expandafter\expandafter\@secondoftwo\csname r@x:\thepcount\endcsname\@empty}%
\ifx\this\@empty
\typeout{first pass}%
\def\format{}%
\else
\advance\c@pcount\m@ne
\edef\prev{\expandafter\expandafter\expandafter\@secondoftwo\csname r@x:\thepcount\endcsname\@empty}%
\advance\c@pcount\@ne
\ifx\prev\this
\def\format{}%
\else
\def\format{first on page! }%
\fi
\fi
\begin{tabular}{|l|}\hline \format test:\label{x:\thepcount} \thepcount\\\hline}
{\\\hline\end{tabular}
\bigskip}
\makeatother

\begin{document}

test

\begin{test}one\\two\end{test}
\begin{test}aaa\\bbb\\ccc\end{test}
\begin{test}aaa\\bbb\\ccc\end{test}

more text

\begin{test}red\\green\\blue\end{test}
\begin{test}1\\2\\2\\4\end{test}

more text

\begin{test}black\\white\\\end{test}
\begin{test}a\\b\\c\\d\end{test}

\end{document}
share|improve this answer
    
Ok, I'll have to spend a little time trying to determine exactly how the code works but I might be able to get it to work in my code. Is it possible to wrap this in a sort of "2ndpasspagecounter" and "2ndpasspageindexcounter" macros? The first would create a page counter that is expanded on the 2nd pass and the second would create an index counter per page(which would reset every new page)... basically your pcount. Essentially I would like to wrap the complexities since it would be too much work to apply this to each image. Obviously you can do it as an environment like you have. –  Uiy Apr 3 '12 at 23:36
    
But I'm thinking of simply having to call \2ndpasspagecounter would return the page number(but after the fact). \2ndpasspageindexcounter would return the index into the page... possibly every time it is called it is simply incremented except when a new page is create it would reset. (so it would be as simple as checking if a new page has been created and then reset the internal counter) –  Uiy Apr 3 '12 at 23:39
    
Your comment is not very clear, but if I understand you correctly that is not how TeX works. You can increment a page counter in the output routine as each page is shipped out, but that can not (with any reliability) affect the macro expansion that happens on that page, as as I explained the macros are expanded (and counters are set/reset/compared) long before that. –  David Carlisle Apr 3 '12 at 23:57
3  
That's why we always ask people to supply a MWE (which you have objected to in the past) If there had been an example, I'd have added the page reset to that, but as there was not, I had to make up an example and you have to extract the page reset code from that example. That's the way it goes... –  David Carlisle Apr 4 '12 at 10:23
1  
@Uiy If anything is unclear, please visit TeX Meta for questions and discussions about the site. Please do not do this in comments to TeX questions or answers. It is offtopic here. So I ask you please delete your comments here. Feel free to post a summary or follow-up questions on TeX Meta. I will clean up the other offtopic comments then. edit: offtopic/meta comments removed after 2 further days –  Stefan Kottwitz Apr 5 '12 at 10:07
show 6 more comments

Here is a plain TeX solution. I don't know if it will help you understand David Carlisle's code.

I still use LaTeX's document environment to test the code, but this is irrelevant.

\documentclass{article}

\newcount\uiycount
\newwrite\uiyout
\def\uiycar#1#2\nil{#1}
\def\uiyenv#1{%
  \global\advance\uiycount by1
  \def\currtag{\number\uiycount\number\count0}%
  \par\bigskip
  \def\proclaim{}%
  \immediate\write\uiyout{%
    \noexpand\expandafter\gdef\noexpand\csname
    uiy-\currtag\noexpand\endcsname{\the\count0}%
  }%
  \expandafter\expandafter\expandafter
  \ifx\expandafter\uiycar\csname uiy-\currtag\endcsname\nil\relax
    \typeout{first pass; please rerun.}%
  \else
    \edef\curr{\csname uiy-\currtag\endcsname}%
    \advance\uiycount by-1
    \edef\prev{\csname uiy-\currtag\endcsname}%
    \advance\uiycount by1
    \ifx\prev\curr\else
      \def\proclaim{first on page! }%
    \fi
  \fi
  #1\relax
}
\def\enduiyenv#1{#1\relax}
\openin\uiyout=\jobname.uiy
\ifeof\uiyout\else
  \input\jobname.uiy
\fi
\immediate\openout\uiyout=\jobname.uiy

% Tests
\begin{document}

Testing \ldots

% You can define \startstuff to be anything you want, or just use
% the stuff being defined in \startstuff directly as argument of
% \uiyenv (see example below):
\def\startstuff{%
  \begin{tabular}{|l|}\hline
  \proclaim test: \number\uiycount\\\hline
}
% Similarly, you can define \endstuff to be anything you want, or just use
% the stuff being defined in \endstuff directly as argument of
% \enduiyenv:
\def\endstuff{%
  \\\hline\end{tabular}\bigskip
}

\uiyenv\startstuff one\\two\enduiyenv\endstuff

\uiyenv{%
  \begin{tabular}{|l|}\hline
  \proclaim test: \number\uiycount\\\hline
}
aaa\\bbb\\ccc
\enduiyenv{%
  \\\hline\end{tabular}\bigskip
}

\uiyenv\startstuff aaa\\bbb\\ccc\enduiyenv\endstuff

\newpage
Next text \ldots

\uiyenv\startstuff red\\green\\blue\enduiyenv\endstuff
\uiyenv\startstuff 1\\2\\2\\4\enduiyenv\endstuff

\newpage
More text \ldots

\uiyenv\startstuff black\\white\\\enduiyenv\endstuff

\newpage
\uiyenv\startstuff a\\b\\c\\d\enduiyenv\endstuff

\end{document}
share|improve this answer
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.