4

I have a code that runs through and automated process in order to produce a latex layout.

In this process I need to recognize in which flowframe a specific point of text is. For example I need to know if the end of the second paragraph is on the flowframe 1 or 2.

To achieve this I'm using the command \thethis frame which returns the value contained in the counter \c@thisframe that should correspond to the current frame.

This works fine until the line i'm querying is the first line of a flowframe. In this case the ID returned is from the previous frame.

Here is a simple example of the issue

\documentclass[a4paper]{article}
\usepackage{flowfram}

\twocolumn

\begin{document}
aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa 
aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa 
aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa 
aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa 
aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa 
aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa 
aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa 
aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa 
aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa 
aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa 
aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa 
aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa 
aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa 
aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa 
aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa 
aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa 
aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa 
aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa 
aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa 
aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa 
aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa 
aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa 
aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa 
aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa 
aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa 
aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa 
aaa aaa aaa aaa aaa aaa aaa aaa \textbf{The current frame id is: \thethisframe} aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa \textbf{And now the frame id is: \thethisframe}

aaa \textbf{Here the frame id is: \thethisframe}

\end{document}

Which produces the following result.

Code sample result

Is there a way that I can always identify the correct frame of any specific position? Or how can I fix the code so this error doesn't happen?

1 Answers1

2

The problem is caused by TeX's asynchronous output routine. The count register isn't updated until the paragraph break occurs. The same problem occurs with the page count as illustrated here:

\documentclass[a4paper]{article}

\usepackage{geometry}
\usepackage{lipsum}

\begin{document}
\lipsum[1-6]

\lipsum*[7] Page: \thepage.

\end{document}

The standard way of getting around this is to use \label / \pageref like this:

\documentclass[a4paper]{article}

\usepackage{geometry}
\usepackage{lipsum}

\begin{document}
\lipsum[1-6]

\lipsum*[7] Page: \label{here}\pageref{here}.

\end{document}

Unfortunately this only works for counters that are incremented using \refstepcounter. The count register \c@thisframe isn't increment but is instead set to the next available frame that's valid for the given page. However, flowfram provides a command to label the current frame:

\newcommand*{\labelflowidn}[1]{%
  {%
    \def\@currentlabel{\thethisframe}%
    \label{#1}%
  }%
}

Unfortunately, unlike \c@page, \c@thisframe doesn't stabilise until after the \protected@write to the .aux file occurs.

One way to get around this is to patch \@setcol like this:

\makeatletter
\let\@org@setcol\@setcol

\def\dodeferredstuff{}

\renewcommand{\@setcol}[1]{\@org@setcol{#1}\dodeferredstuff}

\newcommand{\deferredlabelflowidn}[1]{%
  \def\dodeferredstuff{\labelflowidn{#1}\let\dodeferredstuff\relax}%
}
\makeatother

And use \deferredlabelflowidx instead. Adjusted MWE:

\documentclass[a4paper]{article}

\usepackage{flowfram}

\makeatletter
\let\@org@setcol\@setcol

\def\dodeferredstuff{}

\renewcommand{\@setcol}[1]{\@org@setcol{#1}\dodeferredstuff}

\newcommand{\deferredlabelflowidn}[1]{%
  \def\dodeferredstuff{\labelflowidn{#1}\let\dodeferredstuff\relax}%
}
\makeatother

\twocolumn

\begin{document}
aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa 
aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa 
aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa 
aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa 
aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa 
aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa 
aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa 
aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa 
aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa 
aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa 
aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa 
aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa 
aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa 
aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa 
aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa 
aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa 
aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa 
aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa 
aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa 
aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa 
aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa 
aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa 
aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa 
aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa 
aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa 
aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa 
aaa aaa aaa aaa aaa aaa aaa aaa \textbf{The current frame id is:
\thethisframe} aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa \textbf{And
now the frame id is: \thethisframe} Label/ref: 
\labelflowidn{here}\ref{here}.
Deferred: \deferredlabelflowidn{defhere}\ref{defhere}.

aaa \textbf{Here the frame id is: \thethisframe}


\end{document}

Label/ref: 1. Deferred: 2.

Unfortunately, this only works when used in the last paragraph of the frame. A better approach is to do the deferred command at the start of the next paragraph using \everypar:

\def\dodeferredstuff{}

\newcommand{\deferredlabelflowidn}[1]{%
  \def\dodeferredstuff{\labelflowidn{#1}\let\dodeferredstuff\relax}%
}

\everypar{\dodeferredstuff}

To guard against section commands that reset \everypar:

\def\dodeferredstuff{}

\newcommand{\deferredlabelflowidn}[1]{%
  \def\dodeferredstuff{\labelflowidn{#1}\let\dodeferredstuff\relax}%
  \everypar{\dodeferredstuff}%
}

Here's the amended MWE:

\documentclass[a4paper]{article}

\usepackage{flowfram}

\def\dodeferredstuff{}

\newcommand{\deferredlabelflowidn}[1]{%
  \def\dodeferredstuff{\labelflowidn{#1}\let\dodeferredstuff\relax}%
  \everypar{\dodeferredstuff}%
}

\twocolumn

\begin{document}
aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa 
aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa 
aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa 
aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa 
aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa 
aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa 
aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa 
Deferred: \deferredlabelflowidn{sample}\ref{sample}.

aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa 
aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa 
aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa 
aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa 
aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa 
aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa 
aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa 
aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa 
aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa 
aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa 
aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa 
aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa 
aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa 
aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa 
aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa 
aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa 
aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa 
aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa 
aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa 
aaa aaa aaa aaa aaa aaa aaa aaa \textbf{The current frame id is:
\thethisframe} aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa \textbf{And
now the frame id is: \thethisframe} Label/ref: 
\labelflowidn{here}\ref{here}.
Deferred: \deferredlabelflowidn{defhere}\ref{defhere}.

aaa \textbf{Here the frame id is: \thethisframe}


\end{document}

image of result

Nicola Talbot
  • 41,153
  • The only issue with the last solution is that it won't work if the line that we want to reference is the last line of the document. In that case the reference will not be defined. – Fernando Jan 16 '17 at 17:19
  • As this is an automated process I might as well use your @setcol solution concurrently with the \everypar solution. Do you see any problems with that approach? – Fernando Jan 16 '17 at 17:27
  • @Fernando I'm not sure if there'll be a conflict. It's occurred to me that it might be better to append to \dodeferredstuff and reset \dodeferredstuff after it's used (rather than including the reset in the command definition). It could have a problem with a new instance of \deferredlabelflowidn overriding a previous one before it's been processed. – Nicola Talbot Jan 16 '17 at 17:57