summaryrefslogtreecommitdiff
path: root/tex/context/base/mkiv/page-otr.mklx
diff options
context:
space:
mode:
Diffstat (limited to 'tex/context/base/mkiv/page-otr.mklx')
-rw-r--r--tex/context/base/mkiv/page-otr.mklx335
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