diff options
Diffstat (limited to 'tex/context/base/mkiv/page-otr.mklx')
-rw-r--r-- | tex/context/base/mkiv/page-otr.mklx | 335 |
1 files changed, 335 insertions, 0 deletions
diff --git a/tex/context/base/mkiv/page-otr.mklx b/tex/context/base/mkiv/page-otr.mklx new file mode 100644 index 000000000..797e31274 --- /dev/null +++ b/tex/context/base/mkiv/page-otr.mklx @@ -0,0 +1,335 @@ +%D \module +%D [ file=page-otr, +%D version=2012.01.25, +%D title=\CONTEXT\ Page Macros, +%D subtitle=Output Routines, +%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 Page Macros / Output Routines} + +%D This module will get some of the code from other modules. At the same time we +%D provide a bit more control. + +% When issuing two \par\penalty-\plustenthousand's, only the first triggers the +% otr. Is this an obscure feature or an optimization? + +\registerctxluafile{page-otr}{} + +\unprotect + +\let\triggerpagebuilder\clf_triggerpagebuilder + +\def\m!otr{otr} % todo + +\installcorenamespace{outputroutine} + +\installswitchcommandhandler \??outputroutine {outputroutine} \??outputroutine + +\newtoks\t_page_otr_commands +\newtoks\t_page_otr_tracers + +\protected\def\defineoutputroutinecommand[#name]% doing multiple on one go saves syncing + {\processcommalist[#name]\page_otr_commands_define} + +\protected\def\page_otr_commands_define#name% + {\ifcsname#name\endcsname \else + \letcsname#name\endcsname\relax + \normalexpanded{\t_page_otr_commands{\the\t_page_otr_commands\noexpand\page_otr_commands_process{#name}}}% + \fi} + +\let\page_otr_commands_process\gobbleoneargument + +\appendtoks + \let\page_otr_commands_process\page_otr_specifics_preset + \the\t_page_otr_commands + \let\page_otr_commands_process\gobbleoneargument +\to \everyswitchoutputroutine + +\protected\def\page_otr_specifics_preset#name% + {\edef\page_otr_specifics_command{\directoutputroutineparameter{#name}}% no inheritance of commands + \ifempty\page_otr_specifics_command + \writestatus{\currentoutputroutine}{- \expandafter\strippedcsname\csname#name\endcsname}% + \letcsname#name\endcsname\relax + \else + \writestatus{\currentoutputroutine}{+ \expandafter\strippedcsname\csname#name\endcsname}% + \letcsname#name\expandafter\endcsname\page_otr_specifics_command + \fi} + +\protected\def\page_otr_specifics_preset_normal#name% + {\edef\page_otr_specifics_command{\directoutputroutineparameter{#name}}% no inheritance of commands + \ifempty\page_otr_specifics_command + \letcsname#name\endcsname\relax + \else + \letcsname#name\expandafter\endcsname\page_otr_specifics_command + \fi} + +\protected\def\page_otr_specifics_preset_traced#name% + {\edef\page_otr_specifics_command{\directoutputroutineparameter{#name}}% no inheritance of commands + \ifempty\page_otr_specifics_command + \writestatus{\currentoutputroutine}{preset: - \expandafter\strippedcsname\csname#name\endcsname}% + \letcsname#name\endcsname\relax + \else + \writestatus{\currentoutputroutine}{preset: + \expandafter\strippedcsname\csname#name\endcsname}% + \letcsname#name\expandafter\endcsname\page_otr_specifics_command + \fi} + +\let\page_otr_specifics_preset\page_otr_specifics_preset_normal + +\protected\def\traceoutputroutines + {\the\t_page_otr_tracers} + +\appendtoks + \let\page_otr_specifics_preset\page_otr_specifics_preset_traced +\to \t_page_otr_tracers + +%D We have a couple of output routines and the default one is +%D the single column routine. Then there is a multicolumn variant +%D that can be used mixed, and a columnset variant that is more +%D exclusive. + +\installcorenamespace{otrtriggers} + +\newconstant\c_page_otr_eject_penalty \c_page_otr_eject_penalty -\plustenthousand +\newconstant\c_page_otr_super_penalty \c_page_otr_super_penalty -\plustwentythousand +\newcount \c_page_otr_trigger_penalty \c_page_otr_trigger_penalty -100010 + +\newcount \c_page_otr_columns % we will share this one + +\newif \ifinotr % we keep this (name) for old times sake + +% \def\page_otr_update_page_goal#1#2% +% {\global\c_page_otr_columns#2\relax +% \pagegoal\dimexpr\vsize-\c_page_otr_columns\insertheights\relax} + +\appendtoks + \insertheights\zeropoint +\to \everyaftershipout + +\protected\def\page_otr_message_b{\page_otr_message_s+} +\protected\def\page_otr_message_e{\page_otr_message_s-} + +\protected\def\page_otr_message_s#sign#what% + {\writestatus + \currentoutputroutine + {#sign\space \space + #what\space \space + p:\the\outputpenalty,\space + r:\the\realpageno ,\space + c:\number\mofcolumns,\space + v:\the\vsize ,\space + g:\the\pagegoal ,\space + t:\the\pagetotal ,\space + i:\the\insertheights + \ifdim\pagetotal>\pagegoal + ,\space + d:\the\dimexpr\pagetotal-\pagegoal\relax + \fi}} + +\protected\def\page_otr_trigger#penalty% + {\begingroup + \par + \penalty#penalty% + \endgroup} + +\protected\def\installoutputroutine#invoke#action% \invoke \action + {\global\advance\c_page_otr_trigger_penalty\minusone + \frozen\protected\edef#invoke{\page_otr_trigger{\number\c_page_otr_trigger_penalty}}% + \setvalue{\??otrtriggers\number\c_page_otr_trigger_penalty}{#action}} + +\protected\def\page_otr_triggered_output_routine_traced + {\ifcsname\??otrtriggers\the\outputpenalty\endcsname + \page_otr_message_b{special}% + \csname\??otrtriggers\the\outputpenalty\endcsname % \lastnamedcs can be gone + \page_otr_message_e{special}% + \else + \page_otr_message_b{normal}% + \page_otr_command_routine + \page_otr_message_e{normal}% + \fi} + +\protected\def\page_otr_triggered_output_routine_normal + {\ifcsname\??otrtriggers\the\outputpenalty\endcsname + \lastnamedcs + \else + \page_otr_command_routine + \fi} + +\let\page_otr_triggered_output_routine\page_otr_triggered_output_routine_normal + +\appendtoks + \let\page_otr_triggered_output_routine\page_otr_triggered_output_routine_traced +\to \t_page_otr_tracers + +%D The real routine handler: + +\ifdefined\everybeforeoutput \else \newtoks\everybeforeoutput \fi +\ifdefined\everyafteroutput \else \newtoks\everyafteroutput \fi + +\def\page_otr_set_engine_output_routine#content% + {\global\output + {\inotrtrue + \the\everybeforeoutput + #content\relax + \the\everyafteroutput}} + +% Just as fuzzy (and in 'one' we are okay with \aftergroup anyway): +% +% \ifdefined\everybeforeoutputgroup \else \newtoks\everybeforeoutputgroup \fi +% \ifdefined\everyafteroutputgroup \else \newtoks\everyafteroutputgroup \fi +% +% \def\page_otr_set_engine_output_routine#content% +% {\the\everybeforeoutputgroup +% \global\output +% {\inotrtrue +% \the\everybeforeoutput +% #content\relax +% \the\everyafteroutput +% \aftergroup\the\aftergroup\everyafteroutputgroup}} +% +% \appendtoks +% \ifnum\c_page_postponed_mode=\plusone +% \page_postponed_blocks_flush % and then not in \page_otr_construct_and_shipout +% \fi +% \to \everyafteroutputgroup + +\page_otr_set_engine_output_routine\page_otr_triggered_output_routine + +\installoutputroutine\synchronizeoutput % use \triggerpagebuilder instead + {\ifvoid\normalpagebox\else + \unvbox\normalpagebox + % not \pagediscards as it does more harm than good + \fi} + +\installoutputroutine\discardpage + {\setbox\scratchbox\box\normalpagebox} + +% todo: \resetpagebreak -> everyejectpage + +\def\page_otr_trigger_output_routine + {\par + \ifvmode + \penalty\c_page_otr_eject_penalty + \fi + \resetpagebreak} + +\def\page_otr_fill_and_eject_page + {\par + \ifvmode + \vfill + \penalty\c_page_otr_eject_penalty + \fi + \resetpagebreak} + +\def\page_otr_eject_page + {\par + \ifvmode + \ifdim\pagetotal>\pagegoal \else + \normalvfil + \fi + \penalty\c_page_otr_eject_penalty + \fi + \resetpagebreak} + +\def\page_otr_eject_page_and_flush_inserts % can be an installed one + {\par + \ifvmode + \ifdim\pagetotal>\pagegoal \else + \normalvfil + \fi + \penalty\c_page_otr_super_penalty + \fi + \resetpagebreak} + +\def\page_otr_check_for_pending_inserts + {\ifnum\outputpenalty>\c_page_otr_super_penalty \else + \ifnum\insertpenalties>\zerocount + % something is being held over so we force a new page + \page_otr_force_another_page + \fi + \fi} + +\def\page_otr_force_another_page + {% we should actually remove the dummy line in the otr + \hpack to \hsize{}% + \kern-\topskip + \nobreak + \vfill + \penalty\c_page_otr_super_penalty + \resetpagebreak} + +%D For those who've read the plain \TEX\ book, we provide the next +%D macro: + +\protected\def\bye + {\writestatus\m!system{Sorry, you're not done yet, so no goodbye!}} + +%D We define a few constants because that (1) provides some checking +%D and (2) is handier when aligning definitions (checks nicer). Most +%D routines will use ard codes names but sometimes we want to adapt, +%D which is why we have these: + +\definesystemconstant{page_otr_command_routine} +\definesystemconstant{page_otr_command_package_contents} +\definesystemconstant{page_otr_command_set_vsize} +\definesystemconstant{page_otr_command_set_hsize} +\definesystemconstant{page_otr_command_synchronize_hsize} +\definesystemconstant{page_otr_command_next_page} +\definesystemconstant{page_otr_command_next_page_and_inserts} +\definesystemconstant{page_otr_command_set_top_insertions} +\definesystemconstant{page_otr_command_set_bottom_insertions} +\definesystemconstant{page_otr_command_flush_top_insertions} +\definesystemconstant{page_otr_command_flush_bottom_insertions} +\definesystemconstant{page_otr_command_check_if_float_fits} +\definesystemconstant{page_otr_command_set_float_hsize} +\definesystemconstant{page_otr_command_flush_float_box} +\definesystemconstant{page_otr_command_side_float_output} +\definesystemconstant{page_otr_command_synchronize_side_floats} +\definesystemconstant{page_otr_command_flush_floats} +\definesystemconstant{page_otr_command_flush_side_floats} +\definesystemconstant{page_otr_command_flush_saved_floats} +\definesystemconstant{page_otr_command_flush_all_floats} +\definesystemconstant{page_otr_command_flush_margin_blocks} +\definesystemconstant{page_otr_command_test_column} +\definesystemconstant{page_otr_command_flush_facing_floats} + +\definesystemconstant{singlecolumn} +\definesystemconstant{multicolumn} % will move +\definesystemconstant{columnset} % will move +\definesystemconstant{pagecolumn} % will move + +\defineoutputroutinecommand + [\s!page_otr_command_routine, + \s!page_otr_command_package_contents, + \s!page_otr_command_set_vsize, + \s!page_otr_command_set_hsize, + \s!page_otr_command_synchronize_hsize, % for columns of different width + \s!page_otr_command_next_page, + \s!page_otr_command_next_page_and_inserts, + \s!page_otr_command_set_top_insertions, + \s!page_otr_command_set_bottom_insertions, + \s!page_otr_command_flush_top_insertions, + \s!page_otr_command_flush_bottom_insertions, + \s!page_otr_command_check_if_float_fits, + \s!page_otr_command_set_float_hsize, + \s!page_otr_command_flush_float_box, + \s!page_otr_command_side_float_output, % name will change as will hooks + \s!page_otr_command_synchronize_side_floats, + \s!page_otr_command_flush_floats, + \s!page_otr_command_flush_side_floats, + \s!page_otr_command_flush_saved_floats, + \s!page_otr_command_flush_all_floats, + \s!page_otr_command_flush_margin_blocks, + \s!page_otr_command_test_column, + \s!page_otr_command_flush_facing_floats] + +\appendtoks + \setupoutputroutine[\s!singlecolumn]% +\to \everydump + +\protect \endinput |