% \iffalse %% %% (C) Copyright 1999-2000 Frank Mittelbach, David Carlisle, Chris Rowley %% All rights reserved. %% %% Not for general distribution. In its present form it is not allowed %% to put this package onto CD or an archive without consulting the %% the authors. %% % \fi % % \begin{macrocode} \def\@tempa#1: #2.dtx,v #3 #4 #5 #6 #7${ \ProvidesPackage{#2}[#4 #3 #5 #6]} \@tempa$Id: xo-or.dtx,v 1.53 2000/08/11 07:14:25 latex3 Exp $ % \end{macrocode} % % \subsection{A flowchart of the algorithm} % % Several output routines are employed. Output routines (that is, % macros to be used as the sole content of the primitive |\output| % register) are named xxx@or. Typically a companion macro named % setup@xxx is called to initialise the state (typically setting % vsize) and to assign |\output|. % % % [The flow chart has be cut into pieces and individual pieces are % shown below.] % % ^^A \input{xo-flow-chart.sty} ^^A .sty to ease updating % % % % Ignore white space in this package. % \begin{macrocode} \IgnoreWhiteSpace % \end{macrocode} % % % % % \subsection{General helper Routines} % % \begin{macro}{\@gobblethree} % Get rid of three tokens or brace groups. % \begin{macrocode} \long\def\@gobblethree#1#2#3{} % \end{macrocode} % \end{macro} % % \begin{macro}{\xin@} % Like |\in@| but with both args (which have to be single tokens!) % expanded. Should be replaced by a proper interface. % \begin{macrocode} \def\xin@#1#2{% % expanded once: \expandafter\def\expandafter\in@@\expandafter##\expandafter1#1##2##3\in@@{% \ifx\in@##2\in@false\else\in@true\fi}% \expandafter\expandafter\expandafter\in@@\expandafter#2#1\in@\in@@} % \end{macrocode} % \end{macro} % % % \begin{macro}{\gincrement@num} % Globally increment a ``number macro'' by one. % \begin{macrocode} \def\gincrement@num#1 { % \end{macrocode} % We don't want to modify |\count@| here as it might hold some % important data so we do everything in a group. % \begin{macrocode} \begingroup \count@#1 \advance\count@\@ne \xdef#1{\the\count@} \endgroup } % \end{macrocode} % \end{macro} % % % \begin{macro}{\gdecrement@num} % Globally decrement a ``number macro'' by one. % \begin{macrocode} \def\gdecrement@num#1 { \begingroup \count@#1 \advance\count@\m@ne \xdef#1{\the\count@} \endgroup } % \end{macrocode} % \end{macro} % % % % \begin{macro}{\split@skip} % \begin{macro}{\check@for@fil} % \begin{macro}{\get@plus@part} % \begin{macro}{\get@minus@part} % |\split@skip| takes four aguments: a template key name (for error % recovery), a skip specification (e.g., either the value of a skip % register via |\the|\meta{register}, or a macro holding the % information, or the specification directly), and two dimen % registers. The skip specification is taken apart and the first % dimen register receives ``plus'' part and the second the % ``minus'' part. If the specification contains any |fil| parts an % error is generated since these values can't be assigned to a % dimen register. % \begin{macrocode} \begingroup % \end{macrocode} % We employ the |\lowercase| trick to get certain letters with % |\catcode| 12 since we have to scan for them (they are what % |\the| outputs. So if we say |MINUS| below we get |minus| but all % |\catcode|d 12. % \begin{macrocode} \catcode`\M=12 \catcode`\I=12 \catcode`\N=12 \catcode`\U=12 \catcode`\S=12 % \end{macrocode} % We need |p| with |\catcode| 12 to scan for |pt| but we also need % |P| with |\catcode| 11 to be able to say |\PackageError|. So we % claim lowecase of |Z| is |p| and then say |ZT| and |ZLUS| below. % \begin{macrocode} \catcode`\Z=12 \lccode`\Z=`\p \catcode`\T=12 % \end{macrocode} % And we need to scan for |FIL|: % \begin{macrocode} \catcode`\L=12 \catcode`\F=12 % \end{macrocode} % And the error message contains uppercase |V| and |O| and we want % to retain those. % \begin{macrocode} \lccode`\V=`\V \lccode`\O=`\O % \end{macrocode} % With the above prelims we now apply |\lowercase| to all the % definitions below, which will put the correctly |\catcode|d % strings in the parsing part of the macros. % \begin{macrocode} \lowercase{ \gdef\split@skip #1#2#3#4{ % \end{macrocode} % |#2| is the skip specification. To be sure that the strings % ``plus'', ``minus'', ``pt'' are always having |\catcode| 12 we % assign it to a register first. Otherwise a user supplied string % like |1in plus .5in| wouldn't be parsable since we are only % looking for |pt| and also because in this case the |\catcode|s of % |plus| would be 11. % \begin{macrocode} \@tempskipa#2\relax % \end{macrocode} % Then we pass this on to |\check@for@fil| which will make sure % that there isn't any |fil| present and if not does the rest of % the processing. % \begin{macrocode} \expandafter\check@for@fil \the\@tempskipa FIL\relax\check@for@fil {\the\@tempskipa}{#3}{#4}{#1} } % \end{macrocode} % % \begin{macrocode} \gdef\check@for@fil #1FIL#2\check@for@fil#3#4#5#6{ \ifx\relax#2 \expandafter \get@minus@part #3MINUS 0ZT \get@minus@part{#4}{#5} \else #4\z@ #5\z@ \PackageError{template}{Value~ for~ key~ #6~ contains~ `fil(ll)'} {Only~ finite~ minus~ or~ plus~ parts~ are~ allowed~ for~ this~ key.} \fi } % \end{macrocode} % % \begin{macrocode} \gdef\get@plus@part #1ZLUS#2ZT#3\get@plus@part#4{ #4=#2pt\relax } % \end{macrocode} % % \begin{macrocode} \gdef\get@minus@part #1MINUS#2ZT#3\get@minus@part#4#5{ \get@plus@part #1ZLUS 0ZT\get@plus@part{#4} #5=#2pt\relax } } \endgroup % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % % % % % % % % \subsection{Special Output Routine Penalties} % % % \begin{macro}{\output@collect@penalty} % Special penalty marking the point at which the collection OR ended. % \begin{macrocode} \mathchardef\output@collect@penalty=20202 % \end{macrocode} % \end{macro} % % \begin{macro}{\output@balance@penalty} % Special penalty marking the point at which the collection OR % should end collection because we want to balance the material. % \begin{macrocode} \mathchardef\output@balance@penalty=10010 % \end{macrocode} % \end{macro} % % % Other special penalties are inbetween -10000 and -10010. Those will % not stop the collection OR but are instead recorded along the way. % % \begin{macro}{\output@columnbreak@penalty} % Special penalty marking the point a forced column break was % requested by the user. % \begin{macrocode} \mathchardef\output@columnbreak@penalty=10005 % \end{macrocode} % \end{macro} % % \begin{macro}{\output@flush@float@penalty} % Special penalty to trigger float flushing for one or more types. % \begin{macrocode} \mathchardef\output@flush@float@penalty=10006 % \end{macrocode} % \end{macro} % % \begin{macro}{\output@here@float@penalty} % Special penalty for floats that should stay with their callout. % \begin{macrocode} \mathchardef\output@here@float@penalty=10007 % \end{macrocode} % \end{macro} % % % \begin{macro}{\output@grid@align@penalty} % Special penalty for places that should fall on the page grid. % \begin{macrocode} \mathchardef\output@grid@align@penalty=10008 % \end{macrocode} % \end{macro} % % % % % % % \subsubsection{Utilities for Special Output Routine Penalties} % % % \begin{macro}{\add@badly@guarded@penalty} % Put a special penalty into the output and guard it with a % box. The reason this macro is called |\add@badly@guarded@penalty| % is that such a box of size zero is still messing up spacing % caluclations. Why? Because when the penalty is reached on the MVL % the preceeding line has already be fully added (i.e., including % its depth). This means that \TeX{} might not reach it at all in % time! For example, if the preceeding line would be the last line % of the page the depth would not be taken into account yet, but by % the time we reach the special penalty it has been added to % |\pagetotal| and that may result in not fitting anymore onto the % page. % % A solution would be to use a box that has the same depth as its % preceeding box and a negative height so that it effectively % doesn't modify the galley length. Easy, right? The only problem % is that in case of |\vadjust| (and that is unfortunately the more % important case) we just don't know what the preceeding depth is, % since |\prevdepth| will always give us a friendly |-1000pt| in % that case (start of a vertical sub-list\ldots). % % So not so easy after all. The way out of this dilemma turned out % to be complicated and involves a lot of strange corrective % actions in the collection process, see there for a replacement of % that box and what else can go wrong if one delves into messing % around with that part of \TeX. % \begin{macrocode} \def\add@badly@guarded@penalty#1 { \ifvmode \nointerlineskip \vbox to\z@{\vss\the#1}\penalty-#1\relax \else \@bsphack \vadjust{\vbox to\z@{\vss\the#1}\penalty-#1\relax} \@esphack \fi } % \end{macrocode} % \end{macro} % % % % \begin{macro}{\add@guarded@penalty} % Put a special penalty into the output. To ensure that it doesn't % get mistakenly removed during breaking preceed it with a ``guard % box'' which is later removed again. --- Actually no longer used % but replacement isn't yet finalised.\footnote{CLEANUP!} % \begin{macrocode} \def\add@guarded@penalty#1 {\guard@box{BUG:~\string#1}\penalty-#1\relax} % \end{macrocode} % \end{macro} % % % \begin{macro}{\guard@box} % Could be moved into the previous macro. % % The way it is written (using |\prevdepth|) this can only be used % in vertical mode! We have to carry over the |\prevdepth| and % append the box without adding any additional interline % space. Without it one gets nasty extra glue blobs of height % |\baselineskip| somewhere in the output. % \begin{macrocode} \def\guard@box#1{ \dimen@\prevdepth \nointerlineskip \vbox to0pt{\vss \rlap{#1}\kern\z@} \prevdepth\dimen@ } % \end{macrocode} % Better implementation? The above is wrong!\footnote{FIX!} % \begin{macrocode} \def\guard@box#1{ \dimen@\prevdepth \nointerlineskip \begingroup \setbox\z@\vbox to\z@{\vss \rlap{#1}} \dp\z@\dimen@ \box\z@ \endgroup } % \end{macrocode} % \end{macro} % % % % \begin{macro}{\remove@guard@box@from@cclv} % Remove a guard box again. This always happens in the OR and so we % hard code the box number for speed. % % Chris thinks this needs a maxdepth setting. % \begin{macrocode} \def\remove@guard@box@from@cclv{ \global\setbox\@cclv \vbox{\boxmaxdepth\@maxdepth \unvbox\@cclv \global\setbox\removed@guard@box\lastbox} } % \end{macrocode} % \end{macro} % % % \begin{macro}{\readd@guarded@penalty} % Readding a guared penalty including the box that was removed % earlier. Probably not needed in the end either since the way it % is used at the moment we have a |\topskip| problem this % way.\footnote{FIX!!!!} % \begin{macrocode} \def\readd@guarded@penalty#1 { \box\removed@guard@box %FMi what about topskip? \penalty-#1\relax} % \end{macrocode} % \end{macro} % % % % \begin{macro}{\removed@guard@box} % \begin{macrocode} \newbox\removed@guard@box % \end{macrocode} % \end{macro} % % % % % % \subsection{Columns and their Data Structures} % % \begin{macro}{\col@count} % We are collecting stuff for a given number of columns. This % number of column is available in a count register. % \begin{macrocode} \let\col@count \col@number % reuse a register from LaTeX % which is named differently there % \end{macrocode} % \end{macro} % % % \begin{macro}{\curr@col@count} % Register denoting the column number of the current column while % we cut the galley etc. Should always be modified globally since % it is used within output routines. % \begin{macrocode} \newcount\curr@col@count % \end{macrocode} % \end{macro} % % % % \DescribeMacro\col@box@FOO % Per column number FOO we have one box register allocated in which % the column text from the galley is stored during trials and page % makeup. % % \DescribeMacro\col@ht@FOO % Per column number FOO we have dimen register allocated which % holds the vertical target size for the column during the trials. % % \DescribeMacro\col@t@floats@FOO@number % Per column number FOO we have a macro number in which we count % the number of top floats we have seen so far in this column. This % is used to implement |\pagesetup@float@area@sep| handling. % % \DescribeMacro\col@b@floats@FOO@number % Per column number FOO we have a macro number in which we count % the number of bottom floats we have seen so far in this column. This % is used to implement |\pagesetup@float@area@sep| handling. % % % \DescribeMacro\col@t@delta@FOO % Per column number foo we have a macro in which we record the % difference between the real size of all top floats (including % there separation spaces) and the nominal size which is used to % determine the vertical size of the remaining text column. The two % may differ if we do grid typesetting. % % \DescribeMacro\col@b@delta@FOO % Same kind of delta is recorded per column for the bottom floats. % % \DescribeMacro\fl@FOO@BAR % For each float type BAR (e.g., |figure|, |table|, etc.) and each % column number FOO we have a macro which holds the highest float % sequence number for floats of type BAR allocated to column FOO or % zero if no float has been allocated so far. % % \DescribeMacro{\fl@0@BAR} % For each float type BAR (e.g., |figure|, |table|, etc.) % |\fl@0@BAR| holds the highest sequence number in columns of the % previous page. % % \DescribeMacro\tfl@FOO@BAR % |\tfl@FOO@BAR| is like |\fl@FOO@BAR| but only stores information % about floats allocated to top areas. % % % \begin{macro}{\col@box@1} % \begin{macro}{\col@box@2} % \begin{macro}{\col@box@3} % \begin{macro}{\col@box@4} % \begin{macro}{\col@box@5} % \begin{macro}{\col@box@6} % Need a box per column (currently fixed at six) to hold material % from the galley for this column. % \begin{macrocode} \expandafter\newbox\csname col@box@1\endcsname \expandafter\newbox\csname col@box@2\endcsname \expandafter\newbox\csname col@box@3\endcsname \expandafter\newbox\csname col@box@4\endcsname \expandafter\newbox\csname col@box@5\endcsname \expandafter\newbox\csname col@box@6\endcsname % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % % \begin{macro}{\col@ht@ 1} % \begin{macro}{\col@ht@ 2} % \begin{macro}{\col@ht@ 3} % \begin{macro}{\col@ht@ 4} % \begin{macro}{\col@ht@ 5} % \begin{macro}{\col@ht@ 6} % Need a dimen\footnote{Could be a macro if we find ourselves to % use up too many dimens.} per column to hold its current vertical % target size. % \begin{macrocode} \expandafter\newdimen\csname col@ht@ 1\endcsname \expandafter\newdimen\csname col@ht@ 2\endcsname \expandafter\newdimen\csname col@ht@ 3\endcsname \expandafter\newdimen\csname col@ht@ 4\endcsname \expandafter\newdimen\csname col@ht@ 5\endcsname \expandafter\newdimen\csname col@ht@ 6\endcsname % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % % % % % \subsubsection{Utilities for Columns and their Data Structures} % % \begin{macro}{\forall@columns} % If we want to do something to data structures for all column we % can use the macro |\forall@columns|. Within its argument the % current column is available in the register % |\curr@col@count|. The macro takes some pains to restore the % original value of |\curr@col@count| afterwards. % \begin{macrocode} \def\forall@columns#1{ \edef\saved@curr@col@count{\the\curr@col@count} \global\curr@col@count\z@ \@whilenum \curr@col@count<\col@count \do {\global\advance\curr@col@count\@ne #1 } \global\curr@col@count\saved@curr@col@count\relax } % \end{macrocode} % \end{macro} % % % \begin{macro}{\initialise@column@data} % \begin{macrocode} \def\initialise@column@data{ %<*trace> \@tracepush{initialise@column@data} % % \end{macrocode} % % \begin{macrocode} \global\let\best@trial\@empty \forall@columns { \global\csname col@ht@ \the\curr@col@count\endcsname\textheight % \end{macrocode} % % \begin{macrocode} \expandafter \g@addto@macro\expandafter\best@trial\expandafter { \expandafter \global \csname col@ht@ \the\curr@col@count\endcsname \textheight } % \end{macrocode} % We haven't seen any top or bottom floats yet. % \begin{macrocode} \global\@namedef{col@t@floats@ \the\curr@col@count @number}{0} \global\@namedef{col@b@floats@ \the\curr@col@count @number}{0} % \end{macrocode} % For the same reason the delta values for top and bottom areas are % zeroed.\footnote{Using \texttt{\string\let} and % \texttt{\string\z@} in places like this would be more faster and % shorter, but it wouldn't work nicely in tracing as it would make % unexpandable macros. Perhaps the tracing versions should be made % specially.} % \begin{macrocode} \global\@namedef{col@t@delta@ \the\curr@col@count}{0pt} \global\@namedef{col@b@delta@ \the\curr@col@count}{0pt} } %<*trace> \tr@ce{\meaning\best@trial} \@tracepop{initialise@column@data} % } % \end{macrocode} % \end{macro} % % % % % % % \subsubsection{User Commands for Columns} % % % \begin{macro}{\columnbreak} % And here is the user command formaking a column % break:\footnote{All this is stolen from \texttt{multicol.sty} and % there is still code that doesn't belong here.} |\columnbreak| is % modelled after |\pagebreak| except that we generate a penalty % |-\output@columnbreak@penalty|. % \begin{macrocode} \def\columnbreak{ % \end{macrocode} % We have to ensure that it is only used within a multicolumn % environment since if that penalty would be seen by the unmodified % \LaTeX{} output routine strange things would happen. % \begin{macrocode} \ifnum\col@count<\tw@ \PackageError{xoutput} {\noexpand\columnbreak~ in~ one-column~ mode} {???} \else \ifvmode \penalty -\output@columnbreak@penalty \else \@bsphack \vadjust{\penalty -\output@columnbreak@penalty} \@esphack \fi \fi} % \end{macrocode} % \end{macro} % % % % % % % % % % % \subsection{Float Areas and their Data Structures} % % Naming conventions for float areas is as follows: % \begin{quote} % \meta{identifier}\meta{start-column}\meta{span-count}. % \end{quote} % The \meta{identifier} is a single letter denoting the type of area, % e.g., |t| for top, |b| for bottom. The \meta{span-count} is a single % digit denoting the number of columns to span. The % \meta{start-column} is a single digit\footnote{with a bit of care in % the code this could be extended to allow more than one digit.} % denoting the start column of the area. Thus |t32| is a top area % starting at column three and spanning two columns ie three and four. % A restriction due to the naming scheme is that currently no more than % 9 columns are possible. % % Only a subset of the float areas is allowed to be popolated on a % page. In essense the current algorithm does not support placements % that result in splitting the text of a column due to a float (other % than column `here' floats).\footnote{Perhaps this restriction is % lifted one day.} This means that if $pcs$ ($p=\textrm{pos}$, % $c=\textrm{column}$, $s=\textrm{span}$) is a float area that is % being populated then it must prevent populating all float areas that % satisfy either % \[ % pij \textrm{ with } i < c \leq i+j < c+s % \] % or % \[ % pij \textrm{ with } i \leq c+s < i+j \leq \verb=\col@count= % \] % The first formula describes the areas which partly overlap from the % left, the second formula describes those that partly overlap from % the right. Areas which are sub- or super-areas, e.g., \texttt{t13} % and \texttt{t22} do not affect each other. The above restriction is % necessary to prevent situations like %\begin{verbatim} %aaaaaaaaaaa 444 %aaaaaaaaaaa 444 %aaaaaaaaaaa 444 %111 222 bbbbbbb %111 222 bbbbbbb %111 222 bbbbbbb %111 222 333 444 %111 222 333 444 %\end{verbatim} % % % For each area |FOO| (e.g., |t13|) we keep a number of global % variables to store relevant data. These are the following % variables\footnote{Not a consistent lot}: % % \DescribeMacro\area@FOO % Floats allocated to the area |FOO| by the page building process % are stored as an |\@elt| list in the macro |\area@FOO|. % % \DescribeMacro\pagesetup@FOO@float@num % The maximum number of floats allowed in area |FOO| is stored in % the macro |\pagesetup@FOO@float@num|. % % \DescribeMacro\FOO@@float@count % % The number of floats currently allocated to area |FOO| is stored % in the count register |\FOO@@float@count|.\footnote{This is a % waste of registers!} % % \DescribeMacro\pagesetup@FOO@class@close % The areas that should be closed for floats of the same sequence class the % moment a float is placed into area |FOO|. This is a comma % separated list. % % \DescribeMacro\pagesetup@FOO@all@close % The areas that should be closed for all float sequence classes the % moment a float is placed into area |FOO|. This is a comma % separated list. % % % % \begin{macro}{\known@areas} % |\known@areas| are the areas known to the system.\footnote{or % something else, the semantics are still changing} Initialisation % is done when declaring individual areas. % \begin{macrocode} \def\known@areas{} % \end{macrocode} % \end{macro} % % % % \begin{macro}{\used@areas} % |\used@areas| are the areas used by the current page setup. % Initialisation is done in the page setup template so the % definition below is arbitrary. % \begin{macrocode} \def\used@areas{ t11 b11 } % \end{macrocode} % \end{macro} % % % % \begin{macro}{\@activelist} % \begin{macrocode} \let\@activelist\@empty % \end{macrocode} % \end{macro} % % \begin{macro}{\@mvllist} % \begin{macrocode} \let\@mvllist\@empty % \end{macrocode} % \end{macro} % % % \begin{macro}{\area@ddd} % The list of deferred floats (which we consider being an area in % some respects). % \begin{macrocode} \let\area@ddd\@empty % \end{macrocode} % \end{macro} % % \begin{macro}{\pagesetup@ddd@class@close} % \begin{macro}{\pagesetup@ddd@all@close} % \begin{macrocode} \def\pagesetup@ddd@class@close{\pagesetup@area@list} \let\pagesetup@ddd@all@close\@empty % \end{macrocode} % \end{macro} % \end{macro} % % % % \begin{macro}{\this@open@areas} % \begin{macro}{\saved@this@open@areas} % In |\this@open@areas| we store the float areas which we will try % to place a float onto the current page. These areas are tried one % after another until the float is successfully placed or we run % out of areas. The list does not have any separator (as we assume % that all areas are denoted by a letter followed by two digits). % % |\saved@this@open@areas| is the seved version needed for % backtracking if we encounter a flush point that can't be resolved. % \begin{macrocode} \let\this@open@areas\@empty \let\saved@this@open@areas\@empty % \end{macrocode} % \end{macro} % \end{macro} % % % % \begin{macro}{\this@closed@areas} % In |\this@closed@areas| we store the float areas which have been % closed for the current float while trying to place it. In this % list each area name is followed by a comma (to avoid spurious % matches). It is initialised with |closed@\this@class @areas| when % we fetch a new float to try. Once the float is placed we write % the then current value back. % \begin{macrocode} \let\this@closed@areas\@empty % \end{macrocode} % \end{macro} % % % \begin{macro}{\this@page@closed} % In |\this@page@closed| we store the float areas which have been % closed for all float types. In this list each area name is % followed by a comma (to avoid spurious matches). % \begin{macrocode} \let\this@page@closed\@empty % \end{macrocode} % \end{macro} % % % % % \begin{macro}{\t11@float@count} % \begin{macro}{\t21@float@count} % \begin{macro}{\b11@float@count} % \begin{macro}{\b21@float@count} % The float counts are allocated dynamically when an area is % declared if they are not defined, but we have a few registers % left over from \LaTeX{}'s old OR so we might as well use them. % \begin{macrocode} %\expandafter\newcount\csname t11@float@count\endcsname \expandafter\let\csname t11@float@count\endcsname \@topnum %\expandafter\newcount\csname b11@float@count\endcsname \expandafter\let\csname b11@float@count\endcsname \@botnum %\expandafter\newcount\csname t12@float@count\endcsname \expandafter\let\csname t12@float@count\endcsname \@dbltopnum %\expandafter\newcount\csname b12@float@count\endcsname \expandafter\let\csname b12@float@count\endcsname \@dblbotnum % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % \begin{macro}{\ddd@float@count} % And we need to declare the one for the defer area is that isn't % going through the normal initialisation process. % \begin{macrocode} \newcount\ddd@float@count % \end{macrocode} % \end{macro} % % % % % \begin{macro}{\pagesetup@float@area@sep} % |\pagesetup@float@area@sep| is the separation to use between two % adjacent float areas. % \begin{macrocode} \newskip\pagesetup@float@area@sep % \end{macrocode} % \end{macro} % % % % \begin{macro}{\pagesetup@float@text@sep} % |\pagesetup@float@text@sep| is the separation to use between % column text and adjacent float areas. % \begin{macrocode} %\newskip\pagesetup@float@text@sep \let\pagesetup@float@text@sep\textfloatsep % reuse register \let\textfloatsep\@undefined % \end{macrocode} % \end{macro} % % % % \begin{macro}{\pagesetup@float@float@sep} % |\pagesetup@float@float@sep| is the separation to use between % two floats in the same float area. % \begin{macrocode} %\newskip\pagesetup@float@float@sep \let\pagesetup@float@float@sep\floatsep % reuse register \let\floatsep\@undefined % \end{macrocode} % \end{macro} % % % % \begin{macro}{\pagesetup@float@text@shrink} % |\pagesetup@float@text@shrink| is the allowed shrinkability of % |\pagesetup@float@text@sep|. This is used if we are doing grid % typesetting and have to adjust the vertical size of the column. % \begin{macrocode} \newdimen\pagesetup@float@text@shrink % \end{macrocode} % \end{macro} % % % % % \begin{macro}{\pagesetup@float@inline@sep} % |\pagesetup@float@inline@sep| is the separation to use between % two floats in the same float area. % \begin{macrocode} %\newskip\pagesetup@inline@float@sep \let\pagesetup@float@inline@sep\intextsep % reuse register \let\intextsep\@undefined % \end{macrocode} % \end{macro} % % % \begin{macro}{\pagesetup@float@inline@shrink} % |\pagesetup@float@inline@shrink| is the allowed shrinkability of % |\pagesetup@float@inline@sep|. This is used if we are doing grid % typesetting and have to adjust the vertical size of object to be % added, e.g., an inline float with its caption. % \begin{macrocode} \newdimen\pagesetup@float@inline@shrink % \end{macrocode} % \end{macro} % % % % % % % \subsubsection{Utilities for Float Areas and their Data Structures} % % % \begin{macro}{\initialise@areas} % Initialise all float areas used within the current page setup. % \begin{macrocode} \def\initialise@areas{ \expandafter\initialise@areas@loop \used@areas \relax\relax\relax } % \end{macrocode} % \end{macro} % % \begin{macro}{\initialise@areas@loop} % The |\initialise@areas@loop| picks up the next three tokens and % interprets them as the component of an area name. % \begin{macrocode} \def\initialise@areas@loop#1#2#3{ \ifx#1\relax \else \global\csname #1#2#3@float@count\endcsname\z@ \global\expandafter\let\csname area@#1#2#3\endcsname\@empty \expandafter\initialise@areas@loop \fi} % \end{macrocode} % \end{macro} % % % \begin{macro}{\first@of@type} % The macro |\first@of@type| takes a \meta{type} name as its first % argument and an \meta{area} area name as its second argument and % will return in the macro |\returned@sequence@number| the sequence % number of the first float of type \meta{type} currently in % \meta{area}. If there is no float of type \meta{type} in this % area it will return |-1| (impossible sequence number). % \begin{macrocode} \def\first@of@type#1#2{ \begingroup \def\@tempb{#1} \gdef\returned@sequence@number{-1} \def\@elt{\expandafter\first@of@type@aux\the\toks} \csname area@#2\endcsname \endgroup } % \end{macrocode} % \end{macro} % % \begin{macro}{\first@of@type@aux} % This macro picks up the type definition in the data structure of % a float and compares it with the name started in |\@tempb|. If % they agree |\returned@sequence@number| will get updated to % contain the sequence number of the float. % \begin{macrocode} \def\first@of@type@aux#1#2#3#4#5#6#7{ \def\@tempa{#6} \ifx\@tempa\@tempb \gdef\returned@sequence@number{#7} \let\@elt\@gobble \fi} % \end{macrocode} % \end{macro} % % \begin{macro}{\last@of@type} % The macro |\last@of@type| takes a \meta{type} name as its firat % argument and an \meta{area} area name as its second argument and % will return in the macro |\returned@sequence@number| the sequence % number of the last float of type \meta{type} currently in % \meta{area}. If there is no float of type \meta{type} in this % area it will return |-1| (impossible sequence number). % \begin{macrocode} \def\last@of@type#1#2{ \begingroup \def\@tempb{#1} \gdef\returned@sequence@number{-1} \def\@elt{\expandafter\last@of@type@aux\the\toks} \csname area@#2\endcsname \endgroup } % \end{macrocode} % \end{macro} % % \begin{macro}{\last@of@type@aux} % \begin{macrocode} \def\last@of@type@aux#1#2#3#4#5#6#7{ \def\@tempa{#6} \ifx\@tempa\@tempb \gdef\returned@sequence@number{#7} \fi} % \end{macrocode} % \end{macro} % % % % % \begin{macro}{\setup@this@area} % % Whenever the algorithm works with some area as the current % candidate for putting a float into it uses the following commands % to reference this area: % % \DescribeMacro\this@area % The macro |\this@area| holds the name of the candidate area, e.g., % it would expand to something like |t13|. % % \DescribeMacro\this@area@type % The macro |\this@area@type| holds the ``type'' of the area, e.g., |t| % in the above example. % % \DescribeMacro\this@area@col@number % The macro |\this@area@col@number| holds the starting column of the % area, e.g., |1| in the above example. % % % \DescribeMacro\this@area@span@number % The macro |\this@area@span@number| holds the number of columns % spanned by the area, e.g., |3| in the above example. % % All the above macros are globally assigned when calling % |\setup@this@area|. The argument is fully expanded (!) since one % typical usage to pick up the first area from an area like % |\this@open@areas| which can then be done within the argument. % % \begin{macrocode} \def\setup@this@area #1 { \xdef\this@area{#1} % \end{macrocode} % This really relies on |\this@area| containing exactly three % tokens (no error recovery if not). % \begin{macrocode} \expandafter\gassign@area@type@col@and@span@aux\this@area } \def\gassign@area@type@col@and@span@aux #1#2#3{ \gdef \this@area@type {#1} % type \gdef \this@area@col@number {#2} % col \gdef \this@area@span@number {#3} % span } % \end{macrocode} % \end{macro} % % % \begin{macro}{\update@this@area@columns} % % If we have to do updates for all columns that are spanned by the % current target area we can call |\update@this@area@columns|. It % loops through the columns with |\count@| referring to the current % column. Data structure updates have to be global as everything % happens within a group. % \begin{macrocode} \def\update@this@area@columns #1 { \begingroup \count@\this@area@col@number\relax \advance\count@\this@area@span@number\relax \loop \ifnum \this@area@col@number < \count@ \advance\count@\m@ne %<*trace> \tr@ce{looking~ at~ column:~ \the\count@} % #1 \repeat \endgroup } % \end{macrocode} % \end{macro} % % % % % % % \newpage % \subsection{Collection Output Routine} % % \begin{description} % \item[Entry:] |\setup@collection@or| % \item[Exit:] |\setup@float@placement| % \item[Prereq:] |\initialise@next@page| should have been called before. % \item[Description:] Grab enough text (and float call-outs) to obtain % a galley big enough to form the next text page. The page goal is % set to a value high enough to ensure that in normal cases text % for all columns of the page is collected, i.e, we have a safety % margin of 5 extra lines per column.\footnote{This should be made % customisable for unusual jobs!} % % If the output routine is triggered with a special penalty (in the % range of $-10000>p>-10010=|\output@balance@penalty|$) the penalty % is moved into the collection box |\partial@galley@box| without % further processing; otherwise the collection is ended and all % collected material is moved to |\@holdpg| for use in page % production. % % \item[Flow:] %\begin{footnotesize} %\begin{verbatim} % \setup@collection@or % | % V % New OR: \collection@or % | % |<----------------------------------------- % | | % (natural end of collection reached?) | % | | | % yes no | % | | | % | (record special penalty and carry on)---- % | % V % \setup@float@placement %\end{verbatim} %\end{footnotesize} % \end{description} % % Chris noted that |\@holdpg| never gets emptied. This could be % done when the Collection OR is started for a new page (in this % next macro).\footnote{FIX} % % \begin{macro}{\setup@collection@or} % \begin{macrocode} \def\setup@collection@or{ %<*trace> \@tracepush{setup@collection@or} % \global\holdinginserts\@ne % \end{macrocode} % We set the |\vsize| for collection to the height of a single % column (plus a safety margin of currently five lines to allow for % vanishing space at margins) multiplied by the number of columns. % \begin{macrocode} \global\vsize\textheight \global\advance\vsize 5\baselineskip \global\multiply\vsize \col@count %<*trace> \tr@ce{collection~vsize:~\the\vsize } % % \end{macrocode} % Initialising the flush point handling: % \begin{macrocode} \@flushseenfalse \@flushfailfalse % \end{macrocode} % We may have to restart the collection (whenever we find a here or % a flush point) and we don't want to get extra space added via % |\topskip|. So we can either make |\topskip| zero during % collection (current strategy) or back it out whenever we restart. % % We can't set topskip to zero now since a) we want a proper % |\topskip| for the first column and b) due to a bloody fix for the % old \LaTeX{} OR, a value of |0pt| is set to |1sp| in % |\begin{document}| and this results in adding |1sp| at every % special point\ldots no, we definitely do not want this! It took % me ages to find out why the grid design macros didn't work. % \begin{macrocode} \xdef\saved@topskip{\the\topskip} % \end{macrocode} % % \begin{macrocode} \global\output{\collection@or} %<*trace> \@tracepop{setup@collection@or} % } % \end{macrocode} % \end{macro} % % % % % \begin{macro}{\if@collecting@new@material} % There are actually two collecting modes: one when the recent % contributions are empty and we are really collecting material % that we haven't seen before and one where we collect material % that has been collected on a previous collection pass and has been % placed again on to the main vertical list. The reason why we need % to differentiate between the two is that in the second case we % have to handle the special penalties differently since by now % they are already surrounded by the proper guard boxes before and % after and we better do not disturb this fragile setup. % \begin{macrocode} \newif\if@collecting@new@material \def\@collecting@new@materialfalse {\global\let\if@collecting@new@material\iffalse} \def\@collecting@new@materialtrue {\global\let\if@collecting@new@material\iftrue} % \end{macrocode} % \end{macro} % % % % % \begin{macro}{\collection@or} % The output routine during the collection phase assembles the % material until enough has been gathered to be sure to fill a % page. % \begin{macrocode} \def\collection@or{ %<*trace> \@tracepush{collection@or} \tr@ce{output~pen:~ \the\outputpenalty} %{\x\showoutput\showbox255} % % \end{macrocode} % We first look if the call to the OR is due to a special penalty. % \begin{macrocode} \@testfalse \ifnum\outputpenalty < -\@M \ifnum\outputpenalty > -\output@balance@penalty \@testtrue \fi \fi \if@test %<*trace> \tr@ce{Forced~ break~(\the\outputpenalty)~ seen\on@line} % % \end{macrocode} % Whenever a special penalty, i.e., one between $-10000 > p > % -10010$ is encountered we need some magic: % \begin{itemize} % \item We want to keep the the penalty in the collected material but % nevertheless carry on with the collection. Simply moving the % collected material to a separate box is not enough since then % we will restart the collection with an empty page and thus % receive a |\topskip| glue as well as probably losing material % if there is anything discardable after the special penalty. % \item But putting a zero box back and doing something to fix the % problem with the |\topskip| glue isn't good either in case we % later actually want to break after the line with special % penalty, since then we would start a page with our inserted % box, and in this case we would like to get a proper |\topskip| % and we would like to get rid of discardable stuff. % \item And there is another problem, we need a guard box in front of % that special penalty, but this guard box should not be simply a % |\null| box (as it is right now added by % |\add@badly@guarded@penalty|) since that will result in wrong % page calculations because it will make \TeX{} add the depth of % the precious line to the page total which it shouldn't. % \end{itemize} % So what to do? First of all we remove the guard box in front of % the special penalty (which is now at the end of box 255) since we % want to replace that with something better, then we % store away the depth of box 255 since we need that in a minute. % \begin{macrocode} \remove@guard@box@from@cclv % \end{macrocode} % We really have to say |\dp\@cclv| not |\pagedepth|. The latter is % always zero in the OR which looks suspiciously like a bug or at % least an inconsistency when Don implemented the change from \TeX2 % to \TeX3 (in \TeX2 |\page...| registers were useless in the OR, % now only |\pagedepth| seems to be left). % \begin{macrocode} \dimen@\dp\@cclv % \end{macrocode} % Then we subtract the size of the collected material from % |\vsize| since we will store it away in a separate box for a % while. Note that we have to use |\ht\@cclv| here not |\pagetotal| % since the latter might be to large because of that |\null| % box. The height of 255 on the other hand is, after the removal of % that box the natural height of the material. % \begin{macrocode} \global\advance\vsize-\ht\@cclv % \end{macrocode} % Now we append the material to |\partial@galley@box|, this is % straight forward. % \begin{macrocode} \global\setbox\partial@galley@box \vbox{\ifvoid\partial@galley@box \else \unvbox\partial@galley@box \fi \unvbox\@cclv % \end{macrocode} % But how to add the penalty and how to guard it? We need a box or % something to ensure the penalty doesn't get lost at a column % break but we also want to avoid that \TeX{} adds the depth of the % preceding line to |\pagetotal|. Fortunately we know this depth by % now (we have just stored it in |\dimen@|), something we didn't % know at the time the we added the penalty with % |\add@badly@guarded@penalty|. So we could back up and then add a % box with zero height and that depth. This way a break directly % after this line would have the same |\pagetotal| as a break at % the special penalty. In fact, instead of backing up using a % |\kern| or a |\vskip| we can simply make the height of the box % negative. The advantage is that this way we don't generate a % break point between the box and a preceding box and thus don't % have to use special precautions to prevent \TeX{} from breaking in % front of the guard box.\footnote{This statement is only true for % special penalties added using \texttt{\string\vadjust}, i.e., in % hmode. If the penalty was added between paragraphs then there % might be vertical space in front of the box. This might need % special handling too. CHECK!} % \begin{macrocode} \setbox\z@\vbox to-\dimen@{} \dp\z@\dimen@ \box\z@ \penalty\outputpenalty } %{\showoutput\batchmode\showbox\partial@galley@box\errorstopmode} % \end{macrocode} % So now we have put everthing we need into the % |\partial@galley@box|, but how do we restart our collection % process without running into the problems outlined above? % % Well, right now on the recent contributions there will be a % penalty node (from our special penalty) which gets set to 10000 % by \TeX{} followed perhaps by another penalty from the line % breaking followed probably by interline glue calculated to make % the next line of text fit vertically with the preceding one --- % and we don't want to loose that that glue if we are ending up in % the middle of a column. But we want to make it vanish if we % happen to finally break at the special penalty place. % % So the trick is that we a) disable |\topskip| by setting it to % |-\maxdimen| (not zero this might be too large still) and b) we % add another of those funny boxes followed by a penalty of zero to % allow for a break after it. % % If later on all this is put together again into a single box (in % |\@holdpg|) we will have the following sequence there: % \begin{itemize} % \item text line (box) preceding the special penalty with depth $d$ % or some other vertical material in which case $d=0\texttt{pt}$ % \item special box with height $-d$ and depth $d$ % \item special penalty, e.g. $-10008$ % \item |\topskip| glue of 0pt % \item special box with height $-d$ and depth $d$ % \item |\penalty| 0 % \item |\penalty| 10000 % \item perhaps a |\penalty| and/or interline glue % \item perhaps the next text line (box) % \end{itemize} % Now if during later processing we hit the special penalty % |\pagetotal| has the same value as if we would have broken the % galley directly after the text line, in other words we do not see % the penalty too late (assume this happens to be the last line of % the column then if |\pagetotal| would also have the extra depth % added to it it might have been overfull and the penalty not being % considered at all for this column). % % After the OR's have dealt with the special penalty, e.g., by % flushing some floats, etc. the penalty will be replaced by 10000 % and thus the next time the galley is processed there is no % breakpoint between the two special boxes any more. As a result % the next potential breakpoint is the penalty 0 which again % results in exactly the same |\pagetotal| as before, i.e., if the % text line was the last line to fit in the column then this % breakpoint will still fit there. Thus if we break the column % there then the interline glue etc will vanish and \TeX{} will % insert |\topskip| glue (which has be set back to a normal value % by then). If on the other hand, this break point is not chosen % the interline glue will stay and thus the two text lines, before % and after the special penalty will sit one |\baselineskip| apart % just as they should. % % Woah. What did Don said on page 125 of \textit{The \TeX{}book}? % (Deep breath.) You got that?\footnote{There are probably still % cases that aren't covered I fear and the need for an explicit % penalty 0 at the end is kind of toublesome, so we have to see if % this needs further refinements.} % % And here is already the first case where the above method is not % appropriate: if we stumble across a |\output@columnbreak@penalty| % we need to discard any following glue, so we don't want a box % intervene here.\footnote{Once this is interfaced with the galley % code problems like this should vanish since then we can ensure % that all such penalties are added to the galley on at save % places. REDO THEN!} % \begin{macrocode} \global\topskip-\maxdimen % okay here? \if@collecting@new@material \ifnum \outputpenalty = -\output@columnbreak@penalty \else \setbox\z@\vbox to-\dimen@{} \dp\z@\dimen@ \box\z@ \penalty\z@ \fi \fi % \end{macrocode} % % \begin{macrocode} \ifnum\outputpenalty=-\output@flush@float@penalty %<*trace> \tr@ce{Forced~ break~ =~ flush~ float~ point} % \@flushseentrue \fi % \end{macrocode} % Otherwise either the we reached the natural end of the % collection, or the point where we have been before (in case we % are recollecting previously seen material) or we reached an % |\output@balance@penalty|. % \begin{macrocode} \else \ifnum\outputpenalty = -\output@collect@penalty % \end{macrocode} % If we got an |-\output@collect@penalty| then we are at the point % to which the previous collection pass got. So, away with the % guard box, then everything back onto the MVL and as a penalty we % try to put what we have found in the previous collection pass. % \begin{macrocode} \remove@guard@box@from@cclv \unvbox\@cclv %<*trace> \tr@ce{reinsert~penalty:~ \saved@outputpenalty\space (unless~ 10000~ or~ <~ -9999)} % \ifnum\saved@outputpenalty > -\@M \penalty \ifnum\saved@outputpenalty=\@M \z@ \else \saved@outputpenalty\relax \fi % \end{macrocode} % We have a special situation to account for here: if we have a % |\pagebreak| that ended the collection last time then it might % still be the case that we haven't got to this point due to % floats. So we would need to put that penalty back. But only then, % and therese the catch! The alternative is to not stop a % collection as such a point so that this problem doesn't arise in % the first place. Right now we lose the % penalty.\footnote{Unresolved situation. FIX!} % \begin{macrocode} \else \fi % \end{macrocode} % Finally we change the |@collecting@new@material| switch since we % are from now on looking at really new material. % \begin{macrocode} \@collecting@new@materialtrue \else % \end{macrocode} % Next case is not functional right now\ldots % \begin{macrocode} \ifnum\outputpenalty = -\output@balance@penalty \@balancetrue %<*trace> \tr@ce{BALANCE:~ break~ seen\on@line} % \xdef\saved@outputpenalty{0} % \end{macrocode} % This is now the point where the collection ended naturally: we % save the penalty that triggered it and combine the % |\partial@galley@box| if it contains material with the stuff now % in 255 and put everything into |\@holdpg|. % \begin{macrocode} \else \xdef\saved@outputpenalty{\the\outputpenalty} \fi \ifvoid\partial@galley@box \global \setbox\@holdpg\box\@cclv \else %<*trace> \tr@ce{Re-adding~ forced~ break(s)~ for~ splitting} % \global\setbox\@holdpg\vbox{ \unvbox\partial@galley@box \unvbox\@cclv} \fi %\showbox\@holdpg \if@balance \global\setbox\@holdpg\vbox{ \unvbox\@holdpg \penalty\outputpenalty % short for "-\output@balance@penalty" } \fi \mark@save@state \mark@update@structure % \global\holdinginserts\z@ \global\topskip\saved@topskip \setup@float@placement \@collecting@new@materialfalse \fi \fi %<*trace> \@tracepop{collection@or} % } % \end{macrocode} % \end{macro} % % % % \begin{macro}{\partial@galley@box} % Need a box to store the partially collected galley. % \begin{macrocode} \newbox\partial@galley@box % \end{macrocode} % \end{macro} % % % % % % \begin{macro}{\initialise@float@class} % % \begin{macrocode} \def\initialise@float@class#1{ %<*trace> \@tracepush{initialise@float@class} % \count@0\LastMark{#1} % % next line no longer used % \global\expandafter\mathchardef\csname count@#1\endcsname\count@ % %<*trace> \tr@ce{count~ (#1) = \the\count@} % % \end{macrocode} % % At some point the set of open areas at page start (for a % given type of floats) should be specifiable through some % templates. Using |\used@areas| is not really the right thing % to do.\footnote{Code should vanish one day}. % \begin{macrocode} \global\expandafter\let\csname open@#1@areas\endcsname\used@areas \global\expandafter\let\csname closed@#1@areas\endcsname\@empty % \end{macrocode} % % \begin{macrocode} %<*trace> \tr@ce{open~ (#1) = \csname open@#1@areas\endcsname} \tr@ce{closed~ (#1) = \csname closed@#1@areas\endcsname} % % \end{macrocode} % % |\fl@1@figure| are macros that expands to the highest numbered % figure callout in this column (or zero if there is none). % |\fl@0@figure| is the highest value from previous pages (or zero % if there was never any float of this type). % \begin{macrocode} \forall@columns { \ifnum \csname fl@ \the\curr@col@count @#1\endcsname>\z@ \global\expandafter\let\csname fl@0@#1\expandafter\endcsname \csname fl@ \the\curr@col@count @#1\endcsname \expandafter\xdef \csname fl@ \the\curr@col@count @#1\endcsname{0} \fi % \end{macrocode} % |\tfl@1@figure| is like |\fl@1@figure| but only stores % information about floats allocated to top areas. % \begin{macrocode} \expandafter\xdef \csname tfl@ \the\curr@col@count @#1\endcsname{0} } %<*trace> \@tracepop{initialise@float@class} % } % \end{macrocode} % \end{macro} % % % % % \newpage % % \subsection{Placing Floats} % % % \begin{description} % \item[Entry:] |\setup@float@placement| % \item[Exit:] |\setup@grab@column@or| or |\setup@best@column@or| % \item[Prereq:] % \item[Description:] % \item[Flow:] %\begin{footnotesize} %\begin{verbatim} % \setup@float@placement % | % V %(2)--> \float@placement@loop % | % % | | % yes no----------> \setup@grab@column@or % | % V % \trial@inner@loop % | % V % % | | % no yes % | | % (means we now try V % again using different \try@next@float <------------------- % placement rules below ) | | % | | | % | <\@activelist empty?> | % | | | | % | no yes | % | | | | % | | V | % | (get it) \@activelist@empty@action | % | | (= \setup@best@column@or) | % -------------v---------------- | % | | % -----> \try@this@area (= \std@try@this@area, or | % | | \relaxed@try@this@area) | % | | | % | | % | | | | % | yes no---------------(defer float)-------------- % | | | % | (do some tests and perhaps | % | close area this way) | % | | | % | | % | | | | % | yes no---------------(defer float)-------------- % | | % | % | | | % | yes no % | | | % | (select next area) | % | | | % -------- V % \pretests@success@action (\setup@grab@column@or) %\end{verbatim} %\end{footnotesize} % \end{description} % % % % % % \begin{macro}{\if@fail} % \begin{macrocode} \newif\if@fail \def\@failfalse{\global\let\if@fail\iffalse} \def\@failtrue{\global\let\if@fail\iftrue} % \end{macrocode} % \end{macro} % % % \begin{macro}{\setup@float@placement} % % \begin{macrocode} \def\setup@float@placement { % initialise before trial loop (needs work) %<*trace> \@tracepush{setup@float@placement} % % \end{macrocode} % A bit statistics: how many floats do we have on the % |\@activelist|? % \begin{macrocode} %<*progress> \def\@elt{\global\advance\trial@count\@ne\@gobble} \@activelist \let\@elt\relax \progress@separator \progress@nl{STATS:~ floats~ waiting~ =~ \the\trial@count \space on~ page~ \the\absolute@page@number} \progress@separator \global\trial@count\z@ % % \end{macrocode} % We need the list of here floats during all trials. They are % therefore saved in |\saved@herelist| at this point which is then % used to initialise |\@herelist| at the beginning of each trial. % \begin{macrocode} \global\let\saved@herelist\@herelist % \end{macrocode} % % \begin{macrocode} \tighten@float@placement@conditions % \end{macrocode} % First time we run the |\float@placement@loop| we run it without % actually trying any floats (i.e., we are just cutting the % galley).\footnote{Could be improved: if there are no floats then % we run it once too often this way (per page) so\ldots} % \begin{macrocode} \run@with@floatsfalse \float@placement@loop %<*trace> \@tracepop{setup@float@placement} % } % \end{macrocode} % \end{macro} % % % \begin{macro}{\float@placement@loop} % Place the galley box back on the MVL. Needs to be done via the % special output routine call |\mark@restore@state| to ensure that % \TeX's primitive marks reflect the `logical' previous page rather % than the previous actual output routine call. % \begin{macrocode} \def\float@placement@loop{ %<*trace> \@tracepush{float@placement@loop} % % \end{macrocode} % % \begin{macrocode} \deadcycles\z@ \global\let\@activelist@empty@action\setup@best@column@or \global\let\pretests@success@action\setup@grab@column@or % \end{macrocode} % % If we are doing trials we have to place a special penalty at the % end of the MVL but if we are cutting up the galley for % typesetting we don't want this penalty. Since at this point it is % not clear in which case we are we defer this action until % later.\footnote{This part of the documentation is no longer true, % we now add it below. CORRECT DOCU} % % |\mark@restore@state| state is a special output routine those % only purpose is to reinitialise the state of the mark % mechanism. Its argument is executed at the of that OR. % \begin{macrocode} \mark@restore@state{ % \end{macrocode} % Initialising the grabbing trials means putting the saved material % back onto the MVL and reinitialising the here float list. % \begin{macrocode} \unvcopy\@holdpg \ifnum\saved@outputpenalty > -1073741824\relax \add@badly@guarded@penalty\output@collect@penalty \fi \global\let\@herelist\saved@herelist % \end{macrocode} % % The we can start the actual loop: if we run with floats we go to % |\trial@inner@loop| otherwise we immediately setup the grap % column OR. % \begin{macrocode} \ifrun@with@floats \trial@inner@loop \else \setup@grab@column@or \fi } %<*trace> \@tracepop{float@placement@loop} % } % \end{macrocode} % \end{macro} % % % % % \begin{macro}{\trial@inner@loop} % Alternative entry into the float placement trial loop. This can % be used by setting |\@activelist@empty@action| and % |\pretests@success@action| to different values, e.g., for trying % float pages without the overhead of the grabcolumn output % routine, etc. % \begin{macrocode} \def\trial@inner@loop{ %<*trace> \@tracepush{trial@inner@loop} % % \end{macrocode} % If |\if@fail| is true we have already tried the current float % before. This means we either do a retry with relaxed conditions % (in which case the current area to try was suitably modified % beforhand) or else we have just started with a new float and % should try the first area of |\this@open@areas|. % \begin{macrocode} \if@fail \@failfalse \@flushfailfalse % \end{macrocode} % % \begin{macrocode} %<*progress> \global\advance\trial@count\@ne % % \end{macrocode} % % \begin{macrocode} \do@next\try@this@area \else \do@next\try@next@float \fi %<*trace> \@tracepop{trial@inner@loop} % \do@continue } % \end{macrocode} % \end{macro} % % % % \begin{macro}{\trial@count} % To gather statistics we count the number of trials per page. % \begin{macrocode} %<*progress> \newcount\trial@count % % \end{macrocode} % \end{macro} % % % \begin{macro}{\try@this@area} % |\try@this@area| is |\let| to the right definition before it is % called so on top-level it is defined to be an error. % \begin{macrocode} \let\try@this@area\ERROR % \end{macrocode} % \end{macro} % % \begin{macro}{\try@next@area} % |\try@next@area| first updates |\this@open@areas| by removing the % first area in this list and then calls |\try@this@area|. Thus it % should never be called if |\this@open@areas| is already empty. % \begin{macrocode} \def\try@next@area{ \xdef\this@open@areas{\expandafter\@gobblethree\this@open@areas} %<*progress> \global\advance\trial@count\@ne % \try@this@area } % \end{macrocode} % \end{macro} % % % \begin{macro}{\try@next@float} % If there is still a float on the active list take it and try to % place it in the next open float area (which will be the same as % the current area after a successful trial). If there are no % floats left execute |\best@trial| to return to that state then % switch to the bestcolumn output routine to begin typesetting % columns. % \begin{macrocode} \def\try@next@float{ %<*trace> \@tracepush{try@next@float} % \@next\@currbox\@activelist{ %<*trace> \tr@ce{currbox:~ \@currbox} % %<*progress> \progress{Float:~ \@currbox} % \expandafter\update@this@float@structure\the\toks\@currbox %<*trace> \tr@ce{saved@this@open@areas~(init):~ \saved@this@open@areas\space :=~\this@open@areas} % \global\let\saved@this@open@areas\this@open@areas %<*progress> \global\advance\trial@count\@ne % \try@this@area } % \end{macrocode} % no floats left\ldots % \begin{macrocode} { %<*progress> \progress@nl{STATS:~ trials~ =~ \the\trial@count} \global\trial@count\z@ % \@activelist@empty@action } %<*trace> \@tracepop{try@next@float} % } % \end{macrocode} % \end{macro} % % % % % % \begin{macro}{\update@this@float@structure} % Each float box has an associated token register storing several % information fields. % \begin{enumerate} % \item[1] float caption (set by caption command) % \item[2] Currently unused (could have callout page number, set by % |\best@column@or|). % \item[3] saved label string % \item[4] `user counter' number (per-type count) set by float environment. % \item[5] Allowed float areas (from default or optional arg.) % \item[6] float type (currently this is the long name, eg figure) should % probably be the single token name, to allow quicker testing. % \item[7] float sequence number. % \end{enumerate} % % This macro assumes that |\@currbox| is the box number for this structure % \begin{macrocode} \def\update@this@float@structure#1#2#3#4#5#6#7{ \gdef\this@caption{#1} \gdef\this@span@number{#2} \gdef\this@usercnt{#4} \gdef\this@fps{#5} \gdef\this@type{#6} % \end{macrocode} % From the type we infer the class: % \begin{macrocode} \global\expandafter\let\expandafter \this@class\csname sequence@class@#6\endcsname \gdef\this@sequence@number{#7} % \end{macrocode} % If we want to consider all areas for each float (and storing % closed areas via |\closed@|\meta{type}|@areas| we have to % initialise |\this@open@areas| to |\used@areas| (which is % derived from the |area-list| key. % \begin{macrocode} \global\let\this@open@areas\used@areas % \end{macrocode} % % \begin{macrocode} \global\expandafter\let\expandafter\this@closed@areas \csname closed@\this@class @areas\endcsname % FMi tmp \global\let\this@float@box\@currbox %<*trace> \tr@ce{This~float~structure:} \toks@{#1}\tr@ce{~{\the\toks@}} \tr@ce{~{#2}} \tr@ce{~{#3}} \tr@ce{~{#4}} \tr@ce{~{#5}} \tr@ce{~{#6}} \tr@ce{~{#7}} \tr@ce{~this@open@areas~ <-~ \this@open@areas} \tr@ce{~this@closed@areas~ <-~ \this@closed@areas} % %<*progress> \progress{~{#7}} \progress{~{#6}~(\this@class)} \progress{~{#4}} %\progress{~{#2}} %\progress{~{#3}} %\progress{~{#5}} \toks@{#1}\progress@nl{~{\the\toks@}} % } % \end{macrocode} % \end{macro} % % % % \begin{macro}{\extract@this@float@actual@structure} % As used by Chris in xo-final. Should probably be replaced by the % one above or combined with the one above!\footnote{FIX!!} % \begin{macrocode} \def \extract@this@float@actual@structure #1#2#3#4#5#6#7 { \gdef\this@caption{#1} \gdef\this@span@number{#2} \gdef\this@loglabel{#3} \gdef\this@usercnt{#4} \gdef\this@fps{#5} \gdef\this@type{#6} \global\expandafter\let\expandafter \this@class\csname sequence@class@#6\endcsname \gdef\this@sequence@number{#7} } % \end{macrocode} % \end{macro} % % % % \begin{macro}{\update@here@float@structure} % % Similar to |\update@this@float@structure| but filling different % macros.\footnote{We only need some of those macros, so this % should be cleaned up at some stage.} % % This macro assumes that |\@currbox| is the box number for this % structure. % % \begin{macrocode} \def\update@here@float@structure#1#2#3#4#5#6#7{ \gdef\here@span@number{#2} \gdef\here@type{#6} \global\expandafter\let\expandafter \here@class\csname sequence@class@#6\endcsname \gdef\here@sequence@number{#7} \gdef\here@usercnt{#4} % \gdef\here@fps{#5} \gdef\here@caption{#1} \global\let\here@float@box\@currbox %<*trace> \tr@ce{Here~object~structure:} \toks@{#1}\tr@ce~{~{\the\toks@}} \tr@ce{~{#2}} \tr@ce{~{#3}} \tr@ce{~{#4}} \tr@ce{~{#5}} \tr@ce{~{#6}} \tr@ce{~{#7}} % } % \end{macrocode} % \end{macro} % % % % % % % \begin{macro}{\page@float@count} % \begin{macrocode} %\newcount\page@float@count \let\page@float@count\@colnum % \end{macrocode} % \end{macro} % % % \begin{macro}{\this@captioned@float} % \begin{macrocode} \newbox\this@captioned@float % \end{macrocode} % \end{macro} % % % % \newpage % % \subsection{Grab Column Output Routine} % % \begin{description} % \item[Entry:] |\setup@grab@column@or| % \item[Exit:] |\setup@cleanup@or| % \item[Prereq:] % \item[Description:] % \item[Flow:] %\begin{footnotesize} %\begin{verbatim} % \setup@grab@column@or % | % New OR: \grab@column@or % | % V % \grab@column@loop <------- % | % (when entering OR...) % | % % | | % yes no % | | % | % | | | % | yes no % | | | % | | % | | | | % | | yes no % | | | | % | | % | | too early?> | | % | | | | yes no % | | yes no | | % | | | | ? ? % | | | (ignore break) % | | | | % | | | | % (end column now) <------- | % | | % V | % | % | | V % yes no--------------------> (reenter \grab@column@loop) % | % (store results of trial) % | % V % \setup@cleanup@or %\end{verbatim} %\end{footnotesize} % \end{description} % % % % \begin{macro}{\setup@grab@column@or} % % \begin{macrocode} \def\setup@grab@column@or{ %<*trace> \@tracepush{setup@grab@column@or} % % \end{macrocode} % % We just returned to the MVL the current galley. We now add a % special penalty to mark the point that we need to reach in order % to remove everything after the trial run. % This penalty has to be guarded against premature removal, e.g., % if the algorithm would break exactly before it it would then be % discarded which we can't allow.\footnote{Penalty now added % earlier (normally). CORRECT DOCU} % \begin{macrocode} \ifnum\saved@outputpenalty = -1073741824\relax \add@badly@guarded@penalty\output@collect@penalty \fi % \end{macrocode} % % \begin{macrocode} \@failfalse \global\curr@col@count\z@ % \end{macrocode} % In case there is a flush penalty in the collection we have to % find out if we see it again during the trial. So we record the % number of flush points we see during the trial. Same happens for % here points. % \begin{macrocode} \gdef\trial@flush@seen@num{0} \gdef\trial@here@seen@num{0} % \end{macrocode} % % Moved from |\try@this@area| as it should be executed % only if we really do a trial and thus back it out if % unsuccessful---this was a bug as it changed % |\fl@|\meta{col}|@|\meta{type} in cases we never came to this % point here but recursed) % \begin{macrocode} \ifrun@with@floats % \end{macrocode} % Depending on the policy a spanning float can be considered belong % to different columns. This influences the behaviour of the % call-out contraint tests and is determined by the code stored in % |\calculate@target@fl@column|. % \begin{macrocode} \calculate@target@fl@column % \end{macrocode} % |\calculate@target@fl@column| returns its calculated column % number in |\count@|. % \begin{macrocode} \global\expandafter\let\expandafter\saved@fl@ \csname fl@\the\count@ @\this@class\endcsname \global\expandafter\let \csname fl@\the\count@ @\this@class\endcsname \this@sequence@number %<*trace> \tr@ce{~fl@\the\count@ @\this@class\space <-~ \csname fl@\the\count@ @\this@class\endcsname} % % \end{macrocode} % If we are adding to a top area we also have to update the % corresponding |tfl@| commands: % \begin{macrocode} \if t\this@area@type \global\expandafter\let\expandafter\saved@tfl@ \csname tfl@\the\count@ @\this@class\endcsname \global\expandafter\let \csname tfl@\the\count@ @\this@class\endcsname \this@sequence@number %<*trace> \tr@ce{~tfl@\the\count@ @\this@class\space <-~ \csname tfl@\the\count@ @\this@class\endcsname} % \fi \fi % \end{macrocode} % % If we have seen any flush points during collection we need to % save their current |min@col| positions in case we have to throw % away the current trial. % \begin{macrocode} \if@flushseen \count@\z@ \@whilenum \flush@seq@num>\count@ \do { \advance\count@\@ne \global\expandafter\let \csname saved@flush@min@col@\the\count@ \expandafter\endcsname \csname flush@min@col@\the\count@\endcsname %<*trace> \tr@ce{saved@flush@min@col@\the\count@ \space <-~ \csname flush@min@col@\the\count@\endcsname} % } \fi % \end{macrocode} % % \begin{macrocode} \initialise@footins@action % \end{macrocode} % % \begin{macrocode} \global\output{\grab@column@or} \grab@column@loop % \end{macrocode} % % \begin{macrocode} %<*trace> \@tracepop{setup@grab@column@or} % } % \end{macrocode} % \end{macro} % % % % \begin{macro}{\calculate@target@fl@column} % \begin{macro}{\calculate@target@fl@column@flexible} % \begin{macro}{\calculate@target@fl@column@strict} % The purpose of |\calculate@target@fl@column| is to calculate % the column number for which the |\fl@|\meta{col}|@number| has to % be updated in case we place the current float into the area with % start column |\this@area@col@number| and span-number % |\this@area@span@number|. It returns the calculated number in % |\count@|. % % For non-spanning floats it is simply returning % |\this@area@col@number|. If we return this value also in case of % spanning floats then this means that we claim that the float has % be placed the first of its spanned columns. Alternatively we % could return the last of the spanned columns which would if the % |column| policy is in force, allow to place a float into |t12| % even if its call-out is in the second column. % % The real value for |\calculate@target@fl@column| will be assigned % in the page setup template. % \begin{macrocode} \let\calculate@target@fl@column \ERROR % \end{macrocode} % % And here are the two possibilities. % \begin{macrocode} \def\calculate@target@fl@column@flexible { \count@\this@area@col@number\relax \advance\count@\this@area@span@number\relax \advance\count@\m@ne } % \end{macrocode} % % \begin{macrocode} \def\calculate@target@fl@column@strict { \count@\this@area@col@number\relax } % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % % % \begin{macro}{\ifrun@with@floats} % \begin{macro}{\run@with@floatstrue} % \begin{macro}{\run@with@floatsfalse} % % \begin{macrocode} \newif\ifrun@with@floats \def\run@with@floatsfalse{\global\let\ifrun@with@floats\iffalse} \def\run@with@floatstrue{\global\let\ifrun@with@floats\iftrue} % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % % % % \begin{macro}{\grab@column@loop} % The |\grab@column@or| output routine is responsible for % constructing one column of a layout trial. The loop command % increments the column count and sets vsize to the target height % for the current column (which has already been set based on the % size and position of the floats in this trial layout. % \begin{macrocode} \def\grab@column@loop{ %<*trace> \@tracepush{grab@column@loop} % \global\advance\curr@col@count\@ne \global\vsize\csname col@ht@ \the\curr@col@count\endcsname %<*trace> \@tracepop{grab@column@loop} % } % \end{macrocode} % \end{macro} % % % % % % % \begin{macro}{\some@column@or} % |\grab@column@or| and |\best@column@or| are sharing most of their % code which is therefore placed into a separate macro. At the % moment it takes 4 arguments: the name (``grab'' or ``best''), % what to do when we actually finish the column % (``|\grab@column@or@finish|'' or ``|\best@column@or@finish|''), % what to do for a flush point, and what to do when we encounter a % here float.\footnote{This code needs a bit of redesign to deal % properly with the case that we have stumbled upon one of the % special penalties. In this case we need to ensure that we also % remove the special box after the penalty in case we are at a % column break. This is not done right now so that in this case we % will not dicard material at the top of the column properly. FIX!!!!} % \begin{macrocode} \def\some@column@or #1#2#3#4{ %<*trace> \@tracepush{#1@column@or} \tr@ce{output~pen:~ \the\outputpenalty} \tr@ce{#1~ col:~ \the\curr@col@count\space of~ \the\col@count} % \handle@case@of@premature@ending \handle@case@of@forced@pagebreak % \end{macrocode} % If the |\outputpenalty| is |-\output@flush@float@penalty| we % have reached a float flush point in the galley. % \begin{macrocode} \ifnum\outputpenalty=-\output@flush@float@penalty \gincrement@num\trial@flush@seen@num %<*trace> \tr@ce{flush~ point~(\trial@flush@seen@num,~ affects:~ \csname flush@classes@list@\trial@flush@seen@num\endcsname,~ mincol:~ \csname flush@min@col@\trial@flush@seen@num\endcsname,~ lastfloat:~ \csname flush@last@float@\trial@flush@seen@num\endcsname )~ reached} % % \end{macrocode} % We then remove the guard box from the output (which is at the end % of box |\@cclv|. % \begin{macrocode} \remove@guard@box@from@cclv % \end{macrocode} % If the flush penalty moved to an earlier column than in the last % trial we end the current column (by calling % |\#1@column@or@finish|) and reinsert the penalty so that it will % be seen again if we do the next column. % \begin{macrocode} \ifnum\csname flush@min@col@\trial@flush@seen@num\endcsname > \curr@col@count %<*trace> \tr@ce{flush@min@col@\trial@flush@seen@num\space >~ curr@col@count~ (\csname flush@min@col@\trial@flush@seen@num\endcsname \space >~ \the\curr@col@count)~ ->~ ending~ column} % \gdecrement@num\trial@flush@seen@num \readd@guarded@penalty\output@flush@float@penalty #2 \else % \end{macrocode} % Otherwise the flush point is in an acceptable position which % means we ignore it and carry on collecting material for the % current column. This is done be putting everything back onto the % MVL except the guard box and the penalty.\footnote{We lose a % potential break point here (acceptable?) See comments in % best@column@or!!} % \begin{macrocode} %<*trace> \tr@ce{flush@min@col@\trial@flush@seen@num\space <=~ curr@col@count~ (\csname flush@min@col@\trial@flush@seen@num\endcsname \space <=~ \the\curr@col@count)} % % \end{macrocode} % What exactly happens here (beside the above) depends on the % calling macro. % \begin{macrocode} #3 \fi \else % \end{macrocode} % If it was not a flush point we might have a here point to take % care of. This is more or less like the code above. % \begin{macrocode} \ifnum\outputpenalty=-\output@here@float@penalty \gincrement@num\trial@here@seen@num %<*trace> \tr@ce{here~ penalty~(\trial@here@seen@num)~ reached} % \remove@guard@box@from@cclv \ifnum\csname here@min@col@\trial@here@seen@num\endcsname > \curr@col@count %<*trace> \tr@ce{here@min@col@\trial@here@seen@num\space >~curr@col@count~ (\csname here@min@col@\trial@here@seen@num\endcsname \space >~ \the\curr@col@count)~ ->~ ending~ column} % \split@off@last@line \gdecrement@num\trial@here@seen@num \readd@guarded@penalty\output@here@float@penalty #2 \else \@tempdima \pagegoal \advance\@tempdima -\pagetotal \ifdim \@tempdima < \csname here@required@space@\trial@here@seen@num \endcsname \relax %<*trace> \tr@ce{here@required@space@\trial@here@seen@num\space >~ \pagegoal-\pagetotal \space (\csname here@required@space@\trial@here@seen@num\endcsname \space >~ \the\pagegoal\space -~ \the\pagetotal\space =~ \the\@tempdima)~ ->~ ending~ column} % \split@off@last@line \gdecrement@num\trial@here@seen@num \readd@guarded@penalty\output@here@float@penalty #2 \else %<*trace> \tr@ce{here@required@space@\trial@here@seen@num\space <=~ \pagegoal-\pagetotal \space (\csname here@required@space@\trial@here@seen@num\endcsname \space <=~ \the\pagegoal\space -~ \the\pagetotal\space =~ \the\@tempdima)~ ->~ accepting~ here~ point} % \@reinserts \unvbox\@cclv \@next\@currbox\@herelist{ %<*trace> \tr@ce{@currbox:~ \@currbox} % \expandafter\update@here@float@structure\the\toks\@currbox % \end{macrocode} % Different things need to be done depending on the type of the % here point: % \begin{macrocode} \def\@tempa{mpar} \ifx\@tempa\here@type \typeset@a@marginpar \else \def\@tempa{rspace} \ifx\@tempa\here@type % do nothing \else #4 \fi \fi } % \end{macrocode} % If there is no here object left the algorithm has screwed up % (i.e., a ``this can't happen'' situation). % \begin{macrocode} \ERROR \fi \fi \else % \end{macrocode} % If it is neither a flush nor a here point it might be a grid point: % \begin{macrocode} \ifnum\outputpenalty=-\output@grid@align@penalty \align@collected@galley@and@restart % \end{macrocode} % So we now know that it wasn't one of our special points so this % must have been a normal end of the galley: % \begin{macrocode} \else #2 \fi \fi \fi %<*trace> \@tracepop{#1@column@or} % } % \end{macrocode} % \end{macro} % % % % % \begin{macro}{\grab@column@or} % Here is the output routine used during trials, an instantiation % of |\some@column@or|. % \begin{macrocode} \def\grab@column@or{\some@column@or{grab} \grab@column@or@finish \grab@column@or@flushcheck \check@and@typeset@a@here@float } % \end{macrocode} % \end{macro} % % % \begin{macro}{\grab@column@or@flushcheck} % % The |\grab@column@or@flushcheck| code checks for restrictions % regarding the placement of the current float. It is called when % we just have encountered a flush float penalty while grabbing the % text for a column and now have to see which floats (if any) need % to be positioned before that flush point. % \begin{macrocode} \def\grab@column@or@flushcheck{ %<*trace> \@tracepush{grab@column@or@flushcheck} % % \end{macrocode} % If we are making a dry-run without floats then there is no need to % do much, so we skip all testing that involves flush points and % only do the cleanup actions at the end. % \begin{macrocode} \ifrun@with@floats \expandafter\xin@\expandafter\this@class \csname flush@classes@list@\trial@flush@seen@num\endcsname \ifin@ %<*trace> \tr@ce{flush:~ class~ \this@class\space in~ {\csname flush@classes@list@\trial@flush@seen@num\endcsname}} % % \end{macrocode} % We store in |\count@| the float sequence number of the last float % that would be affected by the current flush penalty. This value % is then used in the tests below. % \begin{macrocode} \count@\csname flush@last@float@\trial@flush@seen@num\endcsname\relax % \end{macrocode} % % If the current float number is higher than float number stored in % |\flush@last@float@|\meta{num} with the flush penalty, we are % dealing with a float whose call-out is after the flush penalty % and thus we have no restriction. % \begin{macrocode} \ifnum\this@sequence@number>\count@ %<*trace> \tr@ce{???:\this@sequence@number>\the\count@} \tr@ce{this~float~ past~flush~point} % \else % \end{macrocode} % Otherwise check if this float is placed in an acceptable position % with respect to the current flush point. For this we run % different code depending on the ``fuzziness'' of the flush point % under check: % \begin{macrocode} \csname flush@fuzziness@\trial@flush@seen@num \endcsname \fi %<*trace> \else \tr@ce{flush:~ class~ \this@class\space not~ in~ {\csname flush@classes@list@\trial@flush@seen@num\endcsname}} % \fi \fi % \end{macrocode} % If we failed above we additionally record that the failure is % due to violating restrictions for a flush point. % \begin{macrocode} \if@fail \@flushfailtrue % \end{macrocode} % % \begin{macrocode} \global\setbox\@cclv\box\voidb@x \global\setbox\footins\box\voidb@x % \end{macrocode} % We have to immediately abort the current trial otherwise a % flush point following in the galley might be encountered and % processed before we reach |\evaluate@results@of@trial|. That % would result in updating the wrong data structure there (due to % the fact that there it assumes that |\trial@flush@seen@num| % refers to the flush point that is the reason for % failure).\footnote{Implementation could be improved!} % \begin{macrocode} \global\curr@col@count\col@count \grab@column@or@finish \else % \end{macrocode} % If we haven't failed we might have to update the % |\flush@min@col|\meta{num} for the current flush point in case it % moved to a new column. % \begin{macrocode} \ifnum\csname flush@min@col@\trial@flush@seen@num\endcsname<\curr@col@count \expandafter\xdef \csname flush@min@col@\trial@flush@seen@num\endcsname {\the\curr@col@count} %<*trace> \tr@ce{set~ flush@min@col@\trial@flush@seen@num:~ \csname flush@min@col@\trial@flush@seen@num\endcsname} % \fi % \end{macrocode} % We have to return the collected footnotes first or else \TeX{} % might decide that it is better to break before % them.\footnote{Quite likely that this needs some refinement as it % might mess up vertical spacing in other respects. Look out for % other places where \texttt{\string\@reinserts} is used, if this % needs fixing.} % \begin{macrocode} \@reinserts \unvbox\@cclv % \end{macrocode} % What penalty to return???\footnote{FIX!!!} % \begin{macrocode} % \penalty\z@ % none i think now (in the current version) but this % will change again \fi %<*trace> \@tracepop{grab@column@or@flushcheck} % } % \end{macrocode} % \end{macro} % % % % % % \begin{macro}{\flushcheck@page} % \begin{macrocode} \def\flushcheck@page { %<*trace> \tr@ce{OK:~flush~check~ (same~page)} % } % \end{macrocode} % \end{macro} % % \begin{macro}{\flushcheck@spread} % % This is actually a dummy definition. There is more to do if we % want to provide support for spreads!\footnote{Finish implementation} % \begin{macrocode} \def\flushcheck@spread { %<*trace> \tr@ce{OK:~flush~check~ (using~page~not~ spread)} % } % \end{macrocode} % \end{macro} % % % \begin{macro}{\flushcheck@strict} % \begin{macrocode} \def\flushcheck@strict { %<*trace> \@tracepush{flushcheck@strict} % % \end{macrocode} % If strict flushing is required we look where the current float is % being placed. If it % is placed in a column which is earlier than the current column % then it is definitely before the flush point and thus we are okay. % \begin{macrocode} \ifnum\this@area@col@number<\curr@col@count %<*trace> \tr@ce{OK:~flush~check~ (\this@area@col@number<\the\curr@col@count,~\this@area)} % \else % \end{macrocode} % Otherwise we test if the float is placed into the current % column. If this is the case it might be okay, but only if it is % not placed into the bottom area. % \begin{macrocode} \ifnum\this@area@col@number=\curr@col@count % \end{macrocode} % To test for the bottom area(s) means looking at the first token % in the area identifier. If it is |b| we are past the flush % point.\footnote{It might be an interesting extension to allow % relaxing the flush situation to allow the floats to appear % anywhere on the current column (on which the flush point ends up), % or even allowing that it only has to appear on the current page % or page spread.} % \begin{macrocode} \if b \this@area@type \@failtrue %<*progress> \progress@failed{area~ below~ flush~ point~ (\this@area@col@number=\the\curr@col@count,~\this@area)} % %<*trace> \tr@ce{Fail:~flush~check~ (\this@area@col@number=\the\curr@col@count,~\this@area)} % \end{macrocode} % Otherwise the float was placed into an area that is still before % the flush point. % \begin{macrocode} \else \tr@ce{OK:~flush~check~ (\this@area@col@number=\the\curr@col@count,~\this@area)} % \fi % \end{macrocode} % If the float was neither placed before nor into the current % column we have to conclude that it was placed into a later column % which means it was placed after the flush point --- thus we fail. % \begin{macrocode} \else \@failtrue %<*progress> \progress@failed{area~ after~ flush~ point~ (\this@area@col@number>\the\curr@col@count,~\this@area)} % %<*trace> \tr@ce{Fail:~flush~check~ (\this@area@col@number>\the\curr@col@count,~\this@area)} % \fi \fi %<*trace> \@tracepop{flushcheck@strict} % } % \end{macrocode} % \end{macro} % % \begin{macro}{\flushcheck@column} % \begin{macrocode} \def\flushcheck@column { \ifnum\this@area@col@number>\curr@col@count \@failtrue %<*progress> \progress@failed{area~ after~ flush~ point~ column~ (\this@area@col@number>\the\curr@col@count,~\this@area)} % %<*trace> \tr@ce{Fail:~flush~check~ (\this@area@col@number>\the\curr@col@count,~\this@area)} \else \tr@ce{OK:~flush~check~ (\this@area@col@number<=\the\curr@col@count,~\this@area)} % \fi } % \end{macrocode} % \end{macro} % % % % % \begin{macro}{\grab@column@or@finish} % \begin{macrocode} \def\grab@column@or@finish{ %<*trace> \@tracepush{grab@column@or@finish} % % \end{macrocode} % % \begin{macrocode} \mark@update@structure % \end{macrocode} % % \begin{macrocode} \deal@with@footins@action % \end{macrocode} % % First check if there are some special constraints that should be % met (this is, for example, used to check if there are both bottom % floats and footnotes). If the constraints are not met don't % bother to check the callout/float constraints. % \begin{macrocode} \if@fail\else \ifrun@with@floats \check@some@constraints \fi \fi \if@fail\else % \end{macrocode} % For each float sequence class, call |\check@callout@constraints| % this will be set via a call to a pagesetup template to do an % appropriate check on the float placement relative to float % call-out. % \begin{macrocode} \ifrun@with@floats \let\@elt\check@callout@constraints \float@classes@list \fi \fi % \end{macrocode} % % Throw the text away (it will be reset later if this trial is % in fact chosen). % \begin{macrocode} \global\setbox\@cclv\box\voidb@x \global\setbox\footins\box\voidb@x % \end{macrocode} % After the last column we evaluate the results of the trial (and % if the result looks ok remember it as a candidate for the final % solution). We then switch to the `clean up' OR which will % collect up the main vertical list as far as the special penalty % marking the end of the collection pass, to clear the MVL for the % next trial. If this isn't the last column, set up the next % column. % \begin{macrocode} \ifnum\curr@col@count=\col@count \evaluate@results@of@trial \setup@cleanup@or \else \grab@column@loop \fi %<*trace> \@tracepop{grab@column@or@finish} % } % \end{macrocode} % \end{macro} % % % % % \begin{macro}{\handle@case@of@premature@ending} % Next |\ifnum| is a fix that needs rethinking: what is the best % approach if we hit the penalty which denotes the end of the % collected galley too early, e.g., in the middle of a trial using % |\grab@column@or| or when producing the final columns with % |\best@column@or|? Current solution gets the stuff out, but is it % probably not the best solution. % correct? % \begin{macrocode} \def\handle@case@of@premature@ending{ \ifnum\outputpenalty=-\output@collect@penalty \remove@guard@box@from@cclv \readd@guarded@penalty\output@collect@penalty \fi } % \end{macrocode} % \end{macro} % % % % \begin{macro}{\check@some@constraints} % By default there are no additional constraints to check for. % \begin{macrocode} \let\check@some@constraints\relax % \end{macrocode} % \end{macro} % % % % \begin{macro}{\evaluate@results@of@trial} % % The purpose of |\evaluate@results@of@trial| is to determine if % the current trial is a potential candiate for the final solution % and if so store it away. We can determine if the trial failed by % looking at the switch |@fail|. % \begin{macrocode} \def\evaluate@results@of@trial{ %<*trace> \@tracepush{evaluate@results@of@trial} % % \end{macrocode} % % \begin{macrocode} \ifrun@with@floats \ifx\try@this@area\std@try@this@area \count@\trial@here@seen@num\relax \advance\count@\page@float@count \ifnum \pagesetup@max@float@num < \count@ %<*trace> \tr@ce{Failed:~ area~ +~ here~ floats~ exceed~ max~ floats} % %<*progress> \progress@failed{area~ +~ here~ floats~ exceed~ max~ floats} % \@failtrue \fi \fi \fi % \end{macrocode} % % \begin{macrocode} \if@fail %<*trace> \tr@ce{fail:~true} % % \end{macrocode} % If the trial has failed we have to distinguish two cases: % \begin{itemize} % \item % There has been a request for flushing out floats up to a % certain float somewhere % and the current float belongs to the list of floats to flush. % \item % There has been no such request. % \end{itemize} % % If there have been flush points we need to restore their % |min@col| values since we might have updated them. % \begin{macrocode} \if@flushseen \count@\z@ \@whilenum \flush@seq@num>\count@ \do { \advance\count@\@ne \global\expandafter\let \csname flush@min@col@\the\count@ \expandafter\endcsname \csname saved@flush@min@col@\the\count@\endcsname %<*trace> \tr@ce{flush@min@col@\the\count@ \space <-~ \csname flush@min@col@\the\count@\endcsname \space (restore) } % } \fi \if@flushfail %<*trace> \tr@ce{flushfail:~true} % % \end{macrocode} % If we have failed and |\try@this@area| is already the ``relaxed'' % version we have to artificially move the offending flush point to % the next column and hope that this way we get ourselves some new % options (worst case is that eventually the flush point is removed % from the page in which case we can as a last resort defer the % float). % \begin{macrocode} \ifx\try@this@area\relaxed@try@this@area \expandafter\gincrement@num \csname flush@min@col@\trial@flush@seen@num\endcsname %<*trace> \tr@ce{flush@min@col@\trial@flush@seen@num~ <-~ \csname flush@min@col@\trial@flush@seen@num\endcsname} % %<*progress> \progress@failed{flush~ point~ \trial@flush@seen@num\space moved~ to~ column~ \csname flush@min@col@\trial@flush@seen@num\endcsname} % \else \ifx\saved@this@open@areas\@empty %<*debug> \tr@ce{saved@this@open@areas:~empty ????????} % \ERROR \else \global\let\this@open@areas\saved@this@open@areas %<*trace> \tr@ce{~this@open@areas~ <-~ \this@open@areas \space (reopen)} % \fi \relax@float@placement@conditions \fi \else %<*trace> \tr@ce{flushfail:~false} % \xdef\this@open@areas{\expandafter\@gobblethree\this@open@areas} \fi %<*trace> \tr@ce{open:~\this@open@areas} \tr@ce{restore:~last~allocated:~\saved@fl@} % % \end{macrocode} % To restore the previous state we have to recalculate the target % |fl@| column. % \begin{macrocode} \calculate@target@fl@column \global\expandafter\let \csname fl@\the\count@ @\this@class\endcsname \saved@fl@ %<*trace> \tr@ce{~fl@\the\count@ @\this@class\space <-~ \saved@fl@ \space (restored)} % % \end{macrocode} % And if we tried a top area we also have to restored the % corresponding |tfl@| macro. % \begin{macrocode} \if t\this@area@type \global\expandafter\let \csname tfl@\the\count@ @\this@class\endcsname \saved@tfl@ %<*trace> \tr@ce{~tfl@\the\count@ @\this@class\space <-~ \saved@tfl@ \space (restored)} % \fi % \end{macrocode} % And we better don't forget to restore the heights.\footnote{This % is most likely buggy: I seem to restore all column values but i think % i don't save all of them! FIX!!!!} % \begin{macrocode} \update@this@area@columns { %<*trace> \tr@ce{restore:~saved@col@ht@ \the\count@:~ \csname saved@col@ht@ \the\count@\endcsname} % \global\csname col@ht@ \the\count@\endcsname \csname saved@col@ht@ \the\count@\endcsname\relax \global\expandafter\let \csname col@ \this@area@type @delta@ \the\count@ \expandafter \endcsname \csname saved@col@ \this@area@type @delta@ \the\count@ \endcsname %<*trace> \tr@ce{GRID (delta):~ column~\the\count@\this@area@type:~ \csname saved@col@ \this@area@type @delta@ \the\count@ \endcsname\space (restore) } % } \else %<*trace> \tr@ce{fail:~false} % % \end{macrocode} % % \begin{macrocode} %<*progress> \let\progress@inform@later\@empty % % \end{macrocode} % If this trial is valid and we haven't seen all flush penalties % again we must have pushed them to the next page. We record % this fact by setting |flush@min@col@...| to |\maxdimen|. % \begin{macrocode} \if@flushseen \count@\flush@seq@num\relax \loop \ifnum \trial@flush@seen@num < \count@ \global\@namedef{flush@min@col@\the\count@}{\maxdimen} %<*trace> \tr@ce{flush@min@col@\the\count@\space <-~ maxdimen} % \advance\count@\m@ne \repeat % \end{macrocode} % If there has been a flush point (ie if |\trial@flush@seen@num| und % thus |\count@| is greater than 0) we test whether or not the % float recently placed was the last one affected by the last flush % point on the current page and if so tighten the float placement % setting again.\footnote{correct logic?} % \begin{macrocode} %<*progress> \let\progress@inform@later\@empty % \ifrun@with@floats \ifnum \count@ > \z@ \ifnum \csname flush@last@float@\trial@flush@seen@num\endcsname = \this@sequence@number \relax %<*trace> \tr@ce{flush:~ last~float~affected~ by~ flush~ point~ \trial@flush@seen@num\space placed~ ->~ use~ partly~ normal~ placement~ conditions~ again} % %<*progress> \def\progress@inform@later{ \progress@nl{->~ past~ flush~ point:~ -->~ tighten~ conditions~ again} \progress@nl{} } % \partly@tighten@float@placement@conditions \fi \fi \fi % \end{macrocode} % Having placed a float we need to update |\flush@classes@list@max| to % reflect which float types are affected by the flush points % currently on the page as this might be needed when trying to % place or rather defer the next float. % % So we loop and concatenate all |\flush@classes@list@|\meta{num} that % belong to flush points on the current page. This might result in % the list containing types several times but for the test we need % to do this doesn't make any difference (and it is far faster than % unifying the list). % \begin{macrocode} \count@\z@ \global\let\flush@classes@list@max\@empty \loop \ifnum \trial@flush@seen@num > \count@ \advance\count@\@ne \xdef\flush@classes@list@max{ \flush@classes@list@max; \csname flush@classes@list@\the\count@\endcsname } %<*trace> \tr@ce{flush@classes@list@max~ <-~ \flush@classes@list@max} % \repeat \fi % \end{macrocode} % % With this algorithm a trial which passed so far is always % considered to be better than previous trials (meaning more floats % on the page are better). So we always update the best trial data % (unless this was the run without adding floats in which case we % only change the |run@with@floats| switch. % \begin{macrocode} \ifrun@with@floats \update@best@trial %<*progress> \progress@inform@later % \else \run@with@floatstrue \fi \fi %<*trace> \@tracepop{evaluate@results@of@trial} % } % \end{macrocode} % \end{macro} % % % % % \subsection{Best Trial Data} % % % \begin{macro}{\best@trial} % \begin{macrocode} \let\best@trial\@empty % \end{macrocode} % \end{macro} % % \begin{macro}{\update@best@trial} % Not all of this belongs into this macro!\footnote{redistribute} % \begin{macrocode} \def\update@best@trial{ %<*trace> \@tracepush{update@best@trial} % %<*progress> \progress@nl{->~ accepted} % \global\let\best@trial\@empty \forall@columns{ \expandafter \g@addto@macro\expandafter\best@trial\expandafter { \expandafter \global \csname col@ht@ \the\curr@col@count\expandafter\endcsname \the\csname col@ht@ \the\curr@col@count\endcsname } } % \end{macrocode} % % Frank says this needs to be documented (the rest of the code is self evident) % |\this@float@box| is |\let| to |\@currbox| which is defed to a chardefed % token from newinsert. so this is OK. honest. % \begin{macrocode} \expandafter\@cons\csname area@\this@area\expandafter\endcsname \this@float@box % \end{macrocode} % % \begin{macrocode} %<*trace> \tr@ce{this@page@closed~ \this@page@closed\space +~ "\csname pagesetup@\this@area @all@close\endcsname"} \tr@ce{this@closed@areas~ \this@closed@areas\space +~ "\csname pagesetup@\this@area @class@close\endcsname"} % \xdef\this@page@closed{\this@page@closed, \csname pagesetup@\this@area @all@close\endcsname} \xdef\this@closed@areas{\this@closed@areas, \csname pagesetup@\this@area @class@close\endcsname} % \end{macrocode} % % \begin{macrocode} \global\expandafter\let\csname open@\this@class @areas\endcsname % FMi tmp \this@open@areas \global\expandafter\let\csname closed@\this@class @areas\endcsname % FMi tmp \this@closed@areas % \end{macrocode} % moving the captioned float to the main float box is put into a % separate macro so that we can suppress this in cases where we % potentially want to revert to a previous stage.\footnote{FIX} % \begin{macrocode} %<*obsolete> \add@caption@to@float@box % % \end{macrocode} % % \begin{macrocode} \global\advance\page@float@count\@ne \global\advance\csname \this@area @float@count\endcsname\@ne % \end{macrocode} % % Since the trial was successful, we have to update the the macros % that hold the number of top or bottom floats we have seen so far % in each column.\footnote{Code for this is similar to the one in % construct@and@test@col@ht and elsewhere; perhaps there should be % a subroutine for it!} % \begin{macrocode} \update@this@area@columns { \expandafter \gincrement@num \csname col@ \this@area@type @floats@ \the\count@ @number\endcsname %<*trace> \tr@ce{col@ \this@area@type @floats@ \the\count@ @number <-~ \csname col@ \this@area@type @floats@ \the\count@ @number\endcsname} % } % \end{macrocode} % % \begin{macrocode} %<*trace> \tr@ce{\meaning\best@trial} \tr@ce{area:~\this@area\space\csname area@\this@area\endcsname} \@tracepop{update@best@trial} % } % \end{macrocode} % \end{macro} % % \begin{macro}{\add@caption@to@float@box} % This is a hook really to be able to prevent moving the caption % back into |\this@float@box| (by making this macro |\relax| and % this is what happens later on in xo-final). Yes we know the % coding here needs changing!\footnote{David FIX!!!} % \begin{macrocode} %<*obsolete> \def\add@caption@to@float@box{ \global\setbox\this@float@box\box\this@captioned@float } % % \end{macrocode} % \end{macro} % % % \newpage % % \subsection{Best Column Output Routine} % % \begin{description} % \item[Entry:] |\setup@best@column@or| % \item[Exit:] |\setup@collection@or| % \item[Prereq:] % \item[Description:] % \item[Flow:] %\begin{footnotesize} %\begin{verbatim} % \setup@best@column@or % | % New OR: \best@column@or % | % V % \best@column@loop <------- % | % (when entering OR...) % | % % | | % yes no % | | % | % | | | % | yes no % | | | % | | % | | | | % | | yes no % | | | | % | | % | | too early?> | | % | | | | yes no % | | yes no | | % | | | | ? ? % | | | (ignore break) % | | | | % | | | | % | | | | % | | | | % | | | | % | | | | % | | | | % | | | | % | | | | % (end column now) <------- | % | | % V | % | % | | V % yes no--------------------> (reenter \best@column@loop) % | % (produce final page) % | % V % \initialise@next@page % | % V % (try to make float pages) % | % V % \setup@collection@or %\end{verbatim} %\end{footnotesize} % \end{description} % % % After the best trial is chosen the `best@column@or' output routines % are executed. Structurally this is similar to the grab column output % routines used during the trials, but this time information % about the float placements is recorded in the float area lists % and also optionally in float placement control files. % % \begin{macro}{\setup@best@column@or} % This is the initialisation code for producing the final best set % of columns (via the @best@column@or output routine). % \begin{macrocode} \def\setup@best@column@or{ %<*trace> \@tracepush{setup@best@column@or} % Elsewhere now: % \tr@ce{reinsert~penalty:~ \saved@outputpenalty\space (unless~ 10000)} % % \penalty % \ifnum\saved@outputpenalty=\@M % \z@ % \else % \saved@outputpenalty\relax % \fi \global\curr@col@count\z@ \gdef\trial@flush@seen@num{0} \gdef\trial@here@seen@num{0} \perhaps@write@placements@to@fpl@file \best@trial % \end{macrocode} % % \begin{macrocode} \initialise@footins@action % \end{macrocode} % % \begin{macrocode} \global\output{\best@column@or} \best@column@loop %<*trace> \@tracepop{setup@best@column@or} % } % \end{macrocode} % \end{macro} % % % \begin{macro}{\best@column@loop} % \begin{macrocode} \def\best@column@loop{ %<*trace> \@tracepush{best@column@loop} % \global\advance\curr@col@count\@ne \global\vsize\csname col@ht@ \the\curr@col@count\endcsname %<*trace> \tr@ce{vsize~ <-~ \the\vsize } \@tracepop{best@column@loop} % } % \end{macrocode} % \end{macro} % % % % \begin{macro}{\best@column@or} % Here is the output routine used when preparing the final columns, % an instantiation of |\some@column@or|. In contrast to the version % used for |\grab@column@or| it doesn't do the tests. % \begin{macrocode} \def\best@column@or{\some@column@or{best} \best@column@or@finish { \@reinserts \unvbox\@cclv % \end{macrocode} % Next line not okay! we need to add a penalty here but which one? % Or we need a different mechanism using either |\holdinginserts| % or a partial box line in collection OR.\footnote{FIX!!! there is % also another place like this!} % \begin{macrocode} % \penalty\z@ %FMi? } { \perhaps@write@to@fpl@file{ \@spaces Area:~hhh^^J \expandafter\perhaps@write@placements@to@fpl@file@aux\the\toks\@currbox} \typeset@a@here@float } } % \end{macrocode} % \end{macro} % % % % % % % \begin{macro}{\best@column@or@finish} % % \begin{macrocode} \def\best@column@or@finish{ %<*trace> \@tracepush{best@column@or@finish} % \mark@update@structure % \end{macrocode} % % \begin{macrocode} \deal@with@footins@action % \end{macrocode} % % save all marks here\footnote{not done yet!} % % add floats and footnotes etc to collected column % % \begin{macrocode} \produce@final@column % \end{macrocode} % % \begin{macrocode} \ifnum\curr@col@count=\col@count \produce@final@page \initialise@next@page \try@float@pages \place@deferred@floats \setup@collection@or %{\showoutput\showlists} \else \best@column@loop \fi %<*trace> \@tracepop{best@column@or@finish} % } % \end{macrocode} % \end{macro} % % % \begin{macro}{\initialise@next@page} % Initialises the column heights to text height. Clear the float % area lists, zero holdinginserts to allow footnote texts to arrive % in the insertion box. % \begin{macrocode} \def\initialise@next@page{ %<*trace> \@tracepush{initialise@next@page} % % % \end{macrocode} % % \begin{macrocode} \initialise@column@data % \end{macrocode} % % \begin{macrocode} \initialise@areas % \end{macrocode} % % \begin{macrocode} \global\page@float@count\z@ % \end{macrocode} % % \begin{macrocode} \initialise@flush@data % \end{macrocode} % % \begin{macrocode} \initialise@here@data % \end{macrocode} % % \begin{macrocode} \initialise@footins@action % \end{macrocode} % % Nothing is closed when we are at the start of a page. % \begin{macrocode} \global\let\this@page@closed\@empty % \end{macrocode} % % \begin{macrocode} \let\@elt\initialise@float@class \float@classes@list \let\@elt\relax % %\showfloatlists %\show\area@ddd\show\@activelist % for safety \global\let\this@float@box\@undefined %<*trace> \@tracepop{initialise@next@page} % } % \end{macrocode} % \end{macro} % % % % % \begin{macro}{\handle@case@of@forced@pagebreak} % This is related to |\handle@case@of@premature@ending| but we have % to return the penalty only if we haven't reached the last column. % If we don't do this we would start collecting material in the % middle of final page generation! % \begin{macrocode} \def \handle@case@of@forced@pagebreak{ \ifnum\curr@col@count<\col@count \ifnum\outputpenalty=-\@M \@emptycol \fi \fi \ifnum\outputpenalty=-\output@balance@penalty %<*trace> \tr@ce{BALANCE:~ end~ point~ seen~ again} % \remove@guard@box@from@cclv \ifnum\curr@col@count<\col@count \@emptycol \fi \fi } % \end{macrocode} % \end{macro} % % % % \newpage % % \subsection{Cleanup Output Routine} % % \begin{description} % \item[Entry:] |\setup@cleanup@or| % \item[Exit:] |\float@placement@loop| % \item[Prereq:] % \item[Description:] % Responsible for discarding unused text still on Main Vertical % List After the end of a trial. It eats everything until it sees % the special penalty marking the end of the last collection output % routine. This output routine may need to be called several times % in succession due to forced penalties in the galley. % \item[Flow:] %\begin{footnotesize} %\begin{verbatim} % \setup@cleanup@or % | % V % New OR: \cleanup@or % | % V % --> \float@placement@loop %\end{verbatim} %\end{footnotesize} % \end{description} % % % \begin{macro}{\setup@cleanup@or} % \begin{macrocode} \def\setup@cleanup@or{ \global\vsize\maxdimen \global\output{\cleanup@or} } % \end{macrocode} % \end{macro} % % % \begin{macro}{\cleanup@or} % In the actual output routine we grab text and throw it away until % we see the special output penalty. Then we prepare for the trials % to place the floats properly. % \begin{macrocode} \def\cleanup@or{ %<*trace> \@tracepush{cleanup@or} \tr@ce{output~pen:~ \the\outputpenalty} % % \end{macrocode} % Throw everything away \ldots % \begin{macrocode} \global\setbox\@cclv\box\voidb@x \global\setbox\footins\box\voidb@x % \end{macrocode} % \ldots\ until we see the special output penalty again. % \begin{macrocode} \ifnum\outputpenalty=-\output@collect@penalty \float@placement@loop \fi %<*trace> \@tracepop{cleanup@or} % } % \end{macrocode} % \end{macro} % % % \newpage % % \subsection{Making float pages} % % % \begin{description} % \item[Entry:] |\try@float@pages| % \item[Exit:] --- (this happens within the OR)\\ % On exit |\area@ddd| will be empty and the floats not being put % onto float pages are moved to |\@activelist| (those that have % their call outs on previous pages) and |\@mvllist| (those that % have their call outs still on the MVL). % \item[Prereq:] |\area@ddd| contains the float to work on; all other % areas are empty. % \item[Description:] % \item[Flow:] %\begin{footnotesize} %\begin{verbatim} % \try@float@pages % | % V % <\area@ddd has floats?> % | | % ----no yes % | | % | V % | (split \area@ddd into \@activelist and \@mvllist; % | setup trial conditions) % | | % | V % | \try@float@page <------------- % | | | % | | % | | | | % | no yes | % | | | | % | | (output page) | % | | | | % | | (move new \area@ddd | % | | to \@activelist) | % | | | | % | | ------------------ % | | % | | % | (restore float conditions before last trial) % | | % | (restore trial condition to normal) % | | % ------------->| % | % V %\end{verbatim} %\end{footnotesize} % \end{description} % % % % \begin{macro}{\try@float@pages} % % \begin{macrocode} \def\try@float@pages { %<*trace> \@tracepush{try@float@pages} % \ifx\area@ddd\@empty %<*trace> \tr@ce{no~ deferred~ floats} % \else \global\let\@activelist@empty@action\relax \global\let\pretests@success@action\floatpage@pretests@success@action % \end{macrocode} % this is only a tmp: we just use |\relaxed@try@this@area| but of % course there should be different rules for float pages (and % different float areas and \ldots) % \begin{macrocode} \global\let\try@this@area\relaxed@try@this@area % \end{macrocode} % % First thing to do is to split the list of deferred floats into % those that have ther callouts already typeset (on previous pages) % and those that we have only seen because we looked a bit % ahead. For making float pages we can only use the former. % \begin{macrocode} \let\@elt\split@defer@list \area@ddd \let\@elt\relax \global\let\area@ddd\@empty % \end{macrocode} % Now we loop until we fail to make float pages. The actual work is % done in the macro |\try@float@page|. % \begin{macrocode} \@floatpagetrue \loop \if@floatpage \begingroup % no nesting of \loop without grouping ... % \end{macrocode} % Next line prevents adding the caption to the float box. Of course % the float page does come out even worse this way, but we don't % get multiple captions if float page generation % fails.\footnote{FIX by redesigning caption handling!} % \begin{macrocode} %<*obsolete> \let\add@caption@to@float@box\relax %tmp!! % % \end{macrocode} % % A bit statistics: how many floats do we have on the % |\@activelist|? % \begin{macrocode} %<*progress> \def\@elt{\global\advance\trial@count\@ne\@gobble} \@activelist \let\@elt\relax \progress@nl{} \progress@separator \progress@nl{STATS:~ floats~ waiting~ =~ \the\trial@count \space on~ page~ \the\absolute@page@number\space (float~ page)} \progress@separator \global\trial@count\z@ % % \end{macrocode} % \begin{macrocode} \try@float@page \endgroup \repeat % \end{macrocode} % Once we are finished we have to return to normal trial % conditions, so\ldots % \begin{macrocode} \global\let\try@this@area\std@try@this@area \fi %<*trace> \@tracepop{try@float@pages} % } % \end{macrocode} % \end{macro} % % % % \begin{macro}{\try@float@page} % This macro tries to build a single float page from the floats in % |\@activelist|. If it fails it (tries to) restores the state of % the floats. If it succeeds it will output a float page and returns. % \begin{macrocode} \def\try@float@page { %<*trace> \@tracepush{try@float@page} % % \end{macrocode} % Save the current state in case of failure then run the float % placement loop (setup for this loop should have happened % earlier). % \begin{macrocode} \save@current@float@state \trial@inner@loop % %\typeout{float.list.after.trial} %\showfloatlists % % \end{macrocode} % Loop through all ``text columns'' and add up their heights. This % is again only done to have some sort of measure for float pages % and should be removed once some real code gets into this part. % \begin{macrocode} \dimen@\z@ \forall@columns{ %<*trace> \tr@ce{\ht\the\curr@col@count=\the \csname col@ht@ \the\curr@col@count \endcsname} % \advance\dimen@ \csname col@ht@ \the\curr@col@count \endcsname } % \end{macrocode} % % If the sum of all white space is more than 300pt :-) % \begin{macrocode} \ifdim \dimen@ > 300pt \relax % \end{macrocode} % we fail % \begin{macrocode} \@floatpagefalse %<*trace> \tr@ce{float~page~failed} % %<*progress> \progress@failed{no~ float~ page~ made} \progress@nl{} % % \end{macrocode} % Return to the previous state (and as can be seen by using % |\initialise@next@page|) this needs some work; the latter might % in fact do too much like calling % |\initialise@flush@num|!\footnote{FIX} % \begin{macrocode} \saved@float@state % \end{macrocode} % To avoid having |\initialise@flush@num| do anything harmful we % set |\trial@flush@seen@num| to zero at this point.\footnote{This % needs fixing properly!} And the same is necessary for % |\initialise@here@num|. % \begin{macrocode} \gdef\trial@flush@seen@num{0} \gdef\trial@here@seen@num{0} \initialise@next@page \else % \end{macrocode} % Otherwise we claim we have a good float page. % \begin{macrocode} %<*trace> \tr@ce{float~page~succeeded} \tr@ce{We~ better~ output~ something~ now~ ...} % %<*progress> \progress@nl{succeeded} \progress@nl{} % % \end{macrocode} % producing this page is rubbish as well but it can't be written % before we have parameters and rules for making float pages. % \begin{macrocode} \forall@columns{ \global\setbox\csname col@box@\the\curr@col@count\endcsname \vbox to \csname col@ht@ \the\curr@col@count\endcsname{} \produce@final@column } \perhaps@write@placements@to@fpl@file \produce@final@page \initialise@next@page % \end{macrocode} % But the final lines are for real: if we did succeed we need to % provide a new |\@activelist| for the next potential float page. % It should be the floats we deferred while trying to make the % current float page followed by the floats that are still on the % active list (i.e., those we haven't even tried for the current % page). % \begin{macrocode} \xdef\@activelist{\area@ddd\@activelist} \global\let\area@ddd\@empty \fi % %\typeout{float.list.after.shipout.float.page.or.fail} %\showfloatlists % %<*trace> \@tracepop{try@float@page} % } % \end{macrocode} % \end{macro} % % % % \begin{macro}{\if@floatpage} % \begin{macro}{\@floatpagefalse} % \begin{macro}{\@floatpagetrue} % Switch which is set to true while we are in the process of making % float pages and haven't failed. % \begin{macrocode} \newif\if@floatpage \def\@floatpagefalse{\global\let\if@floatpage\iffalse} \def\@floatpagetrue{\global\let\if@floatpage\iftrue} % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % % % % \begin{macro}{\save@current@float@state} % % Save the current state of affairs concerning % floats\footnote{Needs more work, there are now other data % structures that should be saved if this is every going to be of % much use. (its current usage actually could be achieved with % simpler means). FIX or fold!}. In case of failure return to % this state by executing |\saved@float@state|. % \begin{macrocode} \def\save@current@float@state { %<*trace> \@tracepush{save@current@float@state} % \xdef\saved@float@state{\gdef\noexpand\@activelist{\@activelist}} \forall@columns { \expandafter \g@addto@macro \expandafter \saved@float@state \expandafter { \expandafter \global \csname col@ht@ \the\curr@col@count\expandafter\endcsname \the \csname col@ht@ \the\curr@col@count\endcsname % \end{macrocode} % No final |\relax| needed since this is followed by area data. And % if there are no areas we wouldn't call this code, would we? % \begin{macrocode} } } % \end{macrocode} % Save current state of all used float areas by looping though them. % \begin{macrocode} \expandafter\save@area@info\used@areas ddd\relax\relax\relax %<*trace> \tr@ce{saved:~ \meaning\saved@float@state} \@tracepop{save@current@float@state} % } % \end{macrocode} % \end{macro} % % \begin{macro}{\save@area@info} % Save information about area and recourse. % \begin{macrocode} \def\save@area@info#1#2#3{ \ifx#1\relax \else \edef\@tempa { \global\csname #1#2#3@float@count\endcsname \the\csname #1#2#3@float@count\endcsname % \end{macrocode} % No |\relax| needed since followed by a |\gdef|. % \begin{macrocode} \gdef \expandafter\noexpand \csname area@#1#2#3\endcsname {\csname area@#1#2#3\endcsname} } \expandafter \g@addto@macro \expandafter \saved@float@state \expandafter { \@tempa } \expandafter\save@area@info \fi} % \end{macrocode} % \end{macro} % % % % \begin{macro}{\saved@float@state} % To return to the saved float state execute |\saved@float@state|. % \begin{macrocode} \let\saved@float@state\@empty % \end{macrocode} % \end{macro} % % % % \begin{macro}{\split@defer@list} % % Split |\area@ddd| list, moving those floats whose callouts have % been typeset to |\@activelist| for consideration for (one day) % float pages, and for allocating to text page float areas. % % Floats whose callouts are still on MVL are placed on |\@mvllist|. % \begin{macrocode} \def\split@defer@list #1 { \def\@currbox{#1} \expandafter\extract@this@float@actual@structure\the\toks #1 %<*trace> \tr@ce { #1:~\LastMark{\this@class}~ ???~\this@sequence@number } % \ifnum 0\LastMark{\this@class} < \this@sequence@number %<*trace> \tr@ce {#1:~ not~ really~ defered } % \@cons \@mvllist #1 \else %<*trace> \tr@ce {#1:~ callout~ has~ been~ typeset} % \@cons \@activelist #1 \fi } % \end{macrocode} % \end{macro} % % % % % % \subsection{Preassign deferred floats} % % % % \begin{macro}{\place@deferred@floats} % % The |\place@deferred@floats| is supposed to distribute from % previous pages (i.e., from the top of |\area@ddd| or more exactly % those currently on the |\@activelist| since the |\area@ddd| was % already split when trying to build float pages) into the areas % of the page to be build. After all we know that for those floats % the call outs are on previous pages so testing for them % is unnecessary and we could save time by bypassing this stuff. % % On the other hand if we have flush points in the upcoming text % all our placements might be wrong, so perhaps this doesn't really % save so much time after all and the extra complication might not % be worth the effort. % % Perhaps a compromise is to make a first column grab without any % floats to see if we end up with a flush point (not implemented). % % So if we don't do this then the only thing we need to do at this % point is to move the floats from the |\@mvllist| to the end of % the |\@activelist|. % \begin{macrocode} \def\place@deferred@floats { %<*trace> \@tracepush{place@deferred@floats} % \xdef\@activelist{\@activelist\@mvllist} \global\let\@mvllist\@empty %\showfloatlists %<*trace> \@tracepop{place@deferred@floats} % } % \end{macrocode} % % % Here is an alternate definition which does the preassigning but % it would need to be extended by checking for flush points or by a % flag that ensures that if we later encounter a flush point that % we know we could backtrack if necessary (e.g., the preassignment % might have already deferred some floats past the flush % point).\footnote{Extend, fix, or get rid of.} % \begin{macrocode} \iffalse % we don't do it right now \def\place@deferred@floats { %<*trace> \@tracepush{place@deferred@floats} % %\showfloatlists % \let\@elt\split@defer@list % \area@ddd % \let\@elt\relax % \global\let\area@ddd\@empty \global\let\@activelist@empty@action\relax \global\let\pretests@success@action\floatpage@pretests@success@action \showfloatlists \trial@inner@loop \xdef\@activelist{\area@ddd\@mvllist} \global\let\area@ddd\@empty \global\let\@mvllist\@empty %\showfloatlists %<*trace> \@tracepop{place@deferred@floats} % } \fi % \end{macrocode} % \end{macro} % % % % \begin{macro}{\floatpage@pretests@success@action} % Version of |\pretests@success@action| for use in initial phase % when previously deferred floats are being allocated to float areas. % \begin{macrocode} \def\floatpage@pretests@success@action{ %<*trace> \@tracepush{floatpage@pretests@success@action} % \update@best@trial \trial@inner@loop %<*trace> \@tracepop{floatpage@pretests@success@action} % } % \end{macrocode} % \end{macro} % % % % \newpage % % \subsection{Support for Balancing} % % Code in this section (and related code in other sections) is not % used at the moment and will most likely be replaced with something % completely different. % % \begin{macro}{\if@balance} % |@balance| is set to true if we encounter a balance penalty % during collection. % \begin{macrocode} \newif\if@balance \def\@balancefalse{\global\let\if@balance\iffalse} \def\@balancetrue{\global\let\if@balance\iftrue} % \end{macrocode} % \end{macro} % % % \begin{macro}{\balancecolumns} % % \begin{macrocode} \def\balancecolumns { \add@badly@guarded@penalty\output@balance@penalty } % \end{macrocode} % \end{macro} % % % % % % % \newpage % % \subsection{Support for Flush Points} % % % \begin{macro}{\if@flushseen} % \begin{macro}{\if@flushfail} % % |@flushseen| is set to true if we encounter a flush penalty % during collection. % % |@flushfail| is set to true if we fail a trial due to placing the % float after the flush penalty. % \begin{macrocode} \newif\if@flushseen \def\@flushseenfalse{\global\let\if@flushseen\iffalse} \def\@flushseentrue{\global\let\if@flushseen\iftrue} \newif\if@flushfail \def\@flushfailfalse{\global\let\if@flushfail\iffalse} \def\@flushfailtrue{\global\let\if@flushfail\iftrue} % \end{macrocode} % \end{macro} % \end{macro} % % % % \begin{macro}{\flushfloats} % % Possible variants: % % Flush only one (some) types. % % Fuzzyflush or, more precisely, flush-to-this-column % or -page or -spread.\footnote{Right now "spread" is not implemented.} % % Parts of the flushpenalty (all types) data structure: % % |\flush@min@col@|\meta{num} % |\saved@flush@min@col@|\meta{num} % |\flush@prev@float@num@|\meta{num}\footnote{what is this Chris?} % % |\flush@seq@num| is the number of these so that % \meta{num} has range [1, |\flush@seq@num|] % % In addition, whilst doing an fp trial we need |\trial@flush@seen@num| % to record that we have, in this trial so far, seen the % flush points [1, |\trial@flush@seen@num|]. % % % \begin{macrocode} \DeclareDocumentCommand\flushfloats { o O{strict} } { \flush@floats {#1} {#2} } % \end{macrocode} % % \begin{macrocode} \def\flush@floats #1 #2 { \add@badly@guarded@penalty\output@flush@float@penalty % \end{macrocode} % % \begin{macrocode} \gincrement@num\flush@seq@num % \end{macrocode} % % \begin{macrocode} \global\@namedef{flush@min@col@\flush@seq@num}{1} % \end{macrocode} % % \begin{macrocode} \expandafter\xdef \csname flush@last@float@\flush@seq@num \endcsname {\the\float@sequence@count} % \end{macrocode} % If |#1| is |\NoValue| the current flush point affects all float % sequence classes, thus we store in % |\flush@classes@list@|\meta{num} a list of all float sequence % classes separated by semicolons. Otherwise we assume that we got % a single float type(!) as argument and flush the corresponding % class. % \begin{macrocode} \IfNoValueTF{#1}{ \def\@elt##1{##1;} \expandafter\xdef \csname flush@classes@list@\flush@seq@num \endcsname {\float@classes@list} \let\@elt\relax } {\expandafter\ifx\csname sequence@class@#1\endcsname \relax \ErrorArgumentNotAFloatType \else \global\expandafter\let \csname flush@classes@list@\flush@seq@num \expandafter\endcsname \csname sequence@class@#1\endcsname \fi } % \end{macrocode} % The argument |#2| holds the fuzziness of the flush point which % currently can be either |strict|, |column| or |page|. % We link |\flush@fuzziness@|\meta{num} to the code stored in % |\flushcheck@#2| after making sure that such code % exists.\footnote{Improve error handling (as elsewhere)} % \begin{macrocode} \@ifundefined {flushcheck@#2} \userinputERROR {\global\expandafter\let \csname flush@fuzziness@\flush@seq@num \expandafter \endcsname \csname flushcheck@#2\endcsname %<*trace> \tr@ce{flush@fuzziness@\flush@seq@num \space =:~ \expandafter\noexpand\csname flushcheck@#2\endcsname } % } } % \end{macrocode} % \end{macro} % % % % \begin{macro}{\clearpage} % \LaTeX's |\clearpage| command now looks like this: % \begin{macrocode} \def\clearpage{ \flushfloats \newpage } % \end{macrocode} % \end{macro} % % % \begin{macro}{\doubleclearpage} % \LaTeX's |\doubleclearpage| command also needs a new % definition:\footnote{But not this one :-) FIX!} % \begin{macrocode} \def\doubleclearpage{ \clearpage } % \end{macrocode} % \end{macro} % % % \begin{macro}{\flush@seq@num} % The number |\flush@seq@num| records the number of flush % points we have have seen during collection. % \begin{macrocode} \def\flush@seq@num{0} % \end{macrocode} % \end{macro} % % \begin{macro}{\trial@flush@seen@num} % The number |\trial@flush@seen@num| records the number of flush % points we have seen so far during a trial, i.e., it will be % initialised to zero at the beginning of the trial and advanced by % one for each flush point encountered. % \begin{macrocode} \def\trial@flush@seen@num{0} % \end{macrocode} % \end{macro} % % \begin{macro}{\flush@last@float@xxx} % \begin{macro}{\flush@min@col@xxx} % \begin{macro}{\flush@classes@list@xxx} % \begin{macro}{\flush@fuzziness@xxx} % % For each flush point we have a data structure in which we store % relevant information. This data structure is provided by a set of % macros which can be accessed by using the number of the current % flush point and constructing |\csname|s from it, e.g., to get at % the ``flush min col'' for the flush point with number 3 would be % |\csname flush@min@col@3\endcsname|. % |\flush@min@col@|\meta{num} holds the column number in which we % last seen the flush penalty while trying to find a solution for % the current page. This is initialised to 1 in collection@or when % a flush penalty is encountered during collection (since 1 is the % earliest column in which the flush penalty finally may fall). By % adding additional floats to the page the penalty might move to a % later column but normally not back to an earlier % one\footnote{There is a possibility that this happens if there is % enough space vanishing at the new break.} If we end up with the % flush penalty moving backwards we force a break at this point % until we reach the column where it was before. The reason for % this action is that we might have allocated floats to later % columns that would otherwise end after after the flush penalty. % % If by adding floats to the trials the flush penalty is moved to % the next page we set |\flush@min@col@|\meta{num} to % |\maxdimen|. The actual test to see if a flush penalty still % belongs to the current page is to check against |\curr@col@count| % (so |\curr@col@count+1| would be sufficient, but using % |\maxdimen| avoids calculations. % % |\flush@classes@list@|\meta{num} holds a list of float types which % are affected by the current flush point. % % |\flush@fuzziness@|\meta{num} holds the fuzziness associated with % the flushpoint, valid values are |strict| and |page|. % % By defining (some of) them on top-level we avoid unnecessary % entries on the savestack since they would otherwise be % constructed (locally) first within the output routine (when doing % |\ifx| testing), resulting in |\relax| being stored on the % savestack. % \begin{macrocode} \expandafter\let\csname flush@last@float@1 \endcsname\ERROR \expandafter\let\csname flush@classes@list@1 \endcsname\ERROR \expandafter\let\csname flush@min@col@1 \endcsname\ERROR \expandafter\let\csname flush@fuzziness@1 \endcsname\ERROR \expandafter\let\csname flush@last@float@2 \endcsname\ERROR \expandafter\let\csname flush@classes@list@2 \endcsname\ERROR \expandafter\let\csname flush@min@col@2 \endcsname\ERROR \expandafter\let\csname flush@fuzziness@2 \endcsname\ERROR \expandafter\let\csname flush@last@float@3 \endcsname\ERROR \expandafter\let\csname flush@classes@list@3 \endcsname\ERROR \expandafter\let\csname flush@min@col@3 \endcsname\ERROR \expandafter\let\csname flush@fuzziness@3 \endcsname\ERROR % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % % \begin{macro}{\flush@classes@list@max} % |\flush@classes@list@max| holds the concatenation of all % |\flush@classes@list@|\meta{num} on the page currently % constructed. This information is needed in case we get to a new % float and the preliminary tests suggests that it needs to be % deferred. In that case we need to know which flush points have % been seen previously to decide whether or not we can defer the % new float. % \begin{macrocode} \let\flush@classes@list@max\@empty % \end{macrocode} % \end{macro} % % % \begin{macro}{\initialise@flush@data} % \begin{macrocode} \def \initialise@flush@data{ %<*trace> \@tracepush{initialise@flush@data} % % \end{macrocode} % Does this need any documentation? % % Well, we have to get rid of all information relating to flush % float penalties that have been typeset on the previous page and % move the remaining ones (if any) to the front. % \begin{macrocode} \count@\flush@seq@num\relax \advance\count@ -\trial@flush@seen@num %<*trace> \tr@ce{flush@seq@num~ =~ \flush@seq@num\space <-~ \the\count@ } % % \end{macrocode} % Something wrong here if we get negative values! % \begin{macrocode} %<*debug> \ifnum\count@<\z@ \ERROR \fi % % \end{macrocode} % % \begin{macrocode} \xdef\flush@seq@num{\the\count@} % \end{macrocode} % % \begin{macrocode} \@tempcnta\trial@flush@seen@num \@tempcntb\z@ \loop \ifnum \@tempcntb < \count@ \advance\@tempcnta\@ne \advance\@tempcntb\@ne %<*trace> \tr@ce{flush@fuzziness@\the\@tempcntb\space =~ \expandafter \noexpand \csname flush@fuzziness@\the\@tempcntb\endcsname\space <-~ \expandafter \noexpand \csname flush@fuzziness@\the\@tempcnta \endcsname } \tr@ce{flush@last@float@\the\@tempcntb\space =~ \csname flush@last@float@\the\@tempcntb\endcsname\space <-~ \csname flush@last@float@\the\@tempcnta \endcsname } \tr@ce{flush@classes@list@\the\@tempcntb\space =~ \csname flush@classes@list@\the\@tempcntb\endcsname\space <-~ \csname flush@classes@list@\the\@tempcnta \endcsname } \tr@ce{flush@min@col@\the\@tempcntb\space <-~ 1} % \global\expandafter\let \csname flush@fuzziness@\the\@tempcntb \expandafter\endcsname \csname flush@fuzziness@\the\@tempcnta \endcsname \global\expandafter\let \csname flush@last@float@\the\@tempcntb \expandafter\endcsname \csname flush@last@float@\the\@tempcnta \endcsname \global\expandafter\let \csname flush@classes@list@\the\@tempcntb \expandafter\endcsname \csname flush@classes@list@\the\@tempcnta \endcsname \global\@namedef{flush@min@col@\the\@tempcntb}{1} \repeat % \end{macrocode} % % \begin{macrocode} \global\let\flush@classes@list@max\@empty % \end{macrocode} % Need to reset |\trial@flush@seen@num| in case the current macro % is called again too early, e.g., if it is called to initialize a % float page and then again to initialize a text page. % \begin{macrocode} \gdef\trial@flush@seen@num{0} %<*trace> \@tracepop{initialise@flush@data} % } % \end{macrocode} % \end{macro} % % % % % % \subsection{Support for Here Points} % % A ``Here Point'' is a place in the galley at which something is % supposed to happen. For example, a marginal note needs to be % attached to the column, or a float needs to be inserted into the % column (here float), or it needs to be made sure that from that % point on there is still a certain amount of space available in the % column. % % With each here point there is associated a float structure (i.e. a % box and its corresponding |\toks| register) although in most cases % only parts of that structure is used. In addition each here point % has an associated dimension which denotes the amount of available % space which is required after the here point in the column to allow % to place the here point into this column. If this requirement is not % met the here point is moved to the next column (or page) by ending % the current column prematurely at the last legal breakpoint before % the here point (not at the here point itself\footnote{It should be % considered to allow breaking directly at the here point in special % cases, i.e., specified at the here point declaration.}). This % behaviour will ensure that a line of text preceding the here point % will also be moved to the next column or page which is important in % case of marginals and similar situations. In case of here floats it % might not be a requirements so perhaps this should be made % customisable. % % At the moment the ``type'' in the float structure is used to define % the type of here point. E.g., % \begin{description} % \item[mpar] denotes a marginal % \item[rspace] denotes a requested space % \item[figure,table,\ldots] all normal float types identify the here % point as belonging to a here float. % \end{description} % The down side of this approach is that ``mpar'' can't be used as a % float type any longer and the whole approach might be too difficult % to extend this way. This needs certainly needs a cleanup. % % It is quite likely that there will be additional values that need % storing on a per here point basis. For this reason the code below % provides the requiredspace as a data structure external to the float % structure. Otherwise it could probably be integrated therein. % % When a here point is encountered while making columns for a trial or % for the final page, its requirements are checked. If they are % fulfilled then a here-point-type specific function will update the % column material (e.g. by adding a here float or a marginal). % % Here points are in many aspects like flush points. So most of the % code below should not be very surprising. % % \begin{macro}{\here@seq@num} % The number |\here@seq@num| records the number of here % points we have have seen during collection. % \begin{macrocode} \def\here@seq@num{0} % \end{macrocode} % \end{macro} % % \begin{macro}{\trial@here@seen@num} % The number |\trial@here@seen@num| records the number of here % points we have seen so far during a trial, i.e., it will be % initialised to zero at the beginning of the trial and advanced by % one for each here point encountered. % \begin{macrocode} \def\trial@here@seen@num{0} % \end{macrocode} % \end{macro} % % % \begin{macro}{\@herelist} % |\@elt| list of floats that should appear at a here point. % \begin{macrocode} \let\@herelist\@empty % \end{macrocode} % \end{macro} % % % \begin{macro}{\saved@herelist} % Saved version of the |\@herelist| while we run a through the % float placement trial since we need the full |\@herelist| again in % the next trial. % \begin{macrocode} \let\saved@herelist\@empty % \end{macrocode} % \end{macro} % % % \begin{macro}{\here@point} % |\here@point| adds a here point to the MVL. It takes two % arguments: the box reference associated with the here point and % the vertical space that needs to be reserved for the material % added. % \begin{macrocode} \def\here@point #1#2{ % \end{macrocode} % % \begin{macrocode} \@cons\@herelist#1 % \end{macrocode} % % \begin{macrocode} \gincrement@num\here@seq@num % \end{macrocode} % % \begin{macrocode} \global\@namedef{here@min@col@\here@seq@num}{1} % \end{macrocode} % % \begin{macrocode} \setlength\dimen@{#2} \expandafter\xdef \csname here@required@space@\here@seq@num \endcsname {\the\dimen@} % \end{macrocode} % % \begin{macrocode} \add@badly@guarded@penalty\output@here@float@penalty } % \end{macrocode} % \end{macro} % % % % % \begin{macro}{\initialise@here@data} % \begin{macrocode} \def \initialise@here@data{ %<*trace> \@tracepush{initialise@here@data} % % Does this need any documentation? % % Well, we have to get rid of all information relating to here % float penalties that have been typeset on the previous page and % move the remaining ones (if any) to the front. % \begin{macrocode} \count@\here@seq@num\relax \advance\count@ -\trial@here@seen@num %<*trace> \tr@ce{here@seq@num~ =~ \here@seq@num\space <-~ \the\count@ } % % \end{macrocode} % Something wrong hereif we get negative values! % \begin{macrocode} %<*debug> \ifnum\count@<\z@ \ERROR \fi % % \end{macrocode} % % \begin{macrocode} \xdef\here@seq@num{\the\count@} % \end{macrocode} % % \begin{macrocode} \@tempcnta\trial@here@seen@num \@tempcntb\z@ \loop \ifnum \@tempcntb < \count@ \advance\@tempcnta\@ne \advance\@tempcntb\@ne %<*trace> \tr@ce{here@required@space@\the\@tempcntb\space =~ \csname here@required@space@\the\@tempcntb\endcsname\space <-~ \csname here@required@space@\the\@tempcnta \endcsname } \tr@ce{here@min@col@\the\@tempcntb\space <-~ 1} % \global\expandafter\let \csname here@required@space@\the\@tempcntb \expandafter\endcsname \csname here@required@space@\the\@tempcnta \endcsname \global\@namedef{here@min@col@\the\@tempcntb}{1} \repeat %<*trace> \@tracepop{initialise@here@data} % } % \end{macrocode} % \end{macro} % % % \begin{macro}{\split@off@last@line} % % When a here point doesn't fit onto the current page or column for % some reason it will be moved into the next column. In some cases, % e.g., when the here point is associated with the line before it % (as, for example, in marginals) it is necessary to move the line % also to the later column. % % The purpose of |\split@off@last@line| (to be called inside the % OR) is to split box 255 at the latest possible breakpoint before % the end and return the material following this breakpoint to the % MVL. % % The idea is as follows: if we subtract 1sp from the height of % box 255 and also subtract all of its internal shrinkability and % then split it to this height it can't any longer reach the final % breakpoint (by 1sp). Thus it will settle with some earlier % breakpoint and chances are very very good that this will be the % prefinal one. % \begin{macrocode} \def \split@off@last@line{ %<*trace> \@tracepush{split@off@last@line} \tr@ce{goal:~ \the\pagegoal;~ total:~ \the\pagetotal;~ shrink:~ \the\pageshrink} \tr@ce{ht255:~ \the\ht255;~ dp255:~ \the\dp255} % % \end{macrocode} % % % \begin{macrocode} \dimen@\ht\@cclv % \end{macrocode} % Looking at |\ht255| should be the same as |\pagetotal-\pagedepth| % or not?\footnote{Doesn't seem to be the case, bug in the code, % the program, or in my thinking? (seems to be a bug in \TeX: % pagedepth is always zero in the OR!)} % \begin{macrocode} \advance\dimen@-\pageshrink \advance\dimen@-1sp %{\showoutput\showbox\@cclv} % \end{macrocode} % Before splitting we have to ensure that the maximum depth is not % larger than the maximum depth allowed on the MVL. % \begin{macrocode} \splitmaxdepth\@maxdepth \setbox\z@\vsplit\@cclv to\dimen@ %{\showoutput\showbox\z@} %{\showoutput\showbox\@cclv} % \end{macrocode} % % Before we now |\unvbox| 255 back onto the MVL we have to make sure % that the sum of its vertical dimensions plus the requested space % for the current here point is smaller than a full column height. % % If we don't do that we might end up with a situation where we are % pushing the two from column to columns since they will never fit. % \begin{macrocode} \dimen@\csname here@required@space@\trial@here@seen@num \endcsname \advance\dimen@\ht\@cclv \advance\dimen@\dp\@cclv % \end{macrocode} % If the sum is too large we reduce the required space for the here % point and complain (not really done yet the latter). % \begin{macrocode} \ifdim \dimen@ > \textheight \ERROR-HERE-TOO-LARGE \dimen@\textheight \advance\dimen@-\ht\@cclv \advance\dimen@-\dp\@cclv \expandafter\xdef\csname here@required@space@\trial@here@seen@num \endcsname{\the\dimen@} \fi % \end{macrocode} % So now we can |\unvbox| and then move the top from the split back % into 255 (essentially to have it taken out of that register by % the code following, but such is life). % \begin{macrocode} \unvbox\@cclv \global\setbox\@cclv\box\z@ %<*trace> \@tracepop{split@off@last@line} % } % \end{macrocode} % \end{macro} % % % % % \subsection{Support for Grid Points} % % % % % \begin{macro}{\align@collected@galley@and@restart} % |\align@collected@galley@and@restart| is called inside % |\some@column@or| when we have encountered a grid point. It is % supposed to align the current line with the text grid and then % restarts the galley processing. % % We do this by putting the material gathered so far into a box of % appropriate size, and then push this pack onto the recent % contributions for reconsideration. % \begin{macrocode} \def \align@collected@galley@and@restart { %<*trace> \@tracepush{align@collected@galley@and@restart} \tr@ce{GRID:~ page~ goal~\space\space\space =~ \the\pagegoal} \tr@ce{GRID:~ page~ total~\space\space =~ \the\pagetotal} \tr@ce{GRID:~ page~ depth~\space\space =~ \the\pagedepth} \tr@ce{GRID:~ page~ shrink~\space =~ \the\pageshrink} \tr@ce{GRID:~ page~ stretch~ =~ \the\pagestretch} \tr@ce{GRID:~ page~ fil~ stretch~ =~ \the\pagefilstretch} \tr@ce{GRID:~ page~ fill~ stretch~ =~ \the\pagefillstretch} \tr@ce{GRID:~ page~ filll~ stretch~ =~ \the\pagefillstretch} \tr@ce{GRID:~ ht~ 255~\space =~ \the\ht\@cclv} \tr@ce{GRID:~ dp~ 255~\space =~ \the\dp\@cclv} % % \end{macrocode} % As a first step we remove the guard box since it has now served % its purpose. % \begin{macrocode} \remove@guard@box@from@cclv % \end{macrocode} % Then we calculate the distance to nearby grid points. % \begin{macrocode} \snap@to@grid{\ht\@cclv}\pagesetup@grid@point@sep % \end{macrocode} % So the next step is to make a decision which grid point to % use. The strategy used below can probably be refined % further\ldots % % First we test if the next grid point down makes us fall off the % page\footnote{We should use \texttt{\string\pagegoal} for the % test I think, not the commented out construct below, since in % case of footnotes the available space for text might has be % reduced!}, if so\ldots % \begin{macrocode} \ifdim \returned@size > \pagegoal % \csname col@ht@ \the\curr@col@count\endcsname % not! % \end{macrocode} % \ldots we better try using the previous grid point. % \begin{macrocode} \ifdim \returned@lower@delta@size < \pageshrink % \end{macrocode} % If the |\pageshrink| allows us to reach the previous point then % use it. % \begin{macrocode} % can use it: do so %<*trace> \tr@ce{GRID:~ outside~ page,~ choosing~ lower~ grid~ point} % \global\let \returned@size \returned@lower@size \xdef \returned@delta@size {-\returned@lower@delta@size } \else % \end{macrocode} % Otherwise, ouch \ldots{} what now? Can this happen? Unfortunately % yes, it seems to happen, for example, when we are trying to place % floats.\footnote{Analyse this situation and decide on a course of % action if necessary.} % \begin{macrocode} \OuchERROR \fi % \end{macrocode} % Otherwise we are in the normal case, i.e., somewhere in the % middle of the page. % \begin{macrocode} \else % \end{macrocode} % So now we can in principle choose either grid point. The code % below makes the decision based on which grid point is closer but % chooses the previous point only if |\pageshink| allows % it.\footnote{One could also have a look at the available % stretchability and base the decision on the resulting badness, % this might in fact be the more appropriate way!} % \begin{macrocode} \ifdim \returned@lower@delta@size < \returned@delta@size \relax \ifdim \returned@lower@delta@size < \pageshrink %<*trace> \tr@ce{GRID:~ choosing~ lower~ grid~ point} % \global\let \returned@size \returned@lower@size \xdef \returned@delta@size {-\returned@lower@delta@size } \fi \fi \fi %<*trace> \tr@ce{GRID:~ adjustment:~ \the\ht\@cclv\space ->~ \returned@size} % % \end{macrocode} % Whatever the decision was, we finally bundle up all material in a % box with the vertical size being that of the chosen grid point % (no |\maxdepth| setting in this case) and return this box to the % MVL followed by any footnotes found in that process. These % footnotes are reinserted so that they will be reconsidered but % since we have no break point between the box and them they will % be considered as a unit. % \begin{macrocode} \vbox to\returned@size{\unvbox\@cclv} \@reinserts % \end{macrocode} % We know that the material returned to the MVL is followered % immediately by a box of size zero followed by a penalty thus % there will be a breakpoint in the right place (or so we hope) so % that the box plus the following footnotes will still fit into the % column when reprocessed. % \begin{macrocode} %<*trace> \@tracepop{align@collected@galley@and@restart} % } % \end{macrocode} % \end{macro} % % % % \begin{macro}{\OuchERROR} % This part of the code (as far as I can see right now) will be % executed if there is some larger display object (ie off grid) % which will just fit onto the page unaligned but not if we align % to the next grid point. The reason for this is that somewhere on % the column there are also footnotes for example, which result in % the column not being an integral number of grid lines. % \begin{macrocode} \def\OuchERROR{ %<*trace> \tr@ce{Failed:~grid~ overflowing~ column~ \the\curr@col@count} % %<*progress> \progress@failed{next~ possible~ grid~ point~ in~ column~ \the\curr@col@count\space outside~ page} % % \end{macrocode} % I think essentially what is needed here is to split the column % just before the current line, ie, using something like % |\split@off@last@line| (except that this only works for here % points right now) and this move the grid align penalty to the % next column.\footnote{Not done! FIX} % \begin{macrocode} % \split@off@last@line % \(re)???add@guarded@penalty\output@grid@align@penalty } % \end{macrocode} % \end{macro} % % % % \begin{macro}{\std@AlignToGrid} % This is the definition for |\AlignToGrid| if we are really doing % grid based layout. % \begin{macrocode} \def\std@AlignToGrid{ \add@badly@guarded@penalty\output@grid@align@penalty } % \end{macrocode} % \end{macro} % % % \begin{macro}{\IgnoreAlignToGrid} % \begin{macro}{\ObeyAlignToGrid} % |\IgnoreAlignToGrid| will turn off automatic grid alignment for a % while, while |\ObeyAlignToGrid| will turn it on again. This is % needed in commands that want to set something outside the grid % and then realign afterwards, e.g., a heading. If that heading % would follow, say, a list that issued a |\AlignToGrid| to be % executed on the next paragraph, that |\AlignToGrid| would % effectively appear on the heading title thus forcing that to be % on a grid line, which is typically not intended. So the heading % macro first says |\IgnoreAlignToGrid| then typesets the material % which should be not aligned, then says |\ObeyAlignToGrid| and % prepares to install its own |\AlignToGrid| (typically after the % first line of text via |\everypar|). % \begin{macrocode} \def\IgnoreAlignToGrid{ \global\let\AlignToGrid\relax } \def\ObeyAlignToGrid{ \global\let\AlignToGrid\std@AlignToGrid } % \end{macrocode} % \end{macro} % \end{macro} % % % % \begin{macro}{\AlignToGrid} % |\AlignToGrid| is the command that inserts a grid point which % triggers alignment to the text grid for the current line (if we % are doing grid based design). It should be set in the page setup % so the default is an error. % \begin{macrocode} \let\AlignToGrid\ERROR % \end{macrocode} % \end{macro} % % % \begin{macro}{\TextAlignToGrid} % In nearly all cases the alignment should be done for a text line, % so we provide this abbreviation which starts horizontal mode if % necessary. % \begin{macrocode} \def\TextAlignToGrid{ \leavevmode \AlignToGrid } % \end{macrocode} % \end{macro} % % % % % % % \subsection{Initialisations} % % The initialisation at begin document isn't properly done % yet. Some bits are done unnecessarily here (by calling % initialisation commands that do too much and some bits are % problably still in the wrong place. Furthermore the column data % initialisation needs to be resolved properly. Right now we % hardwire a maximum of 6 columns down there and initialise the % data structures for all the potential columns independently of % whether or not they are ever being used.\footnote{SORT OUT!} % \begin{macrocode} \AtBeginDocument{ \begingroup \col@count6\relax \initialise@column@data % \end{macrocode} % More column data stuff which needs to be set only the very first % time! % \begin{macrocode} \forall@columns { % \end{macrocode} % % \begin{macrocode} \def\@elt#1{ \global\@namedef{fl@\the\curr@col@count @#1}{0} \global\@namedef{tfl@\the\curr@col@count @#1}{0} } \float@classes@list % \end{macrocode} % Setting |\@elt| back to |\relax| is done below. % \begin{macrocode} } % \end{macrocode} % % The default for fps should be all areas known (not only those % currently used!) % \begin{macrocode} \def\@elt#1{ \global\expandafter\let\csname fps@#1\endcsname\known@areas \global\@namedef{fl@0@#1}{0} } \float@classes@list \endgroup % \end{macrocode} % % \begin{macrocode} % \initialise@next@page % \end{macrocode} % Start the document by collecting text. % \begin{macrocode} \@collecting@new@materialtrue \setup@collection@or } % \end{macrocode} % % % \endinput \endinput % % $Log: xo-or.dtx,v $ % Revision 1.53 2000/08/11 07:14:25 latex3 % added header % % Revision 1.52 2000/08/11 06:49:21 latex3 % untabify % % Revision 1.51 2000/08/11 06:46:48 latex3 % change logic for handling special penalties once more (and still not % okay) % % Revision 1.50 2000/08/06 19:03:44 latex3 % change initialisation at \begin{document} % fix \columnbreak % % Revision 1.49 2000/08/04 13:58:16 latex3 % documented issue when grid point overflows column % % Revision 1.48 2000/08/04 10:22:31 latex3 % added \split@skip (probably not final version) % % Revision 1.47 2000/07/26 20:37:03 latex3 % working version of grid points (text grids) % % Revision 1.46 2000/07/21 13:52:13 latex3 % more renaming for float sequence class concept % % Revision 1.45 2000/07/19 17:12:08 latex3 % introduced float sequence class concept % added variables for float area separation % % Revision 1.44 2000/07/10 19:24:59 latex3 % some start at supporting "balance points" (unfinished). % added \initialise@column@data. % getting rid of extra empty page at end due to old defnition of % \clearpage. % % Revision 1.43 2000/07/04 19:45:40 latex3 % fix GRID stuff (restore all values as needed) % % Revision 1.42 2000/07/01 16:07:26 latex3 % use \update@this@area@columns % integrate code to support grid design (first draft) % % Revision 1.41 2000/06/29 17:40:44 latex3 % introduced \setup@this@area % % Revision 1.40 2000/06/26 15:16:15 latex3 % prototype support for \pagesetup@float@area@sep % % Revision 1.39 2000/06/22 20:07:51 latex3 % renamed some macros to get them more uniform % % Revision 1.38 2000/06/22 10:59:57 latex3 % Included support for writing fpl files % % Revision 1.37 2000/06/21 09:55:41 latex3 % fix typo % % Revision 1.36 2000/06/19 19:03:56 latex3 % make \gincrement@num and \gdecrement@num behave (not update \count@) % cleanup flushing (if fail only move flush point one column) % % Revision 1.35 2000/06/18 14:59:50 latex3 % docu updates (and a bug fix due to typo) % % Revision 1.34 2000/06/16 11:21:14 latex3 % rename \construct@and@test@col@height to \construct@and@test@col@ht % rename \construct@and@test@col@heights to \construct@and@test@col@hts % rename \cl@height1 to \@col@ht@1 (etc) % % Revision 1.33 2000/06/16 11:05:25 latex3 % implemented tfl@ support (top area float sequences) % support float-callout-span-constraint % more documentation % % Revision 1.32 2000/06/15 15:20:16 latex3 % implemented new semantics for area names % % Revision 1.31 2000/06/15 09:32:18 latex3 % added mising \end{macro}'s % % Revision 1.30 2000/06/13 20:44:25 latex3 % guard the output@collect@penalty % implemented fuzzy flushing (except for spreads) % % Revision 1.29 2000/06/06 11:03:21 latex3 % before attempting fuzzyflush % % Revision 1.28 2000/05/03 20:17:31 latex3 % need more info about here floats % % Revision 1.27 2000/05/03 18:45:40 latex3 % fix bugs: always have a trial run wihtout floats to initialise here % and flush points; reset \trial@flush@seen@num after using it to update % the data structures on a new pages; have adding to the defer area % close other areas :-) % more documentation % % Revision 1.26 2000/04/27 19:50:11 latex3 % some stats gathered now % combine \grab@column@or and \best@column@or as far as possible % some bug fixes and additional documentation % % Revision 1.25 2000/04/21 19:08:43 latex3 % code cleanup % additional documentation % fixes for here points % support for footnote setup % % Revision 1.24 2000/04/11 21:06:06 latex3 % basically Chris's 1.24 plus my changes % % Revision 1.24 2000/04/10 16:41:14 car2 % typos, comments and guardbox removal % % Revision 1.23 2000/04/09 20:02:00 latex3 % fix topskip problem in collection % added first draft of marginpar support % % Revision 1.22 2000/04/08 09:47:06 latex3 % first draft of here point implementation % code cleanup % further documentation % % Revision 1.21 2000/03/31 17:12:41 latex3 % disable preplacing deferred floats (until caption handling is fixed) % fix float page handling % ensure that float pages don't add additional captions (don't mind that % the float page comes out even worse) % % Revision 1.20 2000/03/26 21:05:11 latex3 % work on float pages % some renaming in particular \try@this@area % and \try@next@area % some more documentation % % Revision 1.19 2000/03/24 15:34:27 latex3 % version that starts supporting spans (still a hack yet) % % Revision 1.18 2000/03/22 15:51:11 latex3 % some normalisations of names % moved code around % lot of updates % % Revision 1.17 2000/03/17 20:26:40 latex3 % more fixes to flushing (looks good now) % % Revision 1.16 2000/03/16 10:28:29 latex3 % partial and full flush working for the first time % % Revision 1.15 2000/03/05 19:36:53 latex3 % some renaming % support multiple columns (6 max right now) % fix flush float logic (hopefully) % % Revision 1.14 2000/02/28 23:41:14 david % deadcycles % % Revision 1.13 2000/02/27 15:39:53 david % *** empty log message *** % % Revision 1.12 2000/02/27 15:12:00 david % 2nd attempt at flush floats (working as far as implemented) % % Revision 1.11 2000/02/27 11:26:35 david % first attempt at flush floats % % Revision 1.10 2000/02/26 18:20:09 david % added pre-allocation of deferred floats to float areas % % Revision 1.9 2000/02/21 23:25:11 david % t11|t22 support in optional argument % % Revision 1.8 2000/02/19 23:14:58 david % chris' doc fix % % Revision 1.7 2000/02/16 13:40:40 latex3 % added 3col support % % Revision 1.6 2000/02/16 10:07:13 latex3 % added further documentation % fixed bug by removing code from \try@this@area to % \pretests@success@action % handle case of hitting special output penalty during trial or % page production % handle case of \newpage ie penalty -10000 % % Revision 1.5 2000/02/15 01:08:25 david % dead code % % Revision 1.4 2000/02/13 22:40:13 latex3 % moved some stuff around and added macro environments %