summaryrefslogtreecommitdiff
path: root/tex/context/base/mkiv/tabl-tsp.mkiv
diff options
context:
space:
mode:
Diffstat (limited to 'tex/context/base/mkiv/tabl-tsp.mkiv')
-rw-r--r--tex/context/base/mkiv/tabl-tsp.mkiv537
1 files changed, 537 insertions, 0 deletions
diff --git a/tex/context/base/mkiv/tabl-tsp.mkiv b/tex/context/base/mkiv/tabl-tsp.mkiv
new file mode 100644
index 000000000..e0c3b9b74
--- /dev/null
+++ b/tex/context/base/mkiv/tabl-tsp.mkiv
@@ -0,0 +1,537 @@
+%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 moved here from other places and needs
+%D a mkiv cleanup. As it mostly targets at tables the code lives in
+%D the tabl and page namespaces.
+
+% work in progress
+
+\unprotect
+
+%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}
+
+%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
+
+\installcorenamespace{floatsplitting}
+
+\installdirectcommandhandler \??floatsplitting {floatsplitting} % \??floatsplitting
+
+\setupfloatsplitting
+ [\c!conversion=\v!character, % \v!romannumerals
+ \c!lines=3,
+ \c!before=,
+ \c!inbetween=\page,
+ \c!after=]
+
+\newconditional\splitfloatfirstdone
+\newconditional\somenextsplitofffloat
+\newconditional\splitfloatdone
+\newconditional\onlyonesplitofffloat \settrue\onlyonesplitofffloat
+
+\newif \ifinsidesplitfloat % will become conditional
+
+\newcount \noffloatssplits
+\newtoks \everysplitfloatsetup
+
+\let \extrasplitfloatlines \!!zerocount
+\let \splitfloatfinalizer \relax
+\let \floatcaptionsuffix \empty
+
+\unexpanded\def\splitfloat
+ {\dosingleempty\page_split_float}
+
+\def\page_split_float[#1]#2% nog dubbele refs
+ {\bgroup
+ \global\setfalse\splitfloatdone
+ \aftergroup\page_split_float_check
+ \insidefloattrue
+ \insidesplitfloattrue
+ \setupcurrentfloatsplitting[#1]%
+ \global\noffloatssplits\zerocount
+ \let\floatcaptionsuffix\page_split_float_suffix
+ \edef\extrasplitfloatlines{\floatsplittingparameter\c!lines}%
+ \the\everysplitfloatsetup
+ \def\splitfloatcommand{#2}%
+ \global\settrue \onlyonesplitofffloat
+ \global\setfalse\somenextsplitofffloat
+ \page_floats_push_saved
+ \floatsplittingparameter\c!before
+ \let\next} % \bgroup
+
+\unexpanded\def\page_split_float_suffix
+ {\begingroup
+ \usefloatsplittingstyleandcolor\c!style\c!color % only the suffix
+ \convertnumber{\floatsplittingparameter\c!conversion}\noffloatssplits
+ \endgroup}
+
+\unexpanded\def\page_split_float_check
+ {\ifconditional\splitfloatdone
+ \splitfloatfinalizer % a weird place (could interfere with flushing)
+ \else
+ \blank
+ \begingroup
+ \tttf \dontleavehmode \getmessage\m!floatblocks{13}\empty
+ \endgroup
+ \blank
+ \showmessage\m!floatblocks{13}\empty
+ \fi}
+
+\def\page_split_float_process % nextbox
+ {\ifinsidesplitfloat
+ \expandafter\page_split_float_process_yes
+ \else
+ \expandafter\page_split_float_process_nop
+ \fi}
+
+\def\page_split_float_process_yes
+ {\dowithnextboxcs\page_split_float_process_finish\vbox}
+
+\def\page_split_float_process_finish
+ {\forgetall
+ \dontcomplain
+ \global\settrue\splitfloatdone
+ % \nodelocationmode\zerocount % bypass auto-renumbering
+ \global\advance\noffloatssplits\plusone
+ \ifcase\noffloatssplits\relax \or
+ \ifconditional\onlyonesplitofffloat
+ \let\floatcaptionsuffix\empty
+ \fi
+ \fi
+ \bgroup
+ \ifconditional\somenextsplitofffloat
+ \notesenabledfalse % best here, experimental, brrr; test with note in caption
+ \fi
+ \splitfloatcommand{\box\nextbox}%
+ \egroup
+ \ifconditional\somenextsplitofffloat
+ \edef\p_inbetween{\floatsplittingparameter\c!inbetween}%
+ \ifx\p_inbetween\empty
+ \ifconditional\splitfloatfirstdone\else\page\fi
+ \else
+ \p_inbetween
+ \fi
+ \else
+ \floatsplittingparameter\c!after
+ \page_floats_pop_saved
+ \page_floats_flush_saved
+ \fi
+ \global\settrue\splitfloatfirstdone}
+
+\def\page_split_float_process_nop
+ {\dowithnextboxcs\page_split_float_process_nop_finish\vbox}
+
+\def\page_split_float_process_nop_finish
+ {\forgetall
+ \dontcomplain
+ \box\nextbox % maybe an option to unvbox
+ \global\settrue\splitfloatfirstdone}
+
+\def\page_split_float_check_content#1% box
+ {\ifinsidesplitfloat
+ % \ifdim\ht#1=\zeropoint % funny: \ifcase does not check for overflow
+ \ifcase\ht#1\relax
+ \global\setfalse\somenextsplitofffloat
+ \else
+ \global\settrue \somenextsplitofffloat
+ \global\setfalse\onlyonesplitofffloat
+ \fi
+ \fi}
+
+\def\page_split_float_check_caption#1% depends on page-flt .. pretty messy
+ {\edef\extrasplitfloatlines{\extrasplitfloatlines}%
+ \ifx\extrasplitfloatlines\v!auto
+ \bgroup
+ \forcelocalfloats
+ \setuplocalfloats[\c!before=,\c!after=,\c!inbetween=]%
+ \splitfloatcommand{\hbox to #1{\strut}}% dummy line
+ \setbox\scratchbox\vbox{\flushlocalfloats}%
+ \getnoflines{\ht\scratchbox}%
+ \resetlocalfloats
+ \advance\noflines\minusone % compensate dummy line
+ \normalexpanded{\egroup\noexpand\edef\noexpand\extrasplitfloatlines{\the\noflines}}%
+ \global\settrue\usesamefloatnumber
+ \else
+ \doifelsenumber\extrasplitfloatlines\donothing{\def\extrasplitfloatlines{1}}%
+ \fi}
+
+\unexpanded\def\doifnotinsidesplitfloat
+ {\ifinsidesplitfloat
+ \expandafter\gobbleoneargument
+ \fi}
+
+%D Table splitter, on top of previous code:
+
+% todo: keep tail to rest, so we need a lookahead
+
+\newbox\tsplitcontent
+\newbox\tsplitresult
+\newbox\tsplithead
+\newbox\tsplitnext
+\newbox\tsplittail
+
+\newtoks\everyresettsplit
+
+\appendtoks
+ \let \tsplitminimumfreelines\!!zerocount
+ \let \tsplitminimumfreespace\!!zeropoint
+ \setbox\tsplitcontent \emptyvbox
+ \setbox\tsplitresult \emptyvbox
+ \setbox\tsplithead \emptyvbox
+ \setbox\tsplitnext \emptyvbox
+ \setbox\tsplittail \emptyvbox
+ \let \tsplitbeforeresult \donothing
+ \let \tsplitafterresult \donothing
+ \let \tsplitinbetween \donothing
+ \let \tsplitbefore \donothing
+ \let \tsplitafter \donothing
+ \let \postprocesstsplit \donothing
+\to \everyresettsplit
+
+\unexpanded\def\resettsplit
+ {\the\everyresettsplit}
+
+\resettsplit
+
+\def\tsplitdirectwidth{\hsize}
+
+\newconditional\c_tabl_split_done
+\newconditional\c_tabl_split_head
+\newconditional\c_tabl_split_full
+
+\newdimen \d_tabl_split_available
+
+\unexpanded\def\handletsplit
+ {\page_split_float_check_caption{\wd\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
+ \setfalse\c_tabl_split_done
+ \doloop\tabl_split_loop_body
+ \global\setfalse\usesamefloatnumber % new, prevent next increment
+ \global\setfalse\splitfloatfirstdone} % we can use this one for tests
+
+\newconditional\tabl_split_forced_page
+
+\def\tabl_split_loop_body
+ {\ifinsidecolumns
+ % brrr, assumes empty columns
+ \global\setfalse\splitfloatfirstdone
+ \d_tabl_split_available\textheight
+ \settrue\c_tabl_split_full
+ \else
+ \ifconditional\splitfloatfirstdone
+ \d_tabl_split_available\textheight
+ \settrue\c_tabl_split_full
+ \else\ifdim\pagegoal<\maxdimen
+ \d_tabl_split_available\dimexpr\pagegoal-\pagetotal\relax
+ \setfalse\c_tabl_split_full
+ \else
+ \d_tabl_split_available\textheight
+ \settrue\c_tabl_split_full
+ \fi\fi
+ \fi
+ \d_tabl_split_available \dimexpr
+ \d_tabl_split_available
+ -\tsplitinbetweenheight
+ -\tsplitminimumfreespace
+ -\extrasplitfloatlines\lineheight
+ \relax
+ \ifdim\htdp\tsplittail>\zeropoint
+ \advance\d_tabl_split_available-\htdp\tsplittail
+ \fi
+ \setbox\tsplitresult\vbox
+ {\ifdim\ht\tsplithead>\zeropoint
+ \unvcopy\tsplithead
+ \tsplitinbetween
+ \fi}%
+ \ifconditional\c_tabl_split_done \else
+ \ifdim\ht\tsplitnext>\zeropoint
+ \setbox\tsplithead\box\tsplitnext
+ \fi
+ \fi
+ \settrue\c_tabl_split_done
+ \ifdim\ht\tsplitresult>\zeropoint
+ \settrue\c_tabl_split_head % table head
+ \else
+ \setfalse\c_tabl_split_head % no tablehead
+ \fi
+ \splittopskip\zeropoint
+ \doloop % inner loop
+ {\setbox\scratchbox\vsplit\tsplitcontent to \onepoint % \lineheight
+ \setbox\scratchbox\vbox % \vpack
+ {\unvbox\scratchbox
+ \setbox\scratchbox\vbox
+ {\splitdiscards
+ \ifnum\lastpenalty>-\plustenthousand\else
+ % so that \bTR[before=\page] works
+ \global\settrue\tabl_split_forced_page
+ \fi}}%
+ \ifconditional\tabl_split_forced_page
+ \global\setfalse\tabl_split_forced_page
+ \setbox\tsplitresult\vbox
+ {\unvbox\tsplitresult
+ \tsplitinbetween
+ \unvbox\scratchbox}%
+ \exitloop
+ \else\ifdim\dimexpr\d_tabl_split_available-\htdp\scratchbox-\htdp\tsplitresult\relax>\zeropoint
+ \setbox\tsplitresult\vbox
+ {\unvbox\tsplitresult
+ \tsplitinbetween
+ \unvbox\scratchbox}%
+ \ifvoid\tsplitcontent \exitloop \fi
+ \else\ifconditional\c_tabl_split_head
+ % we only have a tablehead so far
+ \setbox\tsplitresult\vbox{\unvbox\tsplitresult\unvbox\scratchbox}%
+ \exitloop
+ \else\ifconditional\c_tabl_split_full
+ % 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\fi
+ \setfalse\c_tabl_split_head
+ \setfalse\c_tabl_split_full}%
+ \postprocesstsplit
+ \page_split_float_check_content\tsplitcontent
+ \ifvoid\tsplitcontent
+ \setbox\tsplitresult\vbox
+ {\unvbox\tsplitresult
+ \tsplitinbetween
+ \unvcopy\tsplittail}%
+ \page_split_float_process{\tsplitbeforeresult\box\tsplitresult\tsplitafterresult}%
+ \doifnotinsidesplitfloat\tsplitafter
+ \endgraf
+ \exitloop
+ \else
+ % hack
+ \ifdim\pagegoal<\maxdimen
+ \pagegoal\dimexpr\pagegoal+\lineheight\relax % etex
+ \fi
+ % brrr
+ \ifdim\ht\tsplitresult>\zeropoint
+ \setbox\tsplitresult\vbox
+ {\unvbox\tsplitresult
+ \tsplitinbetween
+ \unvcopy\tsplittail}%
+ \page_split_float_process{\tsplitbeforeresult\box\tsplitresult\tsplitafterresult}%
+ \doifnotinsidesplitfloat\tsplitafter
+ \endgraf
+ \fi
+ \ifinsidecolumns
+ \goodbreak % was \doifnotinsidesplitfloat\goodbreak
+ \else
+ \page % was \doifnotinsidesplitfloat\page
+ \fi
+ \global\settrue\usesamefloatnumber % new, prevent next increment
+ \fi}
+
+%D The next one assumes that the split takes place elsewhere. This is
+%D used in xtables.
+
+\let\resetdirecttsplit\resettsplit
+
+\unexpanded\def\handledirecttsplit
+ {\page_split_float_check_caption{\tsplitdirectwidth}%
+ \global\setfalse\splitfloatfirstdone
+ \testpagesync % new, sync, but still tricky
+ [\tsplitminimumfreelines]
+ [\dimexpr\tsplitminimumfreespace+\extrasplitfloatlines\lineheight\relax]%
+ \doloop\tabl_split_direct_loop_body
+ \global\setfalse\usesamefloatnumber % new, prevent next increment
+ \global\setfalse\splitfloatfirstdone} % we can use this one for tests
+
+\def\tabl_split_direct_loop_body
+ {\ifinsidecolumns
+ \global\setfalse\splitfloatfirstdone
+ \d_tabl_split_available\textheight
+ \else\ifconditional\splitfloatfirstdone
+ \d_tabl_split_available\textheight
+ \else\ifdim\pagegoal<\maxdimen
+ \d_tabl_split_available\dimexpr\pagegoal-\pagetotal\relax
+ \else
+ \d_tabl_split_available\textheight
+ \fi\fi\fi
+ \d_tabl_split_available\dimexpr
+ \d_tabl_split_available
+ -\tsplitminimumfreespace
+ -\extrasplitfloatlines\lineheight
+ \relax
+ \tsplitdirectsplitter\d_tabl_split_available % also sets state
+ \ifdim\ht\tsplitresult>\zeropoint
+ \ifconditional\somenextsplitofffloat
+ \global\setfalse\onlyonesplitofffloat
+ \fi
+ \ifdim\pagegoal<\maxdimen
+ \pagegoal\dimexpr\pagegoal+\lineheight\relax % etex
+ \fi
+ \page_split_float_process{\tsplitbeforeresult\box\tsplitresult\tsplitafterresult}%
+ \global\settrue\usesamefloatnumber % new, prevent next increment
+ \endgraf
+ \ifconditional\somenextsplitofffloat
+ \ifinsidecolumns
+ \goodbreak
+ \else
+ \page
+ \fi
+ \fi
+ \global\settrue\splitfloatfirstdone
+ \else\ifconditional\somenextsplitofffloat
+ \ifinsidecolumns
+ \goodbreak
+ \else
+ \page % no room
+ \fi
+ \else
+ \exitloop
+ \fi\fi}
+
+\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