% \iffalse %% Source File: fix2col.dtx Copyright 1997 1998 David Carlisle %% %% This file may be distributed under the terms of the LPPL. %% See 00readme.txt for details. % %<*dtx> \ProvidesFile{fix2col.dtx} % %\NeedsTeXFormat{LaTeX2e} %\ProvidesPackage{fix2col} % \ProvidesFile{fix2col.drv} % \fi % \ProvidesFile{fix2col.dtx} [2015/11/13 v0.04 Output Routine fixes for two column mode (DPC,FMi)] % % \iffalse %<*driver> \documentclass{ltxdoc} \begin{document} \DocInput{fix2col.dtx} \end{document} % % \fi % % \GetFileInfo{fix2col.dtx} % \CheckSum{583} % % \changes{v0.01}{1997/11/07} % {Initial version} % % \changes{v0.02}{1997/11/11} % {\cs{@ztryfc}} % % \title{The \textsf{fix2col} package\thanks{This file % has version number \fileversion, last % revised \filedate.}} % \author{David Carlisle\thanks{%^^A % Part one is essentially a copy of the fixmarks package by % Piet van Oostrum, itself based on earlier work by Joe Pallas. % Part two is loosely based on the fixfloats package, originally % by Ed Sznyter, with some modifications by Bil Kleb.}} % % \date{\filedate} % % \let\package\textsf % \let\env\textsf % \let\url\texttt % % \maketitle % % \section{Introduction} % % \textbf{Note:} This package is obsolete, the fixes described here are % incorporated into \LaTeX\ formats from 2015/01/01 onwards. % % This package makes two independent changes to \LaTeX's two column % output routine to fix the following two longstanding `features'. % % \begin{itemize} % \item % If the \TeX\ mark system is used (for example using the % `headings' page style in the standard \LaTeX\ classes) then any marks % that originate on the first column are `lost' as \LaTeX\ constructs % the second column. An example document showing how this can result % in incorrect page headings may be found in the latex bug database:\\ % \url{http://www.uni-mainz.de/cgi-bin/ltxbugs2html?pr=latex/2613} % % \item % The second feature is documented in the \LaTeX\ book. By default % \LaTeX\ does not attempt to keep double and single column floats in % sequence, so if `Figure 1' is a double column float produced with % |figure*|, then it may float % after `Figure 2' if that is a single column, |figure|, float. % Further correspondence about this may also be found in the % bug database:\\ % \url{http://www.uni-mainz.de/cgi-bin/ltxbugs2html?pr=latex/2346} % \end{itemize} % % \StopEventually{} % % \section{Notes on the Implementation Strategies} % % \subsection{Preserving Marks} % % The standard \LaTeX\ twocolumn system works internally by making % each column a separate `page' that is passed independently to \TeX's % pagebreaker. (Unlike say the \package{multicol} package, where all % columns are gathered together and then split into columns later, % using |\vsplit|.) This means that the primitive \TeX\ marks that are % normally used for header information, are globally reset after the % first column. By default \LaTeX\ does nothing about this. % A good solution is provided by Piet van Oostrum (building on earlier % work of Joe Pallas) in his \package{fixmarks} package. % % After the first column box has been collected the mark information % for that box is saved, so that any |\firstmark| can be % `artificially' used to set the page-level marks after the second % column has been collected. (The second column |\firstmark| is not % normally required.) Unfortunately \TeX\ does not provide a direct % way of knowing if any marks are in the page, |\firstmark| always has a % value from previous pages, even if there is no mark in this page. % The solution is to make a copy of the box and then |\vsplit| it % so that any marks show up as |\splitfirstmark|. % % The use of |\vsplit| does mean that the output routine will globally % change the value of |\splitfirstmark| and % |\splitbotmark|. The \package{fixmarks} package goes to some trouble % to save and restore these values so that the output routine does % \emph{not} change the values. This part of \package{fixmarks} is not % copied here as it is quite costly (having to be run on every page) and % there is no reason why anyone writing code using |\vsplit| should % allow the output routine to be triggered before the split marks have % been accessed. % % \subsection{Preserving Float Order} % % The standard output routine maintains two lists of floats that have % been `deferred' for later consideration. One list for single column % floats, and one for double column floats (which are always % immediately put onto their deferred list). This mechanism means % that \LaTeX\ `knows' which type of float is contained in each box % by the list that it is processing, but having two lists means % that there is no mechanism for preserving the order between the % floats in each list. % % The solution to this problem consists of two small changes to % the output routine. % % Firstly, abandon the `double column float list' |\@dbldeferlist| % and change every command where it is used so that instead the % same |\@deferlist| is used as for single column floats. % That one change ensures that double and single column floats % stay in the same sequence, but as \LaTeX\ no longer `knows' % whether a float is double or single column, it will happily % insert a double float into a single column, overprinting the % other column, or the margin. % % The second change is to provide an alternative mechanism for % recording the two column floats. \LaTeX\ already has a compact % mechanism for recording float information, an integer count register % assigned to each float records information about the `type' of float % `figure', `table' and the position information `htp' etc. % % The type information is stored in the `high' bits, one bit position % (above `32') allocated to each float type. The `low' bits store % information about the allowed positions, one bit each allocated for % |h t b p|. In the \LaTeX2.09 system, the bit corresponding to `16' % formed a `boundary' between these two sets of information, and it % was never actually used by the system. Ed Sznyter's % \package{fixfloats} package not unreasonably used this position to % store the double column information, setting the bit for double % column floats. Then at each point in the output routine at which a % float is committed to a certain region, an additional check must be % made to check that the float is (or is not) double column. If it % spans the wrong number of columns it is deferred rather than being % added. % % Unfortunately the bit `16' is not available in \LaTeXe. It is used % to encode the extra float position possibility `|!|' that was added % in that system. It would be possible to use position `32' and to % move the flags for `table', `figure',\ldots\ up one position, to % start at 64, but this would mean that in principle one less float % type would be supported, and more importantly is likely to break % any other packages that assume anything about the output routine % internals. So here I instead use another mechanism for flagging % double column floats: By default all floats have depth 0pt. % This package arranges that double column ones have depth 1sp. % This information may then be used in the same manner as in % the \package{fixfloats} package, to defer any floats that are not of % the correct column spanning type. % % Use of the package showed that one also has to change the way % \LaTeX{} handles star-form floats: if they are immediately deferred % (as done normally) certain situations can still result in the float % sequence getting out of order. This happens when a floats are placed % in the middle of a paragraph. In that case the wide float is % deferred immediately while a column wide float early on in the same % paragraph might not be handled until the end of the paragraph when % it is finally seen by the output routine. Since by that time the % wide float is already on the |\@deferlist| the column float will % also end up there (which is not only incorrect because it may have % fitted onto the page but also because it is then placed at the end % of this list). Version v0.03 now fixes this problem. % % % \section{Implementation} % \begin{macrocode} %<*package> % \end{macrocode} % % \subsection{Do nothing on current releases} % % \changes{v0.04}{2015/11/03} % {Abort on new formats} % \begin{macrocode} \@ifl@t@r\fmtversion{2014/12/31} {\PackageWarningNoLine{fix2col}{Obsolete package: ignored}\endinput} {} % \end{macrocode} % % \subsection{Preserving Marks} % % This is just a change to the single command |\@outputdblcol| % so that it saves mark information for the first column and restores % it in the second column. % \begin{macrocode} \def\@outputdblcol{% \if@firstcolumn \global\@firstcolumnfalse % \end{macrocode} % Save the left column % \begin{macrocode} \global\setbox\@leftcolumn\copy\@outputbox % \end{macrocode} % % Remember the marks from the first column % \begin{macrocode} \splitmaxdepth\maxdimen \vbadness\maxdimen \setbox\@outputbox\vsplit\@outputbox to\maxdimen % \end{macrocode} % % One minor difference from the current \package{fixmarks}, pass the % marks through a token register to stop any |#| tokens causing an % error in a |\def|. % \begin{macrocode} \toks@\expandafter{\topmark}% \xdef\@firstcoltopmark{\the\toks@}% \toks@\expandafter{\splitfirstmark}% \xdef\@firstcolfirstmark{\the\toks@}% % \end{macrocode} % % This test does not work if truly empty marks have been inserted, but % \LaTeX\ marks should always have (at least) two brace groups. % (Except before the first mark is used, when the marks are empty, % but that is OK here.) % \begin{macrocode} \ifx\@firstcolfirstmark\@empty \global\let\@setmarks\relax \else \gdef\@setmarks{% \let\firstmark\@firstcolfirstmark \let\topmark\@firstcoltopmark}% \fi % \end{macrocode} % % End of change % \begin{macrocode} \else \global\@firstcolumntrue \setbox\@outputbox\vbox{% \hb@xt@\textwidth{% \hb@xt@\columnwidth{\box\@leftcolumn \hss}% \hfil \vrule \@width\columnseprule \hfil \hb@xt@\columnwidth{\box\@outputbox \hss}}}% \@combinedblfloats % \end{macrocode} % Override current first and top with those of first column if necessary % \begin{macrocode} \@setmarks % \end{macrocode} % End of change % \begin{macrocode} \@outputpage \begingroup \@dblfloatplacement \@startdblcolumn \@whilesw\if@fcolmade \fi{\@outputpage\@startdblcolumn}% \endgroup \fi} % \end{macrocode} % % \subsection{Preserving Float Order} % % Changes |\@dbldeferlist| to |\@deferlist| are not explicitly noted % but are flagged by blank comment lines around the changed line. % % % \begin{macrocode} \def\end@dblfloat{% \if@twocolumn \@endfloatbox \ifnum\@floatpenalty <\z@ \@largefloatcheck % \end{macrocode} % % Force the depth of two column float boxes. % \begin{macrocode} \global\dp\@currbox1sp % % \end{macrocode} % % \changes{v0.03}{1998/08/17}{FMi: use output routine to % defer float} % Next line assumes that first token of |\end@float| is % |\@endfloatbox| so we gobble that. % \begin{macrocode} % \@cons\@deferlist\@currbox \expandafter\@gobble\end@float % \end{macrocode} % |\@Esphack| is then added by |\@endfloat| above. % \begin{macrocode} \fi % \ifnum \@floatpenalty =-\@Mii \@Esphack\fi \else \end@float \fi } % \end{macrocode} % % Test if the float box has the wrong width. (Actually as noted above % the test is for a conventional depth setting rather than for the % width of the float). % \begin{macrocode} \def\@testwrongwidth #1{% \ifdim\dp#1=\f@depth \else \global\@testtrue \fi} % \end{macrocode} % % Normally looking for single column floats, which have zero depth. % \begin{macrocode} \let\f@depth\z@ % \end{macrocode} % % but when making two column float area, look for floats with 1sp % depth. % \begin{macrocode} \def\@dblfloatplacement{\global\@dbltopnum\c@dbltopnumber \global\@dbltoproom \dbltopfraction\@colht \@textmin \@colht \advance \@textmin -\@dbltoproom \@fpmin \dblfloatpagefraction\textheight \@fptop \@dblfptop \@fpsep \@dblfpsep \@fpbot \@dblfpbot % \end{macrocode} % % \begin{macrocode} \def\f@depth{1sp}} % \end{macrocode} % % All the remaining changes are replacing the double column defer list % or insering the extra test |\@testwrongwidth|\marg{box} at suitable % places. That is at plces where a box is taken off the deferlist. % \begin{macrocode} \def \@doclearpage {% \ifvoid\footins \setbox\@tempboxa\vsplit\@cclv to\z@ \unvbox\@tempboxa \setbox\@tempboxa\box\@cclv \xdef\@deferlist{\@toplist\@botlist\@deferlist}% \global \let \@toplist \@empty \global \let \@botlist \@empty \global \@colroom \@colht \ifx \@currlist\@empty \else \@latexerr{Float(s) lost}\@ehb \global \let \@currlist \@empty \fi \@makefcolumn\@deferlist \@whilesw\if@fcolmade \fi{\@opcol\@makefcolumn\@deferlist}% \if@twocolumn \if@firstcolumn % \end{macrocode} % % \begin{macrocode} \xdef\@deferlist{\@dbltoplist\@deferlist}% % \end{macrocode} % % \begin{macrocode} \global \let \@dbltoplist \@empty \global \@colht \textheight \begingroup \@dblfloatplacement % \end{macrocode} % % \begin{macrocode} \@makefcolumn\@deferlist \@whilesw\if@fcolmade \fi{\@outputpage \@makefcolumn\@deferlist}% % \end{macrocode} % % \begin{macrocode} \endgroup \else \vbox{}\clearpage \fi \fi % \end{macrocode} % the next line is needed to avoid losing floats in certain % circumstances a single call to the original |\doclearpage| % will now no longer output all floats. % \changes{v0.03}{1998/08/17}{FMi: ensure \cs{doclearpage} is called again % until all floats are output} % \begin{macrocode} \ifx\@deferlist\@empty \else\clearpage \fi \else \setbox\@cclv\vbox{\box\@cclv\vfil}% \@makecol\@opcol \clearpage \fi } % \end{macrocode} % % \begin{macrocode} \def \@startdblcolumn {% \@tryfcolumn \@deferlist \if@fcolmade \else \begingroup \let \reserved@b \@deferlist \global \let \@deferlist \@empty \let \@elt \@sdblcolelt \reserved@b \endgroup \fi } % \end{macrocode} % % \begin{macrocode} \def\@addtonextcol{% \begingroup \@insertfalse \@setfloattypecounts \ifnum \@fpstype=8 \else \ifnum \@fpstype=24 \else \@flsettextmin \@reqcolroom \ht\@currbox \advance \@reqcolroom \@textmin \ifdim \@colroom>\@reqcolroom \@flsetnum \@colnum \ifnum\@colnum>\z@ \@bitor\@currtype\@deferlist \@testwrongwidth\@currbox \if@test \else \@addtotoporbot \fi \fi \fi \fi \fi \if@insert \else \@cons\@deferlist\@currbox \fi \endgroup } % \end{macrocode} % % \begin{macrocode} \def\@addtodblcol{% \begingroup \@insertfalse \@setfloattypecounts \@getfpsbit \tw@ \ifodd\@tempcnta \@flsetnum \@dbltopnum \ifnum \@dbltopnum>\z@ \@tempswafalse \ifdim \@dbltoproom>\ht\@currbox \@tempswatrue \else \ifnum \@fpstype<\sixt@@n \advance \@dbltoproom \@textmin \ifdim \@dbltoproom>\ht\@currbox \@tempswatrue \fi \advance \@dbltoproom -\@textmin \fi \fi \if@tempswa \@bitor \@currtype \@deferlist % \end{macrocode} % % not in fixfloats? % \begin{macrocode} \@testwrongwidth\@currbox % \end{macrocode} % % \begin{macrocode} \if@test \else \@tempdima -\ht\@currbox \advance\@tempdima -\ifx \@dbltoplist\@empty \dbltextfloatsep \else \dblfloatsep \fi \global \advance \@dbltoproom \@tempdima \global \advance \@colht \@tempdima \global \advance \@dbltopnum \m@ne \@cons \@dbltoplist \@currbox \@inserttrue \fi \fi \fi \fi \if@insert \else \@cons\@deferlist\@currbox \fi \endgroup } % \end{macrocode} % % \begin{macrocode} \def \@addtocurcol {% \@insertfalse \@setfloattypecounts \ifnum \@fpstype=8 \else \ifnum \@fpstype=24 \else \@flsettextmin \advance \@textmin \@textfloatsheight \@reqcolroom \@pageht \ifdim \@textmin>\@reqcolroom \@reqcolroom \@textmin \fi \advance \@reqcolroom \ht\@currbox \ifdim \@colroom>\@reqcolroom \@flsetnum \@colnum \ifnum \@colnum>\z@ \@bitor\@currtype\@deferlist % \end{macrocode} % We need to defer the float also if its width % doesn't fit. % \changes{v0.03}{1998/08/17}{FMi: test for wide float was % in wrong place} % \begin{macrocode} \@testwrongwidth\@currbox % \end{macrocode} % % \begin{macrocode} \if@test \else \@bitor\@currtype\@botlist \if@test \@addtobot \else \ifodd \count\@currbox \advance \@reqcolroom \intextsep \ifdim \@colroom>\@reqcolroom \global \advance \@colnum \m@ne \global \advance \@textfloatsheight \ht\@currbox \global \advance \@textfloatsheight 2\intextsep \@cons \@midlist \@currbox \if@nobreak \nobreak \@nobreakfalse \everypar{}% \else \addpenalty \interlinepenalty \fi \vskip \intextsep \box\@currbox \penalty\interlinepenalty \vskip\intextsep \ifnum\outputpenalty <-\@Mii \vskip -\parskip\fi \outputpenalty \z@ \@inserttrue \fi \fi \if@insert \else \@addtotoporbot \fi \fi \fi \fi \fi \fi \fi \if@insert \else \@resethfps \@cons\@deferlist\@currbox \fi } % \end{macrocode} % % \begin{macrocode} \def\@xtryfc #1{% \@next\reserved@a\@trylist{}{}% \@currtype \count #1% \divide\@currtype\@xxxii \multiply\@currtype\@xxxii \@bitor \@currtype \@failedlist \@testfp #1% % \end{macrocode} % % \begin{macrocode} \@testwrongwidth #1% % \end{macrocode} % % \begin{macrocode} \ifdim \ht #1>\@colht \@testtrue \fi \if@test \@cons\@failedlist #1% \else \@ytryfc #1% \fi} % \end{macrocode} % % \begin{macrocode} \def\@ztryfc #1{% \@tempcnta\count #1% \divide\@tempcnta\@xxxii \multiply\@tempcnta\@xxxii \@bitor \@tempcnta {\@failedlist \@flfail}% \@testfp #1% % \end{macrocode} % % not in fixfloats? % \begin{macrocode} \@testwrongwidth #1% % \end{macrocode} % % \begin{macrocode} \@tempdimb\@tempdima \advance\@tempdimb\ht #1% \advance\@tempdimb\@fpsep \ifdim \@tempdimb >\@colht \@testtrue \fi \if@test \@cons\@flfail #1% \else \@cons\@flsucceed #1% \@tempdima\@tempdimb \fi} % \end{macrocode} % % \begin{macrocode} % % \end{macrocode} % % \Finale %