# How can I detect if I'm inside or outside of a float environment?

I am trying to detect whether I am inside or outside a float. I know the way how caption works. It uses the internal \@captype. But in the example below you see that this test failed by using captionsetup{type=figure}. Of course this feature is really fussy.

I create a minimal example which changed the internal \@endfloatbox and \@floatboxreset to add a bool expression.

You will see that it works in the minimal example. Now my question: Do you know any reasons why I shouldn't do it. (It's for a package on CTAN)

\documentclass{article}
\parindent0pt
\usepackage{caption}
\usepackage{etoolbox}
\makeatletter
\newbool{detect@float}
\appto\@endfloatbox{\boolfalse{detect@float}}
\preto\@floatboxreset{\booltrue{detect@float}}
\newrobustcmd*\testiffloat[1]{%
in \texttt{#1}\ \ifbool{detect@float}{Inside float}{Outside float}%
}
\newrobustcmd*\testiffloatI[1]{%
in \texttt{#1}\
\ifx\@captype\@undefined
Outside float%
\else
Inside float%
\fi
}
\makeatother
\usepackage{lipsum}
\begin{document}

\begin{figure}[!ht]
\end{figure}

\begin{figure*}[!ht]
\end{figure*}

\begin{flushleft}
\captionsetup{type=figure}
\end{flushleft}

\begin{flushleft}
\captionsetup{type=figure}
\end{flushleft}

\end{document}


\documentclass{book}
\usepackage{caption}

\makeatletter
\def\InFloat{\ifnum\@floatpenalty<0\relax in float \else outside float \fi}
\makeatother
\begin{document}

\begin{figure}\relax
[figure]: \InFloat
\end{figure}

\begin{center}
[center]: \InFloat
\end{center}

\captionsetup{type=figure}
\begin{center}
[center]: \InFloat
\end{center}

\end{document}


The counter \@floatpenalty controls float processing. It defaults to 0, but is set to a negative value at a beginning of a float. This code checks for this value to be negative (inside float) or not (outside float) using low-level \ifnum test.

• Oddly, this test doesn’t work when I’m using it to conditionally define a marginpar – I’m doing this, inside a macro: \ifnum\@floatpenalty<0\relax\let\mp\marginnote\else\let\mp\marginpar\fi\mp{Some text}, and that always goes into the float branch. However, if I take out the \let\mp… and instead print some text, it goes into the correct branch. Subsequently outputting a marginpar seems to influence the \IfFloat test in the past. – Konrad Rudolph Feb 4 '15 at 12:01

In most cases, test using \@captype should work:

\makeatletter
\newcommand\InFloat[2]{\@ifundefined{@captype}{#2}{#1}}
\makeatothe‌‌​​r


With the usage \InFloat{INSIDE}{OUTSIDE}.

The code is based on the idea that \@captype stores the type of the float in which we are, i.e. \@captype -> figure inside figure etc. Especially, \@captype is undefined outside any float since floats form a group and the value is "forgotten" once we exit the float. Macro \@ifundefined takes macro name (without the leading \) and tests for being defined.