summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/tex/plain/zztex/zzfloat.tex
diff options
context:
space:
mode:
Diffstat (limited to 'Master/texmf-dist/tex/plain/zztex/zzfloat.tex')
-rw-r--r--Master/texmf-dist/tex/plain/zztex/zzfloat.tex1164
1 files changed, 1164 insertions, 0 deletions
diff --git a/Master/texmf-dist/tex/plain/zztex/zzfloat.tex b/Master/texmf-dist/tex/plain/zztex/zzfloat.tex
new file mode 100644
index 00000000000..b6e3e082462
--- /dev/null
+++ b/Master/texmf-dist/tex/plain/zztex/zzfloat.tex
@@ -0,0 +1,1164 @@
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% Module: ZzTeX Float Facilities
+%
+% Synopsis: This module contains the float and caption blocks, as well as
+% all the code required to support the scheduling of floats.
+%
+% Notes: The broadside capability was implemented by Richard A. Wells and
+% integrated into ZzTeX on 9/7/94.
+%
+% Author: Richard A. Wells & Paul C. Anagnostopoulos
+% Created: 7 March 1990
+%
+% Copyright 1989--2020 by Paul C. Anagnostopoulos
+% under The MIT License (opensource.org/licenses/MIT)
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+% Data Structures
+% ---- ----------
+
+
+\definecount{\zfltcount}{0}
+\def \zfloatfreeq {}
+\def \zfloatpendq {}
+
+
+\def \zdeffloat #1#2{% {\float}{\float-box}
+ \definebox{#2}%
+ \zfreefloat{#1}{#2}%
+ \global\increment \zfltcount}
+
+\def \zgetfloat #1{% {\float}
+ \if \emptydefp{\zfloatfreeq}%
+ \error{toomanyflt}
+ {More than `\the\zfltcount' floats remain for page makeup}%
+ \else
+ \pop{#1}{\zfloatfreeq}%
+ \fi}
+
+\def \zfreefloat #1#2{% {\float}{\float-box}
+ \gdef #1{\def \zcurfloatbox {#2}}%
+ \append{#1}{\zfloatfreeq}}
+
+\zdeffloat{\zflta}{\zfltboxa}
+\zdeffloat{\zfltb}{\zfltboxb}
+\zdeffloat{\zfltc}{\zfltboxc}
+\zdeffloat{\zfltd}{\zfltboxd}
+\zdeffloat{\zflte}{\zfltboxe}
+\zdeffloat{\zfltf}{\zfltboxf}
+\zdeffloat{\zfltg}{\zfltboxg}
+\zdeffloat{\zflth}{\zfltboxh}
+\zdeffloat{\zflti}{\zfltboxi}
+\zdeffloat{\zfltj}{\zfltboxj}
+\zdeffloat{\zfltk}{\zfltboxk}
+\zdeffloat{\zfltl}{\zfltboxl}
+\zdeffloat{\zfltm}{\zfltboxm}
+\zdeffloat{\zfltn}{\zfltboxn}
+\zdeffloat{\zflto}{\zfltboxo}
+\zdeffloat{\zfltp}{\zfltboxp}
+\zdeffloat{\zfltq}{\zfltboxq}
+\zdeffloat{\zfltr}{\zfltboxr}
+\zdeffloat{\zflts}{\zfltboxs}
+\zdeffloat{\zfltt}{\zfltboxt}
+\zdeffloat{\zfltu}{\zfltboxu}
+\zdeffloat{\zfltv}{\zfltboxv}
+\zdeffloat{\zfltw}{\zfltboxw}
+\zdeffloat{\zfltx}{\zfltboxx}
+\zdeffloat{\zflty}{\zfltboxy}
+\zdeffloat{\zfltz}{\zfltboxz}
+
+% There is an insert class for each of the two places where floats
+% can go.
+
+\defineinsert{\ztopcolinsert} % Floats at top of column.
+\count\ztopcolinsert = 1000
+\dimen\ztopcolinsert = \maxdimen
+\skip\ztopcolinsert = 0pt
+\defineinsert{\zbotcolinsert} % Floats at bottom of column.
+\count\zbotcolinsert = 1000
+\dimen\zbotcolinsert = \maxdimen
+\skip\zbotcolinsert = 0pt
+
+
+% We need a dimension register to capture box depths.
+
+\definedimen{\zfloatdp}{0pt}
+
+% Float Types
+% ----- -----
+
+
+\setlist \zfloattypelist = {}
+
+
+\def \definefloattype #1#2#3{% {type}{toc-level}{association}
+ \if \emptyargp{#3}%
+ \withname\definecount{\float#1number}{0}%
+ \withname\declaresnapitem{\float#1number}%
+ \else
+ \edef \znext {%
+ \global\withname\let{\float#1number}=\name{\float#3number}}%
+ \znext
+ \fi
+ \withname\gdef{\zflt#1lvl}{#2}%
+ \append{#1}{\zfloattypelist}}
+
+
+\def \resetfloatnumbers {%
+ \maplist{\global\name{\float##1number}=0\relax}{\zfloattypelist}}
+
+
+% Predefined float types (don't forget an index locator for each one).
+
+\definefloattype{algorithm}{101}{}
+\definefloattype{figure}{102}{}
+\definefloattype{table}{103}{}
+\definefloattype{listing}{104}{}
+\definefloattype{sidebar}{105}{}
+
+% Float Block
+% ----- -----
+
+
+\defineblock{\float}{\endfloat}{\false}{}
+
+%~block float Type
+% \aboveskip = glue % Space b/b above float.
+% \def \beginformat {...} % Beginning of float formatter.
+% \belowskip = glue % Space b/b below float.
+% \def \comptextformat {...} % Composite number text formatter.
+% \continue = integer % Continued or continuation.
+% \def \endformat {...} % End of float formatter.
+% \leftindent = dimen % Horizontal fudge for all floats.
+% \pageplacement = {...} % Overriding page placement.
+% \position = {...} % Position (see below).
+% \runners = {style} % Runners for a page of floats.
+% \topfloatfudge = dimen % Vertical fudge for topmost float.
+% \width = dimen % Explicit width for float.
+%~end
+
+\definetoks{\pageplacement}
+\definedimen{\topfloatfudge}{0pt}
+
+% These derived parameters are needed here and by \caption. They may
+% also be useful to the user.
+
+\definecount{\floatpage}{0}
+\definedimen{\floatshift}{0pt}
+\definedimen{\floatwidth}{0pt}
+
+\definecount{\zdivfltcounter}{0} % Count floats in each division.
+\definebox{\zfltbroadbox}
+
+
+% Floats are packaged up in a vbox using \vtop, so that the float box
+% has the same height as the first thing inside. This improves the
+% chances that a float at the top of a page will be positioned correctly.
+
+\def \float #1{% {type}
+ \if \undefinedp{\float#1number}%
+ \error{undefflt}{Float type `#1' has not been defined}%
+ \fi
+ \endgraf
+ \blockcantbein{\float}{\float}%
+ \blockcantbein{\float}{\multicolumn}%
+ \beginblockscope{float}%
+ \global\increment \floatdepth
+ \global\increment \zdivfltcounter
+ \whichpage{\floatpage}{zF:\the\divisionname-\the\zdivfltcounter}%
+ \def \beginformat {}% %~default soft
+ \continue = 0 %~default with
+ \def \comptextformat {}% %~default soft
+ \setflag \continuation = \false % Deprecated
+ \def \endformat {}% %~default soft
+ \leftindent = 0pt %~default soft
+ \pageplacement = {}% %~default with
+ \runners = {normal}% %~default soft
+ \zoldrunners{\normalheader\normalfooter}%
+ \width = \naturalwidth %~default soft
+ \processdesign{\float}{#1}%
+ \zsetcontinue % Handle old \continuation.
+ \if \notp{\continuationp}\global\withname\increment{\float#1number}\fi
+ \global\withname\floatnumber{\float#1number}%
+ \setcomptext{\floatcomptext}%
+ \def \zcurflttype {#1}%
+ \edef \zcurfltlvl {\name{\zflt\zcurflttype lvl}}%
+ \parindent = 0pt
+ \parrag = 0pt
+ \parskip = 0pt
+ \zparsefltpos{\the\position}%
+ \if \notp{\emptytoksp{\pageplacement}}%
+ \zparsefltpagepos{\the\pageplacement}%
+ \fi
+ \if \zfltposhere
+ \penalty \breakallowed % Synchronize main list.
+ \zparsefltpos{\the\position}% % Recalculate global stuff.
+ \if \notp{\emptytoksp{\pageplacement}}
+ \zparsefltpagepos{\the\pageplacement}%
+ \fi
+ \fi
+ \zcalcfltparams
+ \zgetfloat{\zcurfloat}%
+ \zcurfloat
+ \global\setbox \zcurfloatbox = \vtop \bgroup
+ \zpushvcontext
+ \setindentation{0pt}{0pt}%
+ \settextwidth{\floatwidth}%
+ \settaginfo{\the\floatcomptext}{}% % Set tag info without title.
+ \setsubtagnumber{0}%
+ \beginformat}
+
+\def \endfloat {%
+ \endgraf
+ \endformat
+ \global\zfloatdp = \prevdepth
+ \tagpageonly{\uniquetag{zF}{\the\zdivfltcounter}}%
+ \zpopvcontext
+ \egroup % \vtop
+ \expandafter\xdef \zcurfloat {%
+ \def \noexpand\zcurfloatid {\zcurflttype\space \the\floatnumber}%
+ \def \noexpand\zcurfloatbox {\zcurfloatbox}%
+ \zfloatdp = \the\zfloatdp
+ \aboveskip = \the\aboveskip
+ \belowskip = \the\belowskip
+ \leftindent = \the\leftindent
+ \position = {\the\position}%
+ \pageplacement = {\the\pageplacement}%
+ \runners = {\the\runners}%
+ \floatshift = \the\floatshift
+ \topfloatfudge = \the\topfloatfudge}%
+ \expandafter\append \zcurfloat{\zfloatpendq}%
+ \zschedulefloats{\znext}{\false}{\false}%
+ \if \gtrp{\znext}{99}%
+ \zfltpage{\zpenfloatpage}%
+ \fi
+ \global\decrement \floatdepth
+ \endblockscope{float}}
+
+%~ This |\float| modifier forces an alone float.
+
+\def \alonefloat {% %^modifier
+ \with{\pageplacement={\alone}}}
+
+%~ This |\float| modifier forces a bottom float.
+
+\def \bottomfloat {% %^modifier
+ \with{\pageplacement={\bottom}}}
+
+%~ This |\float| modifier forces a broadside float.
+
+\def \broadsidefloat {% %^modifier
+ \with{\pageplacement={\broadside}}}
+
+%~ This |\float| modifier forces a here float.
+
+\def \herefloat {% %^modifier
+ \with{\pageplacement={\here}}}
+
+%~ This |\float| modifier forces a separate float.
+
+\def \separatefloat {% %^modifier
+ \with{\pageplacement={\separate}}}
+
+%~ This |\float| modifier allows the float to occupy the
+%~ running head area. Any running head is deleted.
+
+\def \userharea {% %^modifier
+ \with{\runners={blind}%
+ \advance \topfloatfudge by -\headerheight}}
+
+\def \adjusttopfloatfudge #1{%
+ \global\advance \topfloatfudge by #1\relax}
+
+\def \piggybackfloat {%
+ \edef \znext {\noexpand\global\noexpand\increment
+ \name{\float\zcurflttype number}}%
+ \znext
+ \edef \znext {\floatnumber = \name{\float\zcurflttype number}}%
+ \znext}
+
+% Controlling Floats
+% ----------- ------
+
+
+% This macro is invoked at the beginning of each division.
+
+\def \zfltdivinit {%
+ \global\zdivfltcounter = 0\relax}
+
+
+\setflag \zschedflts = \true
+
+\def \deferfloats #1{% {boolean}
+ \global\setflag \zschedflts = {\notp{#1}}}
+
+
+% Scheduling Tools
+% ---------- -----
+
+
+% These counters keep track of the number of floats scheduled for the
+% current page.
+
+\definecount{\ztopcolfloats}{0} % Number of top column floats.
+\definecount{\zbotcolfloats}{0} % Number of bottom column floats.
+\definecount{\zfloatsinserted}{0} % Total number of floats.
+\definetoks{\zfltrunners} % Runners for first float on page.
+
+% This macro initializes for handling floats on a new page.
+
+\def \zfloatinit {%
+ \global\setflag \zschedflts = \true
+ \global\ztopcolfloats = 0
+ \global\zbotcolfloats = 0
+ \zfltrunners = {}}
+
+% These macros simply hide some of the details to make the \zsched*
+% macros easier to read.
+
+\def \ztallytopfloat {%
+ \if \orp{\notp{\zfltposmargonly}}{\posp{\ztopcolfloats}}%
+ \global\increment \ztopcolfloats
+ \fi}
+
+\def \zforcenewpage{%
+ \global\zfloatsinserted = 101\relax}
+
+\let \zquitscheding = \exitmaplist
+
+\def \zsetfloattall{%
+ \zmakefloatalone
+ \setflag \zfloattall = \true
+ \tracepagemakeup{Float is too tall for column; positioning `alone'.}}
+
+\def \zmakefloatalone{%
+ \setflag \zfltposalone = \true
+ \setflag \zfltposbottom = \false
+ \setflag \zfltposhereonly = \false
+ \setflag \zfltposhere = \false
+ \setflag \zfltposseparate = \false
+ \setflag \zfltpostop = \false}
+
+\def \zmakefloattop{%
+ \setflag \zfltposalone = \false
+ \setflag \zfltposbottom = \false
+ \setflag \zfltposhereonly = \false
+ \setflag \zfltposhere = \false
+ \setflag \zfltposseparate = \false
+ \setflag \zfltpostop = \true}
+
+% Float Scheduler
+% ----- ---------
+
+
+% return-count is a counter passed in by the caller that we should
+% set at the end of \zschedulefloats to indicate how
+% many floats were emitted during this call. A value
+% greater than 99 indicates that a new page should be
+% FORCED (e.g. for alone floats) by the output routine.
+% during-output? is a flag indicating that the caller is
+% part of the output routine.
+% flushing? A flag indicating whether we are flushing floats.
+
+\def \zschedulefloats #1#2#3{% {return-count}{during-output?}{flushing?}
+ \tracepagemakeup{[Scheduling \if #2floats during output%
+ \else float when encountered\fi.}%
+ \tracepagemakeup{Page total: \the\pagetotal; goal: \the\pagegoal.}%
+ % Reset our counter
+ \global\zfloatsinserted = 0
+ \if \zschedflts
+ \if \emptydefp{\zfloatpendq}%
+ \tracepagemakeup{There are no floats to be scheduled.}%
+ \else
+ \endgraf
+ \zinitfloatfit{#2}%
+ {\setflag \zschedfirstseparate = \true
+ \setflag \zschedseparateloop = \false
+ \maplist{\zschedone{#2}{#3}{##1}}{\zfloatpendq}}%
+ \fi
+ \else
+ \tracepagemakeup{Floats are deferred now.}%
+ \fi
+ \tracepagemakeup{Float scheduling complete;
+ floats inserted: \the\zfloatsinserted.]}%
+ \xdef #1{\the\zfloatsinserted}}
+
+
+\def \zschedone #1#2#3{% {during-output?}{flushing?}{\float}
+ #3%
+ \zparsefltpos{\the\position}%
+ \if \notp{\emptytoksp{\pageplacement}}
+ \zparsefltpagepos{\the\pageplacement}%
+ \fi
+ \if #2% % If flushing floats, force float
+ \setflag \zfltposbottom = \false % to a `separate'.
+ \setflag \zfltpostop = \false
+ \setflag \zfltposseparate = \true
+ \fi
+ \tracepagemakeup{Trying to schedule \zcurfloatid;
+ size: \the\ht\zcurfloatbox+\the\dp\zcurfloatbox.}%
+ \if \orp{\andp{\zfltposeven}{\oddpagep}}%
+ {\andp{\zfltposodd}{\evenpagep}}%
+ \tracepagemakeup{Float is deferred until appropriate even/odd page.}%
+ \zquitscheding
+ \else
+ \setflag \zfloatunsched = \true
+ \setflag \zfloattall = \false
+ % The following macros attempt, in order of priority, to schedule
+ % the current float. Each macro may set up state that causes
+ % the subsequent macro(s) to do nothing.
+ \zschedhereonly{#1}%
+ \zschedhere{#1}%
+ \zschedalone{#1}%
+ \zschedbroadside{#1}%
+ \zschedseparate{#1}%
+ \zschedtop{#1}%
+ \zschedbottom{#1}%
+ \if \zfloattall % Schedule as `alone'.
+ \zschedalone{#1}%
+ \fi
+ \if \zfloatunsched
+ \tracepagemakeup{Float could not be scheduled.}%
+ % This exits a \maplist call to \zschedone.
+ \zquitscheding
+ \else
+ % Remove the current float from the queue...
+ \pop{\zcurfloat}{\zfloatpendq}%
+ % ...and free up the associated data structures.
+ \expandaftertwice\zfreefloat \expandafter\zcurfloat\zcurfloatbox
+ \fi
+ \fi}
+
+% Fitting a Float
+% ------- - -----
+
+
+% These registers are used in float fitting. They contain,
+% respectively, the amount of vertical space used up by floats for
+% the current page and the maximum space available for floats.
+
+\definedimen{\zfloatpageused}{0pt}
+\definedimen{\zfloatmaxavail}{0pt}
+
+
+% Macro to initialize the above parameters (called in \zschedulefloats).
+
+\def\zinitfloatfit #1{% {during-output?}
+ \if #1
+ \zfloatpageused = 0pt
+ % Effectively: zfloatmaxavail = (100-mintextpercent) * vsize
+ \calculate \tcounta = {100,-,\mintextpercent}%
+ \calculate \zfloatmaxavail = {\vsize,P,\tcounta}%
+ \else
+ % Effectively: zfloatpageused = max(pagetotal, vsize * mintextpercent)
+ \calculate \zfloatpageused = {\vsize,P,\mintextpercent,X,\pagetotal}%
+ \zfloatmaxavail = \pagegoal
+ \fi}
+
+
+% The spacing above and below a float is fairly complicated.
+% In this table, h is the height of the float, d is the depth.
+%
+% Position Sequence Above Below
+%
+% \alone only \topskip - h + none
+% \topfloatfudge
+% \bottom first \aboveskip - h none
+% rest min(\aboveskip, none
+% \belowskip) - h
+%
+% \separate first \topskip - h + none
+% \topfloatfudge
+% rest min(\aboveskip, none
+% \belowskip) - h
+% \top first \topskip - h + \belowskip - \topskip - d
+% \topfloatfudge
+% rest min(\aboveskip, \belowskip - \topskip - d
+% \belowskip) - h
+
+
+% Here and broadside floats are handled differently, below in \zfitfloathere
+% and \zfitfloatbroadside
+
+\def \zfitfloat #1#2#3#4#5{% {result-flag}{top?}{aboveskip-first}
+ % {aboveskip-rest}{belowskip}
+ {\if \zfltposmargonly
+ \tcounta = 0 % Margin float should act as first one.
+ \else
+ \tcounta = \if #2\ztopcolfloats \else \zbotcolfloats \fi
+ \fi
+ \zskipa = \if \zerop{\tcounta}#3\else #4\fi
+ \advance \zskipa by -\ht\zcurfloatbox
+ \if \andp{#2}{\zerop{\tcounta}}\advance \zskipa by \topfloatfudge \fi
+ \tdimena = \zskipa
+ \advance \tdimena by \ht\zcurfloatbox
+ \advance \tdimena by \dp\zcurfloatbox
+ \tdimenb = #5\advance \tdimena by \tdimenb
+ \tdimenc = \zfloatpageused
+ \if \notp{\zfltposmargonly}\advance \tdimenc by \tdimena \fi
+ \tracepagemakeup{Requires: \the\tdimena;
+ available: \the\zfloatmaxavail;
+ used: \the\zfloatpageused.}%
+ \if \dimlssp{\tdimenc}{\zfloatmaxavail}%
+ \if \andp{\notp{#2}}{\zfltposmargonly}%
+ \insert \zbotcolinsert {%
+ \vbox to 0pt{%
+ \vss
+ \moveright \floatshift \box\zcurfloatbox
+ \vskip -\dp\zcurfloatbox}}%
+ \else
+ \insert \if #2\ztopcolinsert \else \zbotcolinsert \fi {%
+ \vskip \zskipa
+ \moveright \floatshift \box\zcurfloatbox
+ \nobreak
+ \if \zfltposmargonly
+ \vskip \tdimenb
+ \nobreak
+ \vskip -\tdimena
+ \else
+ \vskip #5\relax
+ \fi}%
+ \fi
+ \if \emptytoksp{\zfltrunners}%
+ \global\zfltrunners = \expandafter{\the\runners}%
+ \fi
+ \global\increment \zfloatsinserted
+ \global\zfloatpageused = \tdimenc
+ \global\setflag #1= \true
+ \else
+ \global\setflag #1= \false
+ \fi}}
+
+\def \zfitfloathere #1#2#3{% {result-flag}{aboveskip}{belowskip}
+ {\tdimena = #2\relax
+ \advance \tdimena by \dp\zcurfloatbox
+ \advance \tdimena by #3\relax
+ \tracepagemakeup{Requires: \the\tdimena;
+ page total: \the\pagetotal;
+ page goal: \the\pagegoal.}%
+ \advance \tdimena by \pagetotal
+ \if \dimlssp{\tdimena}{\pagegoal}%
+ \bbskipabove{\breaknever}{#2}%
+ \fakepar
+ \moveright \floatshift \box\zcurfloatbox
+ \prevdepth = \zfloatdp
+ \bbskipbelow{\breakallowed}{#3}%
+ \global\increment \zfloatsinserted
+ \global\setflag #1= \true
+ \else
+ \global\setflag #1= \false
+ \fi}}
+
+\def \zfitfloatbroadside {%
+ {% We know there are no other floats on the the topcolumn when
+ % this is called (by \zschedbroadside only) and we don't have to
+ % worry about fixing up the vertical position at the end of the
+ % page.
+ %
+ % Compute the space required
+ % Start with the topskip
+ \tdimena = \topfloatfudge
+ % Add the *width* (since the box will be rotated)
+ \advance \tdimena by \wd\zcurfloatbox
+ \tracepagemakeup{Requires: \the\tdimena;
+ broadside floats always fit.}%
+ \insert \ztopcolinsert {%
+ % vskip the top float fudge
+ \vskip \topfloatfudge
+ % save the width for unskipping later
+ \tdimenb = \wd\zcurfloatbox
+ % vskip the *width* of the box to do the position translation
+ % that we can't do with PostScript
+ \vskip \tdimenb
+ % Put our hbox in a vbox, so we can "lower" it rather than move
+ % it right (since it will be rotated)
+ \global\setbox\zfltbroadbox = \vbox{%
+ \vskip\floatshift % replaces \moveright in other floats
+ \box\zcurfloatbox}%
+ \rotatebox{\zfltbroadbox}{90}%
+ % Undo vertical skip so that insert doesn't cause additional page
+ \vskip -\tdimenb}%
+ \if \emptytoksp{\zfltrunners}%
+ \global\zfltrunners = \expandafter{\the\runners}%
+ \fi
+ \global\increment \zfloatsinserted
+ \global\zfloatpageused = \tdimena}}
+
+% Individual Schedulers
+% ---------- ----------
+
+
+% This is a temporary register used in calls to \zfitfloat where the
+% fit needs to take into account more than one skip value (such as
+% both the \aboveskip and \belowskip). In that case this dimen is
+% used as a temp to hold the sum of the skip values.
+
+\defineskip{\zfloatabove}{0pt}
+\defineskip{\zfloatbelow}{0pt}
+\definedimen{\zfloatextraskip}{0pt}
+
+
+% This scheduler is called for floats with position `here' and no others.
+
+\def\zschedhereonly #1{% {during-output?}
+ \if \andp{\zfloatunsched}{\zfltposhereonly}%
+ \tracepagemakeup{Float is to be positioned `here' only.}%
+ \if \zschedseparateloop
+ \tracepagemakeup{Making up a page of separates; quit.}%
+ \zforcenewpage
+ \zquitscheding
+ \else
+ \if #1% during output:
+ \tracepagemakeup{Float moved to top of this page.}%
+ \zmakefloattop
+ \else % when encountered:
+ \if \posp{\zbotcolfloats}%
+ \error{hereonlybot}{Cannot position float `here'; already floats
+ at bottom.}%
+ \else\if \dimzerop{\pagetotal}%
+ \tracepagemakeup{Float at top of column: schedule as `top' float.}%
+ \zmakefloattop
+ \else
+ \zfitfloathere{\zfloatfits}{\aboveskip}{\belowskip}%
+ \if \zfloatfits
+ \tracepagemakeup{Float inserted here.}%
+ \setflag \zfloatunsched = \false
+ \else
+ \tracepagemakeup{Float does not fit here.}%
+ \zforcenewpage
+ \zquitscheding
+ \fi
+ \fi\fi
+ \fi
+ \fi
+ \fi}
+
+
+% This scheduler is called for floats with position `here' along with at
+% least one other page position.
+
+\def\zschedhere #1{% {during-output?}
+ \if \andp{\zfloatunsched}{\zfltposhere}%
+ \tracepagemakeup{Float can be positioned `here'.}%
+ \if \zschedseparateloop
+ \tracepagemakeup{Making up a page of separates; quit.}%
+ \zforcenewpage
+ \zquitscheding
+ \else
+ \if #1% during output:
+ \relax
+ \else % when encountered:
+ \if \posp{\zbotcolfloats}%
+ \tracepagemakeup{There are already floats positioned `bottom'.}%
+ \else\if \dimzerop{\pagetotal}%
+ \tracepagemakeup{Float at top of column: schedule as `top' float.}%
+ \zmakefloattop
+ \else
+ \zfitfloathere{\zfloatfits}{\aboveskip}{\belowskip}%
+ \if \zfloatfits
+ \tracepagemakeup{Float inserted here.}%
+ \setflag \zfloatunsched = \false
+ \else
+ \tracepagemakeup{Float does not fit here.}%
+ \fi
+ \fi\fi
+ \fi
+ \fi
+ \fi}
+
+
+\def \zschedalone #1{% {during-output?}
+ \if \andp{\zfloatunsched}{\zfltposalone}%
+ \tracepagemakeup{Float can be positioned `alone'.}%
+ \if \zschedseparateloop
+ \tracepagemakeup{Making up a page of separates; quit.}%
+ \zforcenewpage
+ \zquitscheding
+ \else
+ \if \orp{#1}{\dimzerop{\pagetotal}}%
+ \if \firstcolumnp % building new page
+ \if \zerop{\zfloatsinserted}% no floats on this page, yet
+ \dp\zcurfloatbox = 0pt % Make it fit.
+ \zfitfloat{\zfloatfits}{\true}{\topskip}{999pt}{0pt}%
+ \if \zfloatfits
+ \ztallytopfloat
+ \tracepagemakeup{Inserted on a page by itself.}%
+ \zforcenewpage
+ \setflag \zfloatunsched = \false
+ \zquitscheding
+ \fi
+ \else % wait for next time
+ \tracepagemakeup{Already floats in this column; quit.}%
+ \zquitscheding
+ \fi
+ \else% still in the middle of a page
+ \tracepagemakeup{Not in first column of page; quit.}%
+ \zquitscheding
+ \fi
+ \else % As encountered, and page not empty.
+ \tracepagemakeup{Must wait for new page; quit.}%
+ \zquitscheding
+ \fi
+ \fi
+ \fi}
+
+\def \zschedbroadside #1{% {during-output?}
+ \if \andp{\zfloatunsched}{\zfltposbroadside}%
+ \tracepagemakeup{Float can be positioned `broadside'.}%
+ \if \zschedseparateloop
+ \tracepagemakeup{Making up a page of separates; quit.}%
+ \zforcenewpage
+ \zquitscheding
+ \else
+ \if \orp{#1}{\dimzerop{\pagetotal}}%
+ \if \firstcolumnp % building new page
+ \if \zerop{\zfloatsinserted}% no floats on this page, yet
+ % Broadside floats "always" fit. The output will have to be
+ % inspected.
+ \zfitfloatbroadside
+ \ztallytopfloat
+ \tracepagemakeup{Inserted on a page by itself.}%
+ \zforcenewpage
+ \setflag \zfloatunsched = \false
+ \zquitscheding
+ \else % wait for next time
+ \tracepagemakeup{Already floats on this page; quit.}%
+ \zquitscheding
+ \fi
+ \else% still in the middle of a page
+ \tracepagemakeup{Not in first column of page; quit.}%
+ \zquitscheding
+ \fi
+ \else % As encountered, and page not empty.
+ \tracepagemakeup{Must wait for new page; quit.}%
+ \zquitscheding
+ \fi
+ \fi
+ \fi}
+
+
+\def\zschedseparate #1{% {during-output?}
+ \if \andp{\zfloatunsched}{\zfltposseparate}%
+ \tracepagemakeup{Float can be positioned `separate'.}%
+ % If a separate float is called when encountered, we don't do anything.
+ \if #1% during output
+ \if \firstcolumnp % building a new page
+ \if \zschedfirstseparate
+ \if \zerop{\zfloatsinserted}% no floats on this page, yet
+ \zfloatmaxavail = \vsize % Entire page is available now.
+ \zfitfloat{\zfloatfits}{\true}{\topskip}{999pt}{0pt}%
+ \if \zfloatfits
+ \ztallytopfloat
+ \setflag \zfloatunsched = \false
+ \zforcenewpage % This is a page of separates now.
+ \tracepagemakeup{Inserted at the top of a new page.}%
+ \setflag \zschedfirstseparate = \false
+ \setflag \zschedseparateloop = \true
+ \else
+ \zsetfloattall
+ \fi
+ \else % wait for next time
+ \tracepagemakeup{Page already has other floats on it.}%
+ \zquitscheding
+ \fi
+ \else % Subsequent separates.
+ \zfloatabove = \if \dimlssp{\aboveskip}{\belowskip}\aboveskip
+ \else \belowskip \fi
+ \zfitfloat{\zfloatfits}{\true}{999pt}{\zfloatabove}{0pt}%
+ \if \zfloatfits
+ \ztallytopfloat
+ \setflag \zfloatunsched = \false
+ \tracepagemakeup{Inserted on a page with other separates.}%
+ \else
+ \zquitscheding
+ \tracepagemakeup{Does not fit on this page; start new page.}%
+ \fi
+ \fi
+ \else% still in the middle of a page
+ \tracepagemakeup{Must wait for new page; quit;}%
+ \zquitscheding
+ \fi
+ \else% when encountered
+ \tracepagemakeup{Must wait for new page; quit.}%
+ \zquitscheding
+ \fi
+ \fi}
+
+
+\def\zschedtop#1{% {during-output?}
+ \if \andp{\andp{\zfloatunsched}{\zfltpostop}}
+ {\orp{\notp{\zfltposfollow}}{#1}}%
+ \tracepagemakeup{Float can be positioned `top'.}%
+ \if \zschedseparateloop
+ \tracepagemakeup{Making up a page of separates; quit.}%
+ \zforcenewpage
+ \zquitscheding
+ \else
+ \if \lssp{\ztopcolfloats}{\maxtopcolumnfloats}%
+ \zfloatabove = \if \dimlssp{\aboveskip}{\belowskip}\aboveskip
+ \else \belowskip \fi
+ \advance \zfloatabove by -\belowskip
+ \advance \zfloatabove by \topskip
+ \zfloatbelow = \belowskip
+ \tdimena = \topskip
+ \advance \zfloatbelow by -\tdimena
+ \advance \zfloatbelow by -\zfloatdp
+ \zfitfloat{\zfloatfits}{\true}{\topskip}{\zfloatabove}{\zfloatbelow}%
+ \if \zfloatfits
+ \ztallytopfloat
+ \tracepagemakeup{Inserted at top of column.}%
+ \setflag \zfloatunsched = \false
+ \else
+ \if \andp{#1}{\zerop{\zfloatsinserted}}\zsetfloattall \fi
+ \fi
+ \fi
+ \fi
+ \fi}
+
+\def \zschedbottom#1{% {during-output?}
+ \if \andp{\zfloatunsched}{\zfltposbottom}%
+ \tracepagemakeup{Float can be positioned `bottom'.}%
+ \if \zschedseparateloop
+ \tracepagemakeup{Making up a page of separates; quit.}%
+ \zforcenewpage
+ \zquitscheding
+ \else
+ \if \lssp{\zbotcolfloats}{\maxbottomcolumnfloats}%
+ \zfloatbelow = \if \dimlssp{\aboveskip}{\belowskip}\aboveskip
+ \else \belowskip \fi
+ \zfitfloat{\zfloatfits}{\false}{\aboveskip}{\zfloatbelow}{0pt}%
+ \if \zfloatfits
+ \if \notp{\zfltpostopafterbot}%
+ \global\ztopcolfloats = \maxtopcolumnfloats
+ \fi
+ \global\increment \zbotcolfloats
+ \tracepagemakeup{Inserted at bottom of column.}%
+ \setflag \zfloatunsched = \false
+ \else
+ \if \andp{#1}{\zerop{\zfloatsinserted}}\zsetfloattall \fi
+ \fi
+ \fi
+ \fi
+ \fi}
+
+% Captions
+% --------
+
+
+\defineblock{\caption}{\endcaption}{\false}{}
+
+%~block caption Type
+% \aboveskip = glue % Space b/b above caption.
+% \setflag \allowintoc = flag % Allow caption in ToC.
+% \belowskip = glue % Space b/b below caption.
+% \captionfudge = dimen % Fudge for \aboveskip.
+% \def \comptextformat {...} % (No longer used with captions.)
+% \difficulty = integer % Level of difficulty.
+% \leftindent = glue % Left indentation.
+% \legendfont = {...} % Font for optional legend.
+% \def \legendformat ##1{...} % Legend formatter.
+% \numberfont = {...} % Font for float number.
+% \parindent = dimen % Paragraph indent.
+% \parrag = dimen % Paragraph raggedness.
+% \parskip = glue % Paragraph skip.
+% \position = {...} % Position (see below).
+% \rightindent = glue % Right indentation.
+% \style = {...} % Heading style.
+% \titlefont = {...} % Font for caption title.
+% \def \titleformat ##1{...} % Title formatter.
+% \width = dimen % Width of caption text.
+%~end
+
+\definedimen{\captionfudge}{0pt}
+\definetoks{\legendfont}
+
+\definebox{\zcapbox}
+\definedimen{\zcapshift}{0pt}
+
+%~ This marker indicates that the following text is the legend or
+%~ credit for the caption.
+
+\definemarker{\legend}
+
+
+\def \caption #1{% {title with optional \legend}
+ \blockmustbein{\caption}{\float}%
+ \blockcantbein{\caption}{\caption}%
+ \beginblockscope{caption}%
+ \global\increment \captiondepth
+ \captionfudge = 0pt %~default with
+ \def \comptextformat {}% %~default hard
+ \style = {Initial cap/lowercase}% %~default soft
+ \difficulty = 0 %~default with
+ \processdesign{\caption}{\zcurflttype}%
+ \global\increment \captionnumber
+ \if \notp{\emptydefp{\comptextformat}}%
+ \error{capcomptext}{The \string\comptextformat\space parameter is no
+ longer used in captions}
+ \fi
+ \captionformat #1\legend\zmark
+ \if \andp{\allowintoc}{\notp{\continuationp}}\zcaptoc #1\legend\zmark \fi
+ \endcaption
+ \zcaptag #1\legend\zmark}% % Reset tag info with title.
+
+\def \endcaption {%
+ \global\decrement \captiondepth
+ \endblockscope{caption}}
+
+\def \captionformat #1\legend#2\zmark{%
+ \the\numberfont
+ \setbox\zcapbox = \vtop{%
+ \zpushvcontext
+ \setindentation{\leftindent}{\rightindent}%
+ \settextwidth{\width}%
+ \setparrag{\parrag}%
+ \if \emptyargp{#2}%
+ \titleformat{#1}%
+ \else
+ \let \legend = \relax % So it won't interfere with formatting.
+ \titleformat{#1\the\legendfont \legendformat{#2}}%
+ \fi
+ \endgraf
+ \global\zfloatdp = \prevdepth
+ \zpopvcontext}%
+ \zparsecappos{\the\position}%
+ \zcalccapitems
+ \bbskipabove{\breaknever}{\aboveskip}%
+ \noindent \kern \zcapshift \box\zcapbox \par
+ \prevdepth = \zfloatdp
+ \bbskipbelow{\breaknever}{\belowskip}}
+
+\def \zcaptoc #1\legend#2\zmark{%
+ \tocentry{\the\floatcomptext}{#1}{\zcurfltlvl}}
+
+\def \zcaptag #1\legend#2\zmark{%
+ \settaginfo{\the\floatcomptext}{#1}}
+
+% Position Handling
+% -------- --------
+
+
+% This macro sets up variables that specify the position of a float,
+% according to the \position design parameter:
+%
+% \alone Place float on a page by itself.
+% \anypage Place float on any page.
+% \any (synonym for \anypage)
+% \bottom Place float at the bottom of a page.
+% \broadside Place float broadside (alone, rotated 90 degrees).
+% \evenpage Place float on an even page.
+% \follow Float must follow its position in the text.
+% \here Place float exactly where it appears.
+% \ifevenpage Use next position only on even page.
+% \ifoddpage Use next position only on odd page.
+% \leftmargin Shift float to left margin.
+% \margin Same as \leftmargin.
+% \marginonly Float fits in the margin and does not occupy any
+% vertical space on the page.
+% \nofollow Float need not follow its position in the text.
+% \oddpage Place float on an odd page.
+% \outsidemargin Shift float to outside margin.
+% \rightmargin Shift float to right margin.
+% \separate Place float on a page with floats only.
+% \textarea Leave float at left edge of text area.
+% \text (synonym for \textarea)
+% \top Place float at the top of a page.
+% \topafterbottom Okay to schedule \top float after \bottom.
+
+
+\definecount{\zfltposshift}{0}
+
+
+\def \zparsefltpos #1{% {options...}
+ {\zclearfltpagepos
+ \global\setflag \zfltposmargonly = \false
+ \global\zfltposshift = 0\relax
+ \zsetupfltpageopts
+ \def \ifevenpage ##1{\if \evenp{\floatpage}##1\fi}%
+ \def \ifoddpage ##1{\if \oddp{\floatpage}##1\fi}%
+ \def \leftmargin {\global\zfltposshift=1\relax}%
+ \let \margin = \leftmargin
+ \def \marginonly {\global\setflag\zfltposmargonly=\true}%
+ \def \outsidemargin{\ifevenpage{\leftmargin}\ifoddpage{\rightmargin}}%
+ \def \rightmargin {\global\zfltposshift=2\relax}%
+ \def \textarea {\global\zfltposshift=0\relax}%
+ \let \text = \textarea
+ \global\floatpage = \floatpage
+ #1%
+ \global\setflag \zfltposhereonly = \zfltposhere
+ \global\setflag \zfltposok = \zfltposhere
+ \if \orp{\zfltposalone}
+ {\orp{\zfltposbottom}
+ {\orp{\zfltposbroadside}
+ {\orp{\zfltposseparate}
+ {\zfltpostop}}}}%
+ \global\setflag \zfltposhereonly = \false
+ \global\setflag \zfltposok = \true
+ \fi
+ \if \zfltposhereonly \setflag \zfltposhere = \false \fi
+ \if \notp{\zfltposok}%
+ \warning{nofloatpos}{No page position has been specified for a float}%
+ \global\setflag \zfltposalone = \true
+ \fi}}
+
+\def \zparsefltpagepos #1{% {options...}
+ {\zclearfltpagepos
+ \zsetupfltpageopts
+ #1%
+ \global\setflag \zfltposhereonly = \zfltposhere
+ \if \orp{\zfltposalone}
+ {\orp{\zfltposbottom}{\orp{\zfltposseparate}{\zfltpostop}}}%
+ \global\setflag \zfltposhereonly = \false
+ \fi
+ \if \zfltposhereonly \global\setflag \zfltposhere = \false \fi}}
+
+\def \zclearfltpagepos {%
+ \global\setflag \zfltposalone = \false
+ \global\setflag \zfltposbottom = \false
+ \global\setflag \zfltposbroadside = \false
+ \global\setflag \zfltposeven = \false
+ \global\setflag \zfltposfollow = \false
+ \global\setflag \zfltposhere = \false
+ \global\setflag \zfltposodd = \false
+ \global\setflag \zfltposseparate = \false
+ \global\setflag \zfltpostop = \false
+ \global\setflag \zfltpostopafterbot = \false}
+
+\def \zsetupfltpageopts {%
+ \def \alone {\global\setflag\zfltposalone=\true}%
+ \def \anypage {\global\setflag\zfltposeven=\false
+ \global\setflag\zfltposodd=\false}%
+ \let \any = \anypage
+ \def \bottom {\global\setflag\zfltposbottom=\true}%
+ \def \broadside {\global\setflag\zfltposbroadside=\true}%
+ \def \evenpage {\global\setflag\zfltposeven=\true}%
+ \def \follow {\global\setflag\zfltposfollow=\true}%
+ \def \here {\global\setflag\zfltposhere=\true}%
+ \def \nofollow {\global\setflag\zfltposfollow=\false}%
+ \def \oddpage {\global\setflag\zfltposodd=\true}%
+ \def \separate {\global\setflag\zfltposseparate=\true}%
+ \def \top {\global\setflag\zfltpostop=\true}%
+ \def \topafterbottom {\global\setflag\zfltpostopafterbot=\true}}
+
+\def \zcalcfltparams {%
+ \floatshift = 0pt\relax
+ % Set \floatshift
+ \ifcase \zfltposshift
+ \relax
+ \or
+ \floatshift = \if \evenp{\floatpage}-\evenlefttextmargin
+ \else -\oddlefttextmargin \fi \relax
+ \or
+ \floatshift = \textmeasure
+ \else
+ \zzerror{Invalid value for float `\string\zfltposshift'}%
+ \fi
+ \advance \floatshift by \leftindent
+
+ % Set \floatwidth. Default of \naturalwidth is handled differently
+ % for broadsides than for non-broadsides. If \width not default, use
+ % it without modification.
+
+ \if \dimeqlp{\width}{\naturalwidth}%
+ \if \zfltposbroadside
+ \floatwidth = \textareaheight \relax
+ \else
+ \floatwidth = \textmeasure \relax
+ \ifcase \zfltposshift
+ \relax
+ \or
+ \advance \floatwidth by -\floatshift
+ \or
+ \floatwidth = \if \evenp{\floatpage}\evenrighttextmargin
+ \else \oddrighttextmargin \fi \relax
+ \else
+ \zzerror{Invalid value for float `\string\zfltposshift'}%
+ \fi
+ \fi
+ \else
+ \floatwidth = \width \relax
+ \fi}
+
+
+% This macro sets up variables that specify the position of a caption,
+% according to the \position design parameter:
+%
+% \above Caption is placed above the figure.
+% \below Caption is placed below the figure.
+% \follow Caption follows left edge of float.
+% \ifevenpage Use next position only on even page.
+% \ifoddpage Use next position only on odd page.
+% \leftmargin Force caption in left margin.
+% \margin Same as \leftmargin
+% \outsidemargin Shift caption to outside margin.
+% \rightmargin Force caption in right margin.
+% \rise Caption rises up from bottom of figure.
+% \separate Caption is separate from figure.
+% \sink Caption sinks down from top of figure.
+% \textarea Force caption at left edge of text area.
+% \text (synonym for \textarea)
+% \textarearight Force caption at right edge of text area.
+% \textright (synonym for \textarearight)
+
+
+\definecount{\zcapposshift}{0}
+\definecount{\zcapposvflow}{0}
+
+\def \zparsecappos #1{% {options...}
+ {\global\setflag \zcapposabove = \true
+ \global\zcapposvflow = 0\relax
+ \global\zcapposshift = 0\relax
+ \def \above {\global\setflag\zcapposabove=\true}%
+ \def \below {\global\setflag\zcapposabove=\false}%
+ \def \follow {\global\zcapposshift=4\relax}%
+ \def \ifevenpage ##1{\if \evenp{\floatpage}##1\fi}%
+ \def \ifoddpage ##1{\if \oddp{\floatpage}##1\fi}%
+ \def \leftmargin {\global\zcapposshift=1\relax}%
+ \let \margin = \leftmargin
+ \def \outsidemargin {\ifevenpage{\leftmargin}\ifoddpage{\rightmargin}}%
+ \def \rightmargin {\global\zcapposshift=2\relax}%
+ \def \rise {\global\zcapposvflow=1\relax}%
+ \def \separate {\global\zcapposvflow=0\relax}%
+ \def \sink {\global\zcapposvflow=2\relax}%
+ \def \textarea {\global\zcapposshift=0\relax}%
+ \let \text = \textarea
+ \def \textarearight {\global\zcapposshift=3\relax}%
+ \let \textright = \textarearight
+ #1}}
+
+\def \zcalccapitems {%
+ \ifcase \zcapposshift
+ \zcapshift = 0pt
+ \or
+ \zcapshift = \if \evenp{\floatpage}-\evenlefttextmargin
+ \else -\oddlefttextmargin \fi \relax
+ \or
+ \zcapshift = \textmeasure
+ \or
+ \zcapshift = \textmeasure
+ \advance \zcapshift by -\wd\zcapbox
+ \or
+ \zcapshift = \floatshift
+ \else
+ \zzerror{Invalid value for caption `\string\zcapposshift'}%
+ \fi
+ \advance \zcapshift by -\floatshift
+ % Captions in broadsides *always* follow, i.e. \zcapshift is 0pt
+ \if \zfltposbroadside
+ \zcapshift = 0pt\relax
+ \fi
+ \ifcase \zcapposvflow
+ \relax
+ \or
+ \forcenextbbskip
+ \aboveskip = -\dp\zcapbox
+ \advance \aboveskip by \zfloatdp
+ \advance \aboveskip by \captionfudge
+ \or
+ \advance \belowskip by -\dp\zcapbox
+ \advance \belowskip by -\captionfudge
+ \else
+ \zzerror{Invalid value for caption `\string\zcapposvflow'}%
+ \fi}