These are LaTeX kernel macros that are associated with environments. In simple terms anything that is enclosed with a \begin{foo}...\end{foo}
is an environment. For example a figure or a table.
Every time you insert a table a counter is incremented. This counter let us call it foo
has an associated macro named \p@foo
. This macro expands to a printed `reference prefix' of counter
foo.
Any \ref
to a value created by counter foo
will produce the expansion of \p@foo\thefoo
when the \label
command is executed. \thefoo
justs prints the value of counter `foo'.
Change foo
to figure
or table
and it will make more sense.
The \def
part defines the macro. You can for example say \def\milan{Milan Ramaiyan}
and every time you type \milan
it will expand too .. Milan Ramaiyan. The @
symbol is just a special symbol used by TeX and LaTeX to avoid overriding commands accidentally. It needs special treatment and that is why the makeatletter
and makeatother
are required.
For our purposes, \begin{#1}
is roughly
\begingroup \@endpefalse \csname #1\endcsname
and \end{#1}
is roughly
\csname end#1\endcsname\expandafter \endgroup \if@endpe \@doendpe \fi
Since \expandafter
expands \if@endpe
before the group ends, the value of the switch that is used is the one within the environment. If the \csname #1\endcsname
part of a \begin{#1}
features \@endpetrue
, then \@doendpe
will be expanded. However, it will be expanded outside the environment, where the switch has been returned to its former value.
Consider the following document. The environment parenvA
suppresses the indentation afterwards. In the second case, \@endparenv
is called within two groups, and causes \@doendpe
to be called still within the parenvB
environment. If the definition of \@doendpe
did not have \@endpetrue
, then it would simply define \par
and \everypar
within the parenvB
environment. These definitions would disappear at the end of the group, and the next paragraph would be indented. So instead, \@doendpe
makes sure to carry the truth of the switch with it beyond environment boundaries, until the next \par
or \everypar
.
\documentclass{article}
\makeatletter
\newenvironment{parenvA}{}{\par\@endparenv}
\newenvironment{parenvB}{}{}
\makeatother
\usepackage{lipsum}
\begin{document}
% case 1
\begin{parenvA}
\lipsum[1]
\end{parenvA}
\lipsum[2]
% case 2
\begin{parenvB}
\begin{parenvA}
\lipsum[3]
\end{parenvA}
\end{parenvB}
\lipsum[4]
% case 3
\begin{parenvB}
\begin{parenvA}
\lipsum[5]
\end{parenvA}
\lipsum[6]
\end{parenvB}
\lipsum[7]
\end{document}
Once this is established, both \par
and \everypar
must have \@endpefalse
, otherwise the last paragraph in the example above would lose its indentation: indeed, the \@doendpe
triggered just outside the parenvA
environment contains \@endpetrue
, but we don't want the indentation to be suppressed after that \end{parenvB}
, because there has already been a paragraph.
Now why do we need to work with both \everypar
and \par
? Because there are actually two cases. If the user leaves no blank line after \end{parenvA}
, then the first letter, inherently horizontal for TeX, causes \everypar
to be inserted, and to eat the indentation (with \lastbox
). However, if the user leaves a blank line, TeX's eyes replace that by a \par
token, which resets the normal definitions of \par
and \everypar
, and do not eat any indentation (try adding some blank lines in the file above and see what happens).
For your bonus question, well, if you remove those lines, the indentation will only be removed if the next \par
(blank line) or \everypar
(triggered by horizontal material) is within the same group/environment. Not necessarily what you want.
Best Answer
The declaration
does
Let's see what happens when LaTeX finds
$\rm a$
in the following minimal document:Let's start:
\rm
is a robust command, so this is its normal expansion. Now, since\protect
is\relax
,\rm
is expanded:Next
\@fontswitch
is expanded:We see the arguments. Since we are in math mode, the "true" branch is followed, so the redefinitions of
\math@bgroup
and\math@egroup
are performed and\mathrm
is expanded:Again, we're in math mode (
\mathrm
has some code for disallowing its use outside of it); the tests are performed using the fact that the expansion of\f@encoding
isNow it remains to expand
\math@egroup
:and the business is finished. Essentially, this is transformed into
If
{\rm a}
is found in text mode, then it becomes essentiallythat is, the old behavior of the
\rm
command is emulated.This is why
{\sf\sl a}
won't use a slanted sans serif font, but a serif slanted one: it becomes equivalent toMoral: never use the old font commands. You gain nothing and lose much of the flexibility of the new ones. Well, after 18 years they aren't really new.