%  P L A C E I N S . T E X        ver 2.0   Mar 3, 1995
%
%  Insertions that keep their place.
%
%  Copyright 1995    Donald Arseneau       <asnd@triumf.ca>
%  These macros may be freely used, transmitted, reproduced, or modified
%  provided that this notice is left intact.
%
%  This TeX file provides various mechanisms (for plain TeX and close 
%  relatives) to let insertions (footnotes, topins, pageins, etc.) float 
%  within their appropriate section, but to prevent them from intruding 
%  into the following section, even when sections do not normally begin 
%  a new page.  (If your sections normally begin a new page, just use 
%  \supereject to flush out insertions.)
%
%  Different combinations of insertions can be controlled with different
%  commands:
%  
%  \par\penalty-20029  
%         If there are any insertions that will not fit on the current page,
%         a \supereject is performed and the following text will continue at
%         the top of a page after all insertions.  If all insertions do fit
%         on the current page, then the following text will continue
%         immediately on this page. 
%  \par\penalty-20030  
%         Like above, except that if there are any footnotes at all on the
%         current page, the section must begin on the next page. (This is so
%         no footnote text from section 1 will appear beneath the beginning
%         of section 2.) 
%  \par\penalty-10029  
%         If any insertions cannot fit on the current page, eject them, and
%         then allow the following section to begin immediately on the same
%         page as the last insert. If all insertions do fit on the current
%         page, then the following text will continue immediately on this
%         page. 
%  \barrier{\eject}{\topins}
%         If there are any pageinserts or topinserts that do not fit on the
%         current page, eject them, and then allow the following section to
%         begin immediately on the same page as the last insert.  Split
%         footnotes or other insertions are allowed to intrude into the next
%         section. 
%  \barrier{\supereject}{\topins}
%         Like the \barrier command above, but if any inserts are ejected 
%         the following section will begin at the top of a new page (like 
%         \supereject).
%  \barrier{...}{\footins}
%         *** NOT ALLOWED ***  You will get spurious space and footnote-rules 
%         at the bottom of pages!
%  \barrier{...}{\margins}    
%         If you define other insertion classes, such as marginal notes, you 
%         can use \barrier for them too.  But only if \skip\margins=0pt.  
%         You must also add any new insertion classes to the definition of 
%         \placerestoreoutput
%
%  How to use:  First, \input this file (of course!).  Then, at the beginning
%  of a new section, or at any boundary that insertions should not cross, put
%  one of the commands listed above.  Presumably, you will actually put these
%  commands at the start of your own \section or \startsection macro; that is
%  why they are non mnemonic!
%
%  There is a slight chance that a footnote may be separated from its reference
%  in the text after \penalty-xxxxx when there are no split insertions.  (LaTeX
%  has the same possibility at every float!)
 
\chardef\noplaceoutput\catcode`\@
\catcode`\@=11

\edef\zero@skip{\the\z@skip}

\def\barrier#1#2{\par\begingroup
 \ifdim\skip#2>\z@{\newlinechar10\errhelp{\barrier#2may produce some spurious
   extra material on the page, ^^J but I will try anyway.}\errmessage{Bad use 
   of \string\barrier}}%
 \fi
 \skip@\lastskip \edef\next{\the\skip@}\ifx\next\zero@skip\else\vskip-\skip@\fi
 \penalty\z@ % update page parameters
 \fam-\insertpenalties
 \insert#2{\floatingpenalty\@ne}%
 \ifx\next\zero@skip\else\vskip\skip@\fi
 \advance\fam\insertpenalties % 0: no held; 1: held over
 \expandafter\endgroup
 \ifnum\fam=\@ne % then do eject
% \message{There are held-over \string#2 inserts; performing \string#1. }%
  \ifdim\pagetotal<\topskip \leftline{}\kern-\topskip\fi % avoid empty list 
  {\dimen@\pagetotal \advance\dimen@\pagedepth 
   \ifdim\dimen@<\pagegoal\vfill\fi}%
  #1\@barrier{#1}{#2}\else
%   \message{There are no held-over \string#2 inserts. \space}%
\fi
}

\def\placeinsoutput{%
\ifnum\outputpenalty=-20030\relax % eject if any footnotes
  \ifvoid\footins\else 
   \fam\insertpenalties \advance\fam\@ne \insertpenalties\fam
  \fi \outputpenalty=-20029\relax
\fi
\ifnum\outputpenalty=-20029\relax % Check for `supereject' flag
 \ifnum\insertpenalties>\z@ % something is being held over, must get it out
% \message{Forcing insertions on their own pages. \space}%
  \ifvoid\footins \r@ggedbottomtrue \else \advance\skip\footins 0ptplus1fil\fi
  \noplaceoutput % performs \supereject
 \else % must rejoin seamlessly:
  \placerestoreoutput
 \fi
\else % check for other flag...
 \ifnum\outputpenalty=-10028 % in the middle of ejecting
  \ifnum\insertpenalties=\z@ \global\setbox\@cclv\vbox{}\fi
  \outputpenalty=-10029
 \fi
 \ifnum\outputpenalty=-10029\relax % section start
  \ifnum\insertpenalties>\z@ % something is being held over, must get it out
%  \message{Forcing insertions. \space}%
   \ifvoid\footins \r@ggedbottomtrue \else \advance\skip\footins 0ptplus1fil\fi
   \noplaceoutput % performs \eject, perhaps repeatedly:
   \leftline{}\kern-\topskip \penalty-10028\relax % (like \dosupereject)
  \else % must rejoin seamlessly:
   \placerestoreoutput
  \fi
 \else % just a regular page break
  \noplaceoutput
 \fi
\fi
}

% there is a slim chance that footnotes may lose their place.
\def\placerestoreoutput{%
  \ifvoid\footins\else\insert\footins{\unvbox\footins}\fi
  \ifvoid\topins\else\insert\topins{\unvbox\topins}\fi
% If you have other floating insertion classes, do the same here.
  \unvbox\@cclv
}

\catcode`\@=\noplaceoutput

\edef\noplaceoutput{\the\output}
\output{\placeinsoutput}
