%D \module %D [ file=tabl-tsp, %D version=2000.10.20, %D title=\CONTEXT\ Table Macros, %D subtitle=Splitting, %D author=Hans Hagen, %D date=\currentdate, %D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] %C %C This module is part of the \CONTEXT\ macro||package and is %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. \writestatus{loading}{ConTeXt Table Macros / Splitting} %D The code in this file is move here from other places. \unprotect % only to be used with single tokens (will be prim) \ifx\htdp\undefined \def\htdp#1{\dimexpr\ht#1+\dp#1\relax} \fi %D Although the name resembles floats, and therefore this should be %D a page module, we decided to make it core functionality because the %D table code depends on it. Othrwise there would be too much %D overloading afterwards involved. Actually, the float part is rather %D generic and not that related to floats. % \splitfloat [settings] {\placetable[optional args]{test}} {content} \definenumber [\??si] [\c!way=\v!by\v!text, \c!conversion=\@@siconversion] \def\setupfloatsplitting {\dodoubleargument\getparameters[\??si]} \newif\ifinsidesplitfloat % will become chardef \newtoks \everysplitfloatsetup \def\splitfloat {\dosingleempty\dosplitfloat} \ifx\floatcaptionsuffix\undefined \else \let\floatcaptionsuffix\empty % will become \splitfloatcaptionsuffix \fi \def\extrasplitfloatlines{0} \def\dosplitfloat[#1]#2% nog dubbele refs {\bgroup \global\setfalse\splitfloatdone \aftergroup\checksplitfloat \insidefloattrue \insidesplitfloattrue \getparameters[\??si][#1]% \resetnumber[\??si]% \def\floatcaptionsuffix{\convertednumber[\??si]}% \let\extrasplitfloatlines\@@silines \the\everysplitfloatsetup \def\splitfloatcommand{#2}% \global\settrue \onlyonesplitofffloat \global\setfalse\somenextplitofffloat \dopushsavedfloats \@@sibefore \let\next} % \bgroup \def\checksplitfloat {\ifconditional\splitfloatdone\else \blank{\tttf \getmessage\m!floatblocks{13}\empty}\blank \showmessage\m!floatblocks{13}\empty \fi} \settrue \onlyonesplitofffloat \setfalse\somenextplitofffloat %D When \type {inbetween} is made empty instead of the %D default \type {\page}, we will get delayed flushing %D and text may continue below the graphic. %D %D \starttyping %D \dorecurse{2}{\input tufte } %D %D \splitfloat[lines=auto,inbetween=] %D {\placetable{\dorecurse{5}{test\recurselevel\endgraf}}} %D {\bTABLE[split=yes] %D \bTR \bTD 11 \eTD \bTD \input tufte \eTD \eTR %D \bTR \bTD 12 \eTD \bTD \input zapf \eTD \eTR %D \bTR \bTD 13 \eTD \bTD \input bryson \eTD \eTR %D \bTR \bTD 14 \eTD \bTD test \eTD \eTR %D \bTR \bTD 21 \eTD \bTD \input tufte \eTD \eTR %D \bTR \bTD 22 \eTD \bTD \input zapf \eTD \eTR %D \bTR \bTD 23 \eTD \bTD \input bryson \eTD \eTR %D \bTR \bTD 24 \eTD \bTD test \eTD \eTR %D \bTR \bTD 31 \eTD \bTD \input tufte \eTD \eTR %D \bTR \bTD 32 \eTD \bTD \input zapf \eTD \eTR %D \bTR \bTD 33 \eTD \bTD \input bryson \eTD \eTR %D \bTR \bTD 34 \eTD \bTD test \eTD \eTR %D \eTABLE} %D %D \dorecurse{10}{\input tufte } %D \stoptyping \newconditional\splitfloatdone \def\dodowithsplitofffloat {\dowithnextbox {\forgetall \dontcomplain \global\settrue\splitfloatdone \chardef\nodelocationmode\zerocount % bypass auto-renumbering \incrementnumber[\??si]% \ifcase\rawnumber[\??si]\or \ifconditional\onlyonesplitofffloat \let\floatcaptionsuffix\empty \fi \fi \bgroup \ifconditional\somenextplitofffloat \settrue\retainfloatnumber \notesenabledfalse % best here, experimental, brrr; test with note in caption \else \setfalse\retainfloatnumber \fi \splitfloatcommand{\box\nextbox}% \egroup \ifconditional\somenextplitofffloat \doifelsenothing\@@siinbetween {\ifconditional\splitfloatfirstdone\else\page\fi} \@@siinbetween \else \@@siafter \dopopsavedfloats \doflushsavedfloats \fi \global\settrue\splitfloatfirstdone}% \vbox} \def\nodowithsplitofffloat {\dowithnextbox {\forgetall \dontcomplain \box\nextbox % maybe an option to unvbox \global\settrue\splitfloatfirstdone}% \vbox} \def\dochecksplitofffloat#1% box {\ifinsidesplitfloat \ifdim\ht#1=\zeropoint \global\setfalse\somenextplitofffloat \else \global\settrue \somenextplitofffloat \global\setfalse\onlyonesplitofffloat \fi \fi} \def\analyzesplitfloatcaption#1% depends on page-flt {\doif\extrasplitfloatlines\v!auto {\bgroup \settrue\retainfloatnumber \chardef\nodelocationmode\zerocount \forcelocalfloats \setuplocalfloats[\c!before=,\c!after=,\c!inbetween=]% \splitfloatcommand{\hbox to \wd#1{\strut}}% dummy line \setbox\scratchbox\vbox{\flushlocalfloats}% \getnoflines{\ht\scratchbox}% \resetlocalfloats \advance\noflines\minusone % compensate dummy line \expanded{\egroup\noexpand\edef\noexpand\extrasplitfloatlines{\the\noflines}}}} % \def\analyzesplitfloatcaption#1% % {\edef\extrasplitfloatlines{11}} \def\dowithsplitofffloat % nextbox {\ifinsidesplitfloat \expandafter\dodowithsplitofffloat \else \expandafter\nodowithsplitofffloat \fi} \def\doifnotinsidesplitfloat {\ifinsidesplitfloat\expandafter\gobbleoneargument\fi} %D Some defaults: \setupfloatsplitting [\c!conversion=\v!character, % \v!romannumerals \c!lines=3, \c!before=, \c!inbetween=\page, \c!after=] %D Table splitter, on top of previous code: \newbox\tsplitcontent \newbox\tsplitresult \newbox\tsplithead \newbox\tsplitnext \newbox\tsplittail \def\resettsplit{% only \def's starting a a new line are seen by the dep checker \def\tsplitminimumfreelines{0}% \def\tsplitminimumfreespace{0pt}% \setbox\tsplitcontent \vbox{}% \setbox\tsplitresult \vbox{}% \setbox\tsplithead \vbox{}% \setbox\tsplitnext \vbox{}% \setbox\tsplittail \vbox{}% \let\tsplitbeforeresult\donothing \let\tsplitafterresult \donothing \let\tsplitinbetween \donothing \let\tsplitbefore \donothing \let\tsplitafter \donothing \let\postprocesstsplit \donothing } \resettsplit % todo: keep tail to rest, so we need a lookahead \newconditional\splitfloatfirstdone \def\handletsplit {\analyzesplitfloatcaption\tsplitcontent \global\setfalse\splitfloatfirstdone \testpagesync % new, sync, but still tricky [\tsplitminimumfreelines] [\dimexpr\tsplitminimumfreespace+\extrasplitfloatlines\lineheight\relax]% \setbox\scratchbox\vbox{\tsplitinbetween}% \edef\tsplitinbetweenheight{\the\htdp\scratchbox}% etex \!!doneafalse \doloop {\ifinsidecolumns % brrr, assumes empty columns \global\setfalse\splitfloatfirstdone \scratchdimen\textheight \!!donectrue \else \ifconditional\splitfloatfirstdone \scratchdimen\textheight \!!donectrue \else\ifdim\pagegoal<\maxdimen \scratchdimen\dimexpr\pagegoal-\pagetotal\relax \!!donecfalse \else \scratchdimen\textheight \!!donectrue \fi\fi \fi \scratchdimen\dimexpr\scratchdimen-\tsplitinbetweenheight-\tsplitminimumfreespace-\extrasplitfloatlines\lineheight\relax \ifdim\htdp\tsplittail>\zeropoint \advance\scratchdimen-\htdp\tsplittail \fi \setbox\tsplitresult\vbox {\ifdim\ht\tsplithead>\zeropoint \unvcopy\tsplithead \tsplitinbetween \fi}% \if!!donea\else\ifdim\ht\tsplitnext>\zeropoint \setbox\tsplithead\box\tsplitnext \fi\fi \!!doneatrue \ifdim\ht\tsplitresult>\zeropoint \!!donedtrue % table head \else \!!donedfalse % no tablehead \fi \splittopskip\zeropoint \doloop {\setbox\scratchbox\vsplit\tsplitcontent to \onepoint % \lineheight \setbox\scratchbox\vbox{\unvbox\scratchbox}% \ifdim\dimexpr\scratchdimen-\htdp\scratchbox-\htdp\tsplitresult\relax>\zeropoint \setbox\tsplitresult\vbox {\unvbox\tsplitresult \tsplitinbetween \unvbox\scratchbox}% \ifvoid\tsplitcontent \exitloop \fi \else\if!!doned % we only have a tablehead so far \setbox\tsplitresult\vbox{\unvbox\tsplitresult\unvbox\scratchbox}% \exitloop \else\if!!donec % we have text height available, but the (one) cell is too % large to fit, so, in order to avoid loops/deadcycles we do: \setbox\tsplitresult\vbox {\unvbox\tsplitresult \tsplitinbetween \unvbox\scratchbox}% \exitloop \else \setbox\tsplitcontent\vbox {\unvbox\scratchbox \tsplitinbetween \ifvoid\tsplitcontent\else\unvbox\tsplitcontent\fi}% \exitloop \fi\fi\fi \!!donedfalse \!!donecfalse}% \postprocesstsplit \dochecksplitofffloat\tsplitcontent \ifvoid\tsplitcontent \setbox\tsplitresult\vbox {\unvbox\tsplitresult \tsplitinbetween \unvcopy\tsplittail}% \dowithsplitofffloat{\tsplitbeforeresult\box\tsplitresult\tsplitafterresult}% \doifnotinsidesplitfloat\tsplitafter \endgraf \exitloop \else % hack \ifdim\pagegoal<\maxdimen \global\pagegoal\dimexpr\pagegoal+\lineheight\relax % etex \fi % brrr \ifdim\ht\tsplitresult>\zeropoint \setbox\tsplitresult\vbox {\unvbox\tsplitresult \tsplitinbetween \unvcopy\tsplittail}% \dowithsplitofffloat{\tsplitbeforeresult\box\tsplitresult\tsplitafterresult}% \doifnotinsidesplitfloat\tsplitafter \endgraf \fi \ifinsidecolumns \doifnotinsidesplitfloat\goodbreak \else \doifnotinsidesplitfloat\page \fi \fi}% \global\setfalse\splitfloatfirstdone} % we can use this one for tests \protect \endinput % test cases % \setupTABLE[split=repeat] % % \input tufte \endgraf % \splitfloat[lines=11] % {\placetable{\dorecurse{10}{test\recurselevel\endgraf}}} % {\bTABLE\dorecurse{100}{\bTR \bTD test \eTD \eTR}\eTABLE} % \input tufte \page % % \input tufte \endgraf % \splitfloat[lines=0] % {} % {\bTABLE\dorecurse{100}{\bTR \bTD test \eTD \eTR}\eTABLE} % \input tufte \endgraf \page % % \input tufte \endgraf % \bTABLE\dorecurse{100}{\bTR \bTD test \eTD \eTR}\eTABLE % \input tufte \page % \setuptabulate[split=yes] % % \input tufte \endgraf % \splitfloat[lines=11] % {\placetable{\dorecurse{10}{test\recurselevel\endgraf}}} % {\starttabulate\dorecurse{200}{\NC test \NC test \NC \NR}\stoptabulate} % \input tufte \page % % \input tufte \endgraf % \splitfloat[lines=0] % {} % {\starttabulate\dorecurse{200}{\NC test \NC test \NC \NR}\stoptabulate} % \input tufte \page % % \input tufte \endgraf % \starttabulate\dorecurse{200}{\NC test \NC test \NC \NR}\stoptabulate % \input tufte \page % \setuptables[split=yes] % % \newtoks\TestToks % % \TestToks\emptytoks % \appendtoks\starttablehead\to\TestToks % \dorecurse{3}{\appendtoks\VL head \VL head \VL \SR\to\TestToks} % \appendtoks\stoptablehead\to\TestToks % \appendtoks\starttabletail\to\TestToks % \dorecurse{3}{\appendtoks\VL tail \VL tail \VL \SR\to\TestToks} % \appendtoks\stoptabletail\to\TestToks % \appendtoks\starttables[|c|c|]\to\TestToks % \dorecurse{100}{\appendtoks\VL test \VL test \VL \SR\to\TestToks} % \appendtoks\stoptables\to\TestToks % % \input tufte \endgraf % \splitfloat[lines=auto] % [lines=11] % {\placetable{\dorecurse{10}{test\recurselevel\endgraf}}} % {\the\TestToks} % \input tufte \page % % \input tufte \endgraf % \splitfloat[lines=0] % {} % {\the\TestToks} % \input tufte \page % % \input tufte \endgraf % \the\TestToks % \input tufte \page % % multiple floats % % \starttext % \dorecurse{3}{\input tufte } \endgraf % \dorecurse{5}{\placefigure{}{\framed[height=.5\textheight]{}}} % \splitfloat[lines=auto,inbetween=] % {\placetable{\dorecurse{5}{test\recurselevel\endgraf}}} % {\bTABLE[split=yes] % \bTR \bTD 11 \eTD \bTD \input tufte \eTD \eTR % \bTR \bTD 12 \eTD \bTD \input zapf \eTD \eTR % \bTR \bTD 13 \eTD \bTD \input bryson \eTD \eTR % \bTR \bTD 14 \eTD \bTD test \eTD \eTR % \bTR \bTD 21 \eTD \bTD \input tufte \eTD \eTR % \bTR \bTD 22 \eTD \bTD \input zapf \eTD \eTR % \bTR \bTD 23 \eTD \bTD \input bryson \eTD \eTR % \bTR \bTD 24 \eTD \bTD test \eTD \eTR % \bTR \bTD 31 \eTD \bTD \input tufte \eTD \eTR % \bTR \bTD 32 \eTD \bTD \input zapf \eTD \eTR % \bTR \bTD 33 \eTD \bTD \input bryson \eTD \eTR % \bTR \bTD 34 \eTD \bTD test \eTD \eTR % \eTABLE} % \dorecurse{10}{\input tufte } % \stoptext