% macros=mkvi

%D \module
%D   [       file=page-txt, % copied from main-001,
%D        version=1997.03.31,
%D          title=\CONTEXT\ Page Macros,
%D       subtitle=Texts,
%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 / Texts}

\unprotect

\newtoks\toptextcontent     \newtoks\leftedgetextcontent
\newtoks\headertextcontent  \newtoks\leftmargintextcontent
\newtoks\footertextcontent  \newtoks\rightmargintextcontent
\newtoks\bottomtextcontent  \newtoks\rightedgetextcontent

\newtoks\texttextcontent

%D \macros
%D  {setuptop, setupheader, setuptext,setupfooter, setupbottom}
%D
%D The macros in this module sometimes look a bit more complicated than needed,
%D which is a direct result of the fact that their ancestors are quite old and
%D upward compatibility is a must.
%D
%D \showsetup{setuptop}
%D \showsetup{setupheader}
%D \showsetup{setuptext}
%D \showsetup{setupfooter}
%D \showsetup{setupbottom}

\installcorenamespace{layouttexts}
\installcorenamespace{layouttextsline}
%installcorenamespace{layouttextsreset}
\installcorenamespace{layouttextssynchronize}
\installcorenamespace{layouttextstrut}
\installcorenamespace{layouttextspecial}
\installcorenamespace{layouttextcontent}

\installcommandhandler \??layouttexts {layoutelement} \??layouttexts

% \appendtoks
%     \resetlayoutelementparameter\c!lefttext   % resolves better
%     \resetlayoutelementparameter\c!middletext
%     \resetlayoutelementparameter\c!righttext
% \to \everydefinelayoutelement

\definelayoutelement[\v!top   ]
\definelayoutelement[\v!header]
\definelayoutelement[\v!text  ]
\definelayoutelement[\v!footer]
\definelayoutelement[\v!bottom]

\definelayoutelement[\v!top   :\v!text]  [\v!top   ][\c!lefttext=,\c!middletext=,\c!righttext=]
\definelayoutelement[\v!header:\v!text]  [\v!header][\c!lefttext=,\c!middletext=,\c!righttext=]
\definelayoutelement[\v!text  :\v!text]  [\v!text  ][\c!lefttext=,\c!middletext=,\c!righttext=]
\definelayoutelement[\v!footer:\v!text]  [\v!footer][\c!lefttext=,\c!middletext=,\c!righttext=]
\definelayoutelement[\v!bottom:\v!text]  [\v!bottom][\c!lefttext=,\c!middletext=,\c!righttext=]

\definelayoutelement[\v!top   :\v!margin][\v!top   ][\c!lefttext=,\c!middletext=,\c!righttext=]
\definelayoutelement[\v!header:\v!margin][\v!header][\c!lefttext=,\c!middletext=,\c!righttext=]
\definelayoutelement[\v!text  :\v!margin][\v!text  ][\c!lefttext=,\c!middletext=,\c!righttext=]
\definelayoutelement[\v!footer:\v!margin][\v!footer][\c!lefttext=,\c!middletext=,\c!righttext=]
\definelayoutelement[\v!bottom:\v!margin][\v!bottom][\c!lefttext=,\c!middletext=,\c!righttext=]

\definelayoutelement[\v!top   :\v!edge]  [\v!top   ][\c!lefttext=,\c!middletext=,\c!righttext=]
\definelayoutelement[\v!header:\v!edge]  [\v!header][\c!lefttext=,\c!middletext=,\c!righttext=]
\definelayoutelement[\v!text  :\v!edge]  [\v!text  ][\c!lefttext=,\c!middletext=,\c!righttext=]
\definelayoutelement[\v!footer:\v!edge]  [\v!footer][\c!lefttext=,\c!middletext=,\c!righttext=]
\definelayoutelement[\v!bottom:\v!edge]  [\v!bottom][\c!lefttext=,\c!middletext=,\c!righttext=]

\permanent\tolerant\protected\def\setuplayouttext[#S#vertical]#spacer[#S#horizontal]#spacer[#S#settings]%
  {\ifnum\lastarguments>\plustwo
     \setuplayoutelement[#vertical:#horizontal][#settings]%
   \else
     \setuplayoutelement[#vertical][#horizontal]%
   \fi}

\appendtoks
    \ifempty\currentlayoutelement\else
        \page_layouts_synchronize_element\currentlayoutelement % brr, can be vertical:horizontal
    \fi
\to \everysetuplayoutelement

\mutable\lettonothing\currenttextstate
\mutable\lettonothing\previoustextstate

\def\page_layouts_synchronize_element#vertical%
  {\xdef\previoustextstate{\csname\??layouttextssynchronize#vertical\endcsname}% can be a let
   \cdef\currenttextstate {\namedlayoutelementparameter{#vertical}\c!state}%
  %\writestatus{>>}{[#vertical:\currenttextstate/\previoustextstate]}%
   \ifx\currenttextstate\previoustextstate \else
     \page_layouts_synchronize_element_indeed{#vertical}%
   \fi}

\def\page_layouts_synchronize_element_indeed#vertical%
  {\ifx\currenttextstate \v!high \calculatevsizes\page_backgrounds_recalculate \orelse
   \ifx\previoustextstate\v!high \calculatevsizes\page_backgrounds_recalculate \orelse
   \ifx\currenttextstate \v!none \calculatevsizes\page_backgrounds_recalculate \orelse
   \ifx\previoustextstate\v!none \calculatevsizes\page_backgrounds_recalculate \fi
   \gletcsname\??layouttextssynchronize#vertical\endcsname\currenttextstate}

\permanent\protected\def\setuptop   {\setuplayouttext[\v!top   ]}
\permanent\protected\def\setupheader{\setuplayouttext[\v!header]}
\permanent\protected\def\setuptext  {\setuplayouttext[\v!text  ]}
\permanent\protected\def\setupfooter{\setuplayouttext[\v!footer]}
\permanent\protected\def\setupbottom{\setuplayouttext[\v!bottom]}

%D We inherit some settings:

\setuplayoutelement
  [  \c!leftstyle=\layoutelementparameter\c!style,
   \c!middlestyle=\layoutelementparameter\c!style,
    \c!rightstyle=\layoutelementparameter\c!style,
     \c!leftcolor=\layoutelementparameter\c!color,
   \c!middlecolor=\layoutelementparameter\c!color,
    \c!rightcolor=\layoutelementparameter\c!color,
     \c!leftwidth=\layoutelementparameter\c!width,
   \c!middlewidth=\layoutelementparameter\c!width,
    \c!rightwidth=\layoutelementparameter\c!width]

%D \macros
%D  {noheaderandfooterlines,notopandbottomlines}
%D
%D Although not really needed, the following shortcuts sometimes come in handy.
%D
%D \showsetup{noheaderandfooterlines}
%D \showsetup{notopandbottomlines}

\permanent\protected\def\noheaderandfooterlines
  {\setuplayoutelement[\v!header][\c!state=\v!empty]%
   \setuplayoutelement[\v!footer][\c!state=\v!empty]}

\permanent\protected\def\notopandbottomlines
  {\setuplayoutelement[\v!top   ][\c!state=\v!empty]%
   \setuplayoutelement[\v!bottom][\c!state=\v!empty]}

%D \macros
%D  {setuptoptexts,setupheadertexts,setuptexttexts,setupfootertexts,setupbottomtexts}
%D
%D The next macros take one or more arguments. The exact setup depends on the number
%D of arguments. Although not that intuitive, the current scheme evolved out of the
%D original. When margin and edge texts as well as middle texts showed up, the
%D current odd|/|even scheme surfaced.
%D
%D \showsetup{setuptoptexts}
%D \showsetup{setupheadertexts}
%D \showsetup{setuptexttexts}
%D \showsetup{setupfootertexts}
%D \showsetup{setupbottomtexts}
%D
%D Only the following have checking for pagenumber, date and mark built in, so when
%D someone uses the key|/|value interface these things have to be set explicitly as
%D part of the text.

\permanent\protected\def\setuptoptexts   {\setuptexts[\v!top   ]}
\permanent\protected\def\setupheadertexts{\setuptexts[\v!header]}
\permanent\protected\def\setuptexttexts  {\setuptexts[\v!text  ]}
\permanent\protected\def\setupfootertexts{\setuptexts[\v!footer]}
\permanent\protected\def\setupbottomtexts{\setuptexts[\v!bottom]}

\mutable\lettonothing\currentlayoutelementstate

\permanent\tolerant\protected\def\setuptexts[#S#vertical]#spacer[#S#horizontal]#spacer[#S#a]#spacer[#S#b]#spacer[#S#c]#spacer[#S#d]%
  {\ifarguments
     % there is always one
   \or
     \cdef\currentlayoutelement{#vertical:\v!text}%
     \resetlayoutelementparameter\c!lefttext
     \resetlayoutelementparameter\c!righttext
     \resetlayoutelementparameter\c!middletext
     \cdef\currentlayoutelement{#vertical:\v!margin}%
     \resetlayoutelementparameter\c!lefttext
     \resetlayoutelementparameter\c!righttext
     \resetlayoutelementparameter\c!middletext
     \cdef\currentlayoutelement{#vertical:\v!edge}%
     \resetlayoutelementparameter\c!lefttext
     \resetlayoutelementparameter\c!righttext
     \resetlayoutelementparameter\c!middletext
   \or
     \cdef\currentlayoutelement{#vertical:\v!text}%
     \resetlayoutelementparameter\c!lefttext
     \resetlayoutelementparameter\c!righttext
     \setlayoutelementparameter  \c!middletext{\page_layouts_process_element_single{#horizontal}}%
   \or
     \cdef\currentlayoutelement{#vertical:\v!text}%
     \setlayoutelementparameter\c!lefttext {\page_layouts_process_element_single{#horizontal}}%
     \setlayoutelementparameter\c!righttext{\page_layouts_process_element_single{#a}}%
   \or
     \cdef\currentlayoutelement{#vertical:#horizontal}%
     \setlayoutelementparameter\c!lefttext {\page_layouts_process_element_single{#a}}%
     \setlayoutelementparameter\c!righttext{\page_layouts_process_element_single{#b}}%
   \or
     \cdef\currentlayoutelement{#vertical:\v!text}%
     \setlayoutelementparameter\c!lefttext {\page_layouts_process_element_double{#horizontal}{#c}}%
     \setlayoutelementparameter\c!righttext{\page_layouts_process_element_double{#a}{#b}}%
   \or
     \cdef\currentlayoutelement{#vertical:#horizontal}%
     \setlayoutelementparameter\c!lefttext {\page_layouts_process_element_double{#a}{#d}}%
     \setlayoutelementparameter\c!righttext{\page_layouts_process_element_double{#b}{#c}}%
   \fi}

%D Left and right texts are swapped on odd and even pages, but only when double
%D sided typesetting is enabled.

\defcsname\??layouttextstrut\v!yes\endcsname{\setstrut\strut} % maybe more variants

\lettonothing\m_page_layouts_element_content

\protected\def\page_layouts_process_element_single#content%
  {\edef\m_page_layouts_element_content{\detokenize{#content}}% so no \v!xxx
   \ifcsname\??layouttextspecial\m_page_layouts_element_content\endcsname
     \lastnamedcs
   \else
     \doifelsemarking\m_page_layouts_element_content
       {\getmarking[\m_page_layouts_element_content][\v!first]}%
       {#content}%
   \fi}

\protected\def\page_layouts_process_element_double#first#second%
  {\doifelseoddpage
     {\page_layouts_process_element_single{#first}}
     {\page_layouts_process_element_single{#second}}}

% \protected\def\page_layouts_process_element_indeed#style#color#width%
%   {\begingroup
%    \lefttoright % new
%    \uselayoutelementstyleandcolor#style#color%
%    \begincsname\??layouttextstrut\layoutelementparameter\c!strut\endcsname
%    \ignorecrlf
%    \edef\p_width{\layoutelementparameter#width}%
%    \ifempty\p_width\else
%      \expandafter\page_layouts_process_element_limited
%    \fi\p_text
%    \endgroup}

\protected\def\page_layouts_process_element_indeed#style#color#width%
  {\begingroup
   \ifcstok{\layoutelementparameter\c!state}\v!empty
     \page_layouts_reset_element_status_current
 % \orelse\ifcstok{\layoutelementparameter\c!state}\v!stop
   \orelse\iflastnamedcs\v!stop
     %
   \else
     \lefttoright % new
     \uselayoutelementstyleandcolor#style#color%
     \begincsname\??layouttextstrut\layoutelementparameter\c!strut\endcsname
     \ignorecrlf
     \edef\p_width{\layoutelementparameter#width}%
     \ifempty\p_width\else
       \expandafter\page_layouts_process_element_limited
     \fi
     \p_text
   \fi
   \endgroup}

\def\page_layouts_process_element_limited#content% are the {}{}{} still needed?
  {\limitated
      left     \p_width
      text     {#content}%
      sentinel {\unknown}%
   \relax}

\defcsname\??layouttextspecial\v!pagenumber\endcsname{\page_layouts_place_page_number}
\defcsname\??layouttextspecial\v!date      \endcsname{\currentdate}

%D When specified, the texts are automatically limited in length.

\appendtoks \page_layouts_place_text_line\v!top   \topheight    \to \toptextcontent
\appendtoks \page_layouts_place_text_line\v!header\headerheight \to \headertextcontent
\appendtoks \page_layouts_place_text_line\v!text  \textheight   \to \texttextcontent
\appendtoks \page_layouts_place_text_line\v!footer\footerheight \to \footertextcontent
\appendtoks \page_layouts_place_text_line\v!bottom\bottomheight \to \bottomtextcontent

%D Texts can be disabled, moved up and ignored, depending in the \type {status}
%D variable. This is handled by the next couple of macros.

\newinteger\c_page_layouts_element_state_n

\mutable\lettonothing\textlinestatus

\def\page_layouts_set_element_status#vertical%
  {\c_page_layouts_element_state_n=0\namedlayoutelementparameter#vertical\c!n\relax
   \ifcase\c_page_layouts_element_state_n
     \edef\textlinestatus{\namedlayoutelementparameter#vertical\c!state}%
   \else
     \xdefcsname\namedlayoutelementhash#vertical\c!n\endcsname{\tointeger{\c_page_layouts_element_state_n+\minusone}}%
     \let\textlinestatus\v!stop
   \fi}

\appendtoks
   \ifinset\v!header\floatspecification\xdefcsname\namedlayoutelementhash\v!header\c!n\endcsname{1}\fi
   \ifinset\v!footer\floatspecification\xdefcsname\namedlayoutelementhash\v!footer\c!n\endcsname{1}\fi
\to \everybeforeflushedpagefloat

\protected\def\page_layouts_place_text_line#vertical%
  {\page_layouts_set_element_status#vertical\relax
   \ifcsname\??layouttextsline\textlinestatus\endcsname
     \expandafter\lastnamedcs
   \else
     \expandafter\page_layouts_place_text_line_unknown
   \fi#vertical}

\permanent\protected\def\doifelselayouttextline#vertical% shown or not
  {\cdef\currentlayoutelementstate{\namedlayoutelementparameter{#vertical}\c!state}%
   \ifx\currentlayoutelementstate\v!normal
     \expandafter\firstoftwoarguments
   \orelse\ifx\currentlayoutelementstate\v!start
     \expandafter\firstoftwoarguments
   \else
     \expandafter\secondoftwoarguments
   \fi}

\permanent\protected\def\doifelselayoutsomeline#vertical% present or not
  {\cdef\currentlayoutelementstate{\namedlayoutelementparameter{#vertical}\c!state}%
   \ifx\currentlayoutelementstate\v!none
     \expandafter\secondoftwoarguments
   \orelse\ifx\currentlayoutelementstate\v!high
     \expandafter\secondoftwoarguments
   \else
     \expandafter\firstoftwoarguments
   \fi}

\aliased\let\doiflayouttextlineelse\doifelselayouttextline
\aliased\let\doiflayoutsomelineelse\doifelselayoutsomeline

\newconditional\resyncaftertextline

\defcsname\??layouttextsline\v!normal\endcsname{\page_layouts_place_text_line_indeed}
\defcsname\??layouttextsline\empty   \endcsname{\page_layouts_place_text_line_indeed}

\letcsname\??layouttextsline\v!none\endcsname\gobbletwoarguments
\letcsname\??layouttextsline\v!stop\endcsname\gobbletwoarguments

\defcsname\??layouttextsline\v!high\endcsname#vertical#height%
  {\global\resyncaftertextline\conditionaltrue
   \page_layouts_reset_element_status#vertical}

\defcsname\??layouttextsline\v!empty\endcsname#vertical#height%
  {\page_layouts_reset_element_status#vertical}

\defcsname\??layouttextsline\v!start\endcsname#vertical#height%
  {\page_layouts_reset_element_status#vertical%
   \page_layouts_place_text_line_indeed#vertical#height}

\defcsname\??layouttextsline\v!nomarking\endcsname#vertical#height%
  {\bgroup
   \page_layouts_reset_element_status#vertical%
   \inhibitgetmarking\conditionaltrue
   \page_layouts_place_text_line_indeed#vertical#height%
   \egroup}

% \setupheadertexts            [11]
% \definetext [title] [header] [aa]
% \setupheadertexts            [11] [22]
% \definetext [title] [header] [aa] [bb]
% \setupheadertexts            [text] [11] [22]
% \definetext [title] [header] [text] [aa] [bb]
% \setupheadertexts            [11] [22] [33] [44]
% \definetext [title] [header] [aa] [bb] [cc] [dd]
% \setupheadertexts            [text] [11] [22] [33] [44]
% \definetext [title] [header] [text] [aa] [bb] [cc] [dd]

\def\page_layouts_place_text_line_unknown#vertical#height%
  {\global\resyncaftertextline\conditionaltrue
   \begingroup % new
   \page_layouts_reset_element_status#vertical%
   \begincsname\namedlayoutelementhash{#vertical}\textlinestatus\endcsname
   \begincsname\namedlayoutelementhash{#vertical:\v!text}\textlinestatus\endcsname
   \begincsname\namedlayoutelementhash{#vertical:\v!margin}\textlinestatus\endcsname
   \begincsname\namedlayoutelementhash{#vertical:\v!edge}\textlinestatus\endcsname
   \page_layouts_place_text_line_indeed#vertical#height%
   \endgroup}

\letcsname\??layouttextsline\s!unknown\endcsname\page_layouts_place_text_line_unknown

%D The following macro has to be called after a page is flushed.

% \permanent\protected\def\resetlayouttextlines % public
%   {\begincsname\??layouttextsreset\v!top   \endcsname
%    \begincsname\??layouttextsreset\v!header\endcsname
%    \begincsname\??layouttextsreset\v!text  \endcsname
%    \begincsname\??layouttextsreset\v!footer\endcsname
%    \begincsname\??layouttextsreset\v!bottom\endcsname
%    \ifconditional\resyncaftertextline
%      \calculateglobalvsizes
%      \page_backgrounds_recalculate
%      \global\resyncaftertextline\conditionalfalse
%    \fi}
%
% \def\page_layouts_reset_element_status#vertical%
%   {\gdefcsname\??layouttextsreset#vertical\endcsname{\page_layouts_set_element_status_normal#vertical}}
%
% \def\page_layouts_set_element_status_normal#vertical%
%   {\gletcsname\namedlayoutelementhash#vertical\c!state\endcsname\v!normal
%    \gletcsname\??layouttextsreset#vertical\endcsname\relax
%    \page_layouts_synchronize_element{#vertical}}

\newtoks\t_page_layouts_texts

\def\page_layouts_reset_element_status#vertical%
  {\xtoksapp\t_page_layouts_texts{\page_layouts_set_element_status_normal{#vertical}}}

\def\page_layouts_reset_element_status_current
  {\xtoksapp\t_page_layouts_texts{\page_layouts_set_element_status_current{\currentlayoutelement}}}

\protected\def\page_layouts_set_element_status_normal#vertical%
  {\gletcsname\namedlayoutelementhash{#vertical}\c!state\endcsname\v!normal
   \page_layouts_synchronize_element{#vertical}}

\protected\def\page_layouts_set_element_status_current#current%
  {\gletcsname\namedlayoutelementhash{#current}\c!state\endcsname\v!normal}

\permanent\protected\def\resetlayouttextlines % public
  {\ifempty\t_page_layouts_texts
   \else
     \expand\t_page_layouts_texts
     \global\t_page_layouts_texts\emptytoks
   \fi
   \ifconditional\resyncaftertextline
     \calculateglobalvsizes
     \page_backgrounds_recalculate
     \global\resyncaftertextline\conditionalfalse
   \fi}

\permanent\def\getspecificlayouttext#vertical#horizontal#what%
  {\begincsname\namedlayoutelementhash{#vertical:#horizontal}#what\endcsname}

% \settext[header][text][middle][xxx][yyy]

\permanent\tolerant\protected\def\settextcontent[#S#vertical]#spacer[#S#horizontal]#spacer[#S#one]#spacer[#S#two]#spacer[#S#three]% header text middle text/text
  {\ifarguments\or\or\or % 3
     \defcsname\namedlayoutelementhash{#vertical:#horizontal}\c!middletext\endcsname
       {\page_layouts_process_element_double{#one}{#one}}%
   \or % 4
     \defcsname\namedlayoutelementhash{#vertical:#horizontal}\begincsname\??layouttextcontent\v!text:#one\endcsname\c!middletext\endcsname
       {\page_layouts_process_element_double{#two}{#two}}%
   \or % 5
     \defcsname\namedlayoutelementhash{#vertical:#horizontal}\begincsname\??layouttextcontent\v!text:#one\endcsname\c!middletext\endcsname
       {\page_layouts_process_element_double{#two}{#three}}%
   \fi}

\let\currentlayoutelement\relax

%D This will be redefined, so no \type {\frozen} here!

\permanent\tolerant\protected\def\resettextcontent[#S#vertical]#spacer[#S#horizontal]#spacer[#S#tag]% header text middle
  {\ifarguments\or\or % 2
     \cdef\currentlayoutelement{#vertical:#horizontal}%
     \resetlayoutelementparameter\c!lefttext
     \resetlayoutelementparameter\c!middletext
     \resetlayoutelementparameter\c!righttext
   \or % 3
%      \cdef\currentlayoutelement{#vertical:#horizontal}%
%      \letcsname\layoutelementhash\begincsname\??layouttextcontent\v!text:#tag\endcsname\c!middletext\endcsname\empty
     \letcsname\namedlayoutelementhash{#vertical:#horizontal}\begincsname\??layouttextcontent\v!text:#tag\endcsname\c!middletext\endcsname\empty
   \fi}

\letcsname\??layouttextcontent\v!text:\c!middle\endcsname\c!middletext
\letcsname\??layouttextcontent\v!text:\c!left  \endcsname\c!lefttext
\letcsname\??layouttextcontent\v!text:\c!right \endcsname\c!righttext

%D The placement of a whole line is handled by the next two macros. These are hooked
%D into the general purpose token list registers mentioned before.

\mutable\let\currentlayouttextline\relax

\def\page_layouts_place_text_line_indeed#vertical#height%
  {\let\currentlayouttextline#vertical%
   \ifdim#height>\zeropoint\relax  % prevents pagenumbers when zero height
     \page_layouts_place_text_line_left_or_right{#height}%
   \fi}

\def\page_layouts_place_text_line_left_or_right#height%
  {\goleftonpage
   \setbox\b_page_layouts_element\vbox to #height
     {\vsize#height\relax
     %\hsize\zeropoint % hack so that e.g. after=\hairline gives predictable results
      \hsize\totaltextwidth
      \normalbaselines
      \enforced\let\\\ignoredlinebreak
      \enforced\let\crlf\ignoredlinebreak
      \namedlayoutelementparameter\currentlayouttextline\c!before
      \doifbothsidesoverruled
        \page_layouts_place_text_line_right
        \page_layouts_place_text_line_right
        \page_layouts_place_text_line_left
      \namedlayoutelementparameter\currentlayouttextline\c!after
      \vkern\zeropoint}% keep the \dp, beware of \vtops, never change this!
   \dp\b_page_layouts_element\zeropoint
   \box\b_page_layouts_element
   \vkern-#height\relax}

\lettonothing\page_layouts_place_extra_text_left  % historic
\lettonothing\page_layouts_place_extra_text_right % historic

\def\page_layouts_place_text_line_right
  {\hpack
     {\ifdim\leftedgewidth>\zeropoint
        \page_layouts_left_edge_element\c!lefttext\c!leftstyle\c!leftcolor\c!leftwidth
      \fi
      \ifdim\leftmarginwidth>\zeropoint
        \page_layouts_left_margin_element\c!lefttext\c!leftstyle\c!leftcolor\c!leftwidth\zerocount
      \fi
      \ifdim\makeupwidth>\zeropoint
        \page_layouts_text_body_element_l_m_r_e
      \fi
      \ifdim\rightmarginwidth>\zeropoint
        \page_layouts_right_margin_element\c!righttext\c!rightstyle\c!rightcolor\c!rightwidth\plusone
      \fi
      \ifdim\rightedgewidth>\zeropoint
        \page_layouts_right_edge_element\c!righttext\c!rightstyle\c!rightcolor\c!rightwidth
      \fi}}

\def\page_layouts_place_text_line_left
  {\hpack
     {\ifdim\leftedgewidth>\zeropoint
        \page_layouts_left_edge_element\c!righttext\c!rightstyle\c!rightcolor\c!rightwidth
      \fi
      \ifdim\leftmarginwidth>\zeropoint
        \page_layouts_left_margin_element\c!righttext\c!rightstyle\c!rightcolor\c!rightwidth\plusone
      \fi
      \ifdim\makeupwidth>\zeropoint
        \page_layouts_text_body_element_e_r_m_l
      \fi
      \ifdim\rightmarginwidth>\zeropoint
        \page_layouts_right_margin_element\c!lefttext\c!leftstyle\c!leftcolor\c!leftwidth\zerocount
      \fi
      \ifdim\rightedgewidth>\zeropoint
        \page_layouts_right_edge_element\c!lefttext\c!leftstyle\c!leftcolor\c!leftwidth
      \fi}}

\def\page_layouts_left_edge_element_indeed#text#style#color#width%
  {\letfromlayoutelementparameter\p_text#text%
   \ifempty\p_text
     \kern\leftedgewidth
   \else
     \hbox to \leftedgewidth\bgroup
       \hss
       \page_layouts_process_element_indeed#style#color#width%
     \egroup
   \fi}

\def\page_layouts_left_edge_element#text#style#color#width%
  {\cdef\currentlayoutelement{\currentlayouttextline:\v!edge}%
   \page_layouts_place_element_indeed\leftedgewidth
     {\page_layouts_left_edge_element_indeed#text#style#color#width}%
   \kern\leftedgedistance}

\def\page_layouts_right_edge_element_indeed#text#style#color#width%
  {\letfromlayoutelementparameter\p_text#text%
   \ifempty\p_text
     \kern\rightedgewidth
   \else
      \hbox to \rightedgewidth\bgroup
        \page_layouts_process_element_indeed#style#color#width%
        \hss
      \egroup
   \fi}

\def\page_layouts_right_edge_element#text#style#color#width%
  {\cdef\currentlayoutelement{\currentlayouttextline:\v!edge}%
   \kern\rightedgedistance
   \page_layouts_place_element_indeed\rightedgewidth
     {\page_layouts_right_edge_element_indeed#text#style#color#width}}

% margin needs checking!

% \hbox to \leftmarginwidth{\hss\layoutelementparameter\c!margintext}%
% \hbox to \rightmarginwidth{\layoutelementparameter\c!margintext\hss}%

\def\page_layouts_left_margin_element_indeed#text#style#color#width#margintoo%
  {\letfromlayoutelementparameter\p_text#text%
   \ifempty\p_text
     \kern\leftmarginwidth
   \else
     \hbox to \leftmarginwidth\bgroup
       \hss
       \page_layouts_process_element_indeed#style#color#width%
     \egroup
   \fi
   \ifcase#margintoo\or
     \letfromlayoutelementparameter\p_text\c!margintext
     \ifempty\p_text\else
       \kern-\leftmarginwidth
       \hbox to \leftmarginwidth\bgroup
         \hss
         \p_text % styling ?
       \egroup
     \fi
   \fi}

\def\page_layouts_left_margin_element#text#style#color#width#margintoo%
  {\cdef\currentlayoutelement{\currentlayouttextline:\v!margin}%
   \page_layouts_place_element_indeed\leftmarginwidth
     {\page_layouts_left_margin_element_indeed#text#style#color#width#margintoo}%
   \kern\leftmargindistance}

\def\page_layouts_right_margin_element_indeed#text#style#color#width#margintoo%
  {\letfromlayoutelementparameter\p_text#text%
   \ifempty\p_text
     \kern\rightmarginwidth
   \else
     \hbox to \rightmarginwidth\bgroup
       \page_layouts_process_element_indeed#style#color#width%
       \hss
     \egroup
   \fi
   \ifcase#margintoo\or
     \letfromlayoutelementparameter\p_text\c!margintext
     \ifempty\p_text\else
       \kern-\rightmarginwidth
       \hbox to \rightmarginwidth\bgroup
         \p_text % ? styling
         \hss
       \egroup
     \fi
   \fi}

\def\page_layouts_right_margin_element#text#style#color#width#margintoo%
  {\cdef\currentlayoutelement{\currentlayouttextline:\v!margin}%
   \kern\rightmargindistance
   \page_layouts_place_element_indeed\rightmarginwidth
     {\page_layouts_right_margin_element_indeed#text#style#color#width#margintoo}}

\def\page_layouts_text_body_element_indeed_l_m_r_e
  {\letfromlayoutelementparameter\p_text\c!lefttext
   \ifempty\p_text
     \ifempty\page_layouts_place_extra_text_left\else
       \hbox to \makeupwidth\bgroup
         \page_layouts_place_extra_text_left
         \hss
       \egroup
       \kern-\makeupwidth
     \fi
   \else
     \hbox to \makeupwidth\bgroup
       \page_layouts_place_extra_text_left
       \page_layouts_process_element_indeed\c!leftstyle\c!leftcolor\c!leftwidth
       \hss
     \egroup
     \kern-\makeupwidth
   \fi
   \letfromlayoutelementparameter\p_text\c!middletext
   \ifempty\p_text\else
     \hbox to \makeupwidth\bgroup
       \hss
       \page_layouts_process_element_indeed\c!middlestyle\c!middlecolor\c!middlewidth
       \hss
     \egroup
     \kern-\makeupwidth
   \fi
   \letfromlayoutelementparameter\p_text\c!righttext
   \ifempty\p_text
     \kern\makeupwidth
   \else
     \hbox to \makeupwidth\bgroup
       \hss
       \page_layouts_process_element_indeed\c!rightstyle\c!rightcolor\c!rightwidth
     \egroup
   \fi}

\def\page_layouts_text_body_element_indeed_e_r_m_l
  {\letfromlayoutelementparameter\p_text\c!righttext
   \ifempty\p_text\else
     \hbox to \makeupwidth\bgroup
       \page_layouts_process_element_indeed\c!rightstyle\c!rightcolor\c!rightwidth
       \hss
     \egroup
     \kern-\makeupwidth
   \fi
   \letfromlayoutelementparameter\p_text\c!middletext
   \ifempty\p_text\else
     \hbox to \makeupwidth\bgroup
       \hss
       \page_layouts_process_element_indeed\c!middlestyle\c!middlecolor\c!middlewidth
       \hss
     \egroup
     \kern-\makeupwidth
   \fi
   \letfromlayoutelementparameter\p_text\c!lefttext
   \ifempty\p_text
     \ifempty\page_layouts_place_extra_text_right
       \kern\makeupwidth
     \else
       \hbox to \makeupwidth\bgroup
         \hss
         \page_layouts_place_extra_text_right
       \egroup
     \fi
   \else
     \hbox to \makeupwidth\bgroup
       \hss
       \page_layouts_process_element_indeed\c!leftstyle\c!leftcolor\c!leftwidth
       \page_layouts_place_extra_text_right
     \egroup
   \fi}

\def\page_layouts_text_body_element_l_m_r_e
  {\cdef\currentlayoutelement{\currentlayouttextline:\v!text}%
   \page_layouts_place_element_indeed\makeupwidth\page_layouts_text_body_element_indeed_l_m_r_e}

\def\page_layouts_text_body_element_e_r_m_l
  {\cdef\currentlayoutelement{\currentlayouttextline:\v!text}%
   \page_layouts_place_element_indeed\makeupwidth\page_layouts_text_body_element_indeed_e_r_m_l}

\def\page_layouts_place_element_indeed#width#content%
  {\vbox % to \vsize
     {\hsize#width\relax
      \layoutelementparameter\c!before
      \setlayoutcomponentattribute\currentlayoutelement
      \hbox \layoutcomponentboxattribute to #width{#content}%
      \layoutelementparameter\c!after}}

%D Although it is far better to use backgrounds for this purpose, one can add a rule
%D in the following way. This method makes the rules disappear in case of an empty
%D text line. Consider this a feature.
%D
%D \starttyping
%D \setupheadertexts[left][right]
%D
%D \setupheader[text][after=\hrule,style=bold]
%D
%D \starttext
%D   \input tufte \page
%D   \setupheader[state=empty]
%D   \input tufte \page
%D \stoptext
%D \stoptyping

%D This code will move to \type {page-flt.tex}.

\appendtoks \placerightmarginblock \kern-\rightmarginwidth \to \rightmargintextcontent
\appendtoks \placeleftmarginblock  \kern-\leftmarginwidth  \to \leftmargintextcontent

%D \macros
%D   {definetext}
%D
%D Some macros ago, we implemented the \type {status} option \type {unknown}. This
%D one is used to take care of symbolic texts handlers.
%D
%D \showsetup{definetext}
%D
%D The next example demonstrates how we can use this mechanism to provide page
%D (event) dependent text lines.
%D
%D \starttyping
%D \definetext[chapter][footer][pagenumber]
%D \setuphead[chapter][header=high,footer=chapter]
%D \setupheadertexts[pagenumber]
%D \setupfootertexts[left][right]
%D \chapter{eerste} \dorecurse{20}{\input tufte \relax}
%D \chapter{tweede} \dorecurse{20}{\input tufte \relax}
%D \stoptyping

\permanent\tolerant\protected\def\definetext[#S#tag]#spacer[#S#vertical]#spacer[#S#horizontal]#spacer[#S#a]#spacer[#S#b]#spacer[#S#c]#spacer[#S#d]%
  {\ifnum\lastarguments<\plusfour
     \defcsname\namedlayoutelementhash            {#vertical}#tag\endcsname{\setuptexts[#vertical][#horizontal]\relax}% 1, 2, 3
   \orelse\ifarguments\or\or\or\or
     \defcsname\namedlayoutelementhash            {#vertical}#tag\endcsname{\setuptexts[#vertical][#horizontal][#a]\relax}% 4
   \or
     \defcsname\namedlayoutelementhash{#vertical:#horizontal}#tag\endcsname{\setuptexts[#vertical][#horizontal][#a][#b]\relax}% 5
   \or
     \defcsname\namedlayoutelementhash            {#vertical}#tag\endcsname{\setuptexts[#vertical][#horizontal][#a][#b][#c]\relax}% 6
   \or
     \defcsname\namedlayoutelementhash{#vertical:#horizontal}#tag\endcsname{\setuptexts[#vertical][#horizontal][#a][#b][#c][#d]\relax}% 7
   \fi}

%D A few more page breakers:

\installpagebreakmethod \v!empty
  {\page_otr_flush_all_floats
   \page_otr_command_next_page
   \ifcstok{\namedlayoutelementparameter\v!header\c!state}\v!stop\else\setuplayoutelement[\v!header][\c!state=\v!empty]\fi
   \ifcstok{\namedlayoutelementparameter\v!footer\c!state}\v!stop\else\setuplayoutelement[\v!footer][\c!state=\v!empty]\fi
   \page_otr_insert_dummy_page}

\installpagebreakmethod \v!header
  {\ifcstok{\namedlayoutelementparameter\v!header\c!state}\v!stop\else\setuplayoutelement[\v!header][\c!state=\v!empty]\fi}

\installpagebreakmethod \v!footer
  {\ifcstok{\namedlayoutelementparameter\v!footer\c!state}\v!stop\else\setuplayoutelement[\v!footer][\c!state=\v!empty]\fi}

%D While the header and footer lines are moved away from the main text, the top and
%D bottom lines are centered.

\setuplayoutelement[\v!top   ][\c!state=\v!normal,\c!n=0,\c!before=\vss,\c!after=\vss,\c!strut=]
\setuplayoutelement[\v!header][\c!state=\v!normal,\c!n=0,\c!before=,    \c!after=\vss,\c!strut=\v!yes]
\setuplayoutelement[\v!text  ][\c!state=\v!normal,\c!n=0,\c!before=\vss,\c!after=\vss,\c!strut=]
\setuplayoutelement[\v!footer][\c!state=\v!normal,\c!n=0,\c!before=\vss,\c!after=,    \c!strut=\v!yes]
\setuplayoutelement[\v!bottom][\c!state=\v!normal,\c!n=0,\c!before=\vss,\c!after=\vss,\c!strut=]

%D Moved here from strc-pag:
%D
%D We reset a previous location but only when it has a pagenumber associated. This
%D is a rather messy test but better than the MkII way where we use states and keep
%D settings.

\let\m_page_layouts_page_number_location  \relax
\let\m_page_layouts_page_number_location_v\relax
\let\m_page_layouts_page_number_location_h\relax
\let\m_page_layouts_page_number_location_x\relax

\def\page_layouts_place_page_number   % also elsewhere .. beware, not \protected else
  {\strc_pagenumbers_place_location}  % test below fails

\def\page_layouts_reset_page_number_location
  {\ifrelax\m_page_layouts_page_number_location_v\else
     % this can be done better now, no meaning hackery needed
     \cdef\currentlayoutelement{\m_page_layouts_page_number_location_v:\m_page_layouts_page_number_location_h}%
     \edef\tempstring{\detokenizedlayoutelementparameter\m_page_layouts_page_number_location_x}%
     \iftok{\normalmeaningless\tempstring}{\normalmeaningless\page_layouts_place_page_number}%
       \resetlayoutelementparameter\m_page_layouts_page_number_location_x
     \fi
   \fi}

\def\page_layouts_set_page_number_location
  {\cdef\currentlayoutelement{\m_page_layouts_page_number_location_v:\m_page_layouts_page_number_location_h}%
   \letlayoutelementparameter\m_page_layouts_page_number_location_x\page_layouts_place_page_number
   \ifx\m_page_layouts_page_number_location_x\c!marginedgetext
     \let\page_layouts_place_extra_text_left \page_layouts_place_page_number_left
     \let\page_layouts_place_extra_text_right\page_layouts_place_page_number_right
   \else
     \lettonothing\page_layouts_place_extra_text_left
     \lettonothing\page_layouts_place_extra_text_right
   \fi}

\def\page_layouts_identify_page_number_location
  {\let\m_page_layouts_page_number_location_v\v!footer
   \let\m_page_layouts_page_number_location_h\v!text
   \let\m_page_layouts_page_number_location_x\c!middletext
   \processallactionsinset[\directpagenumberingparameter\c!location]%
     [    \v!header=>\let\m_page_layouts_page_number_location_v\v!header,%
          \v!footer=>\let\m_page_layouts_page_number_location_v\v!footer,%
          \v!middle=>\let\m_page_layouts_page_number_location_h\v!text
                     \let\m_page_layouts_page_number_location_x\c!middletext,%
            \v!left=>\let\m_page_layouts_page_number_location_h\v!text
                     \let\m_page_layouts_page_number_location_x\c!lefttext,%
           \v!right=>\let\m_page_layouts_page_number_location_h\v!text
                     \let\m_page_layouts_page_number_location_x\c!righttext,%
          \v!inleft=>\let\m_page_layouts_page_number_location_h\v!margin
                     \let\m_page_layouts_page_number_location_x\c!lefttext,%
         \v!inright=>\let\m_page_layouts_page_number_location_h\v!margin
                     \let\m_page_layouts_page_number_location_x\c!righttext,%
        \v!inmargin=>\let\m_page_layouts_page_number_location_h\v!margin
                     \def\m_page_layouts_page_number_location_x{\ifdoublesided\c!margintext\else\c!righttext\fi},%
          \v!margin=>\let\m_page_layouts_page_number_location_h\v!margin
                     \def\m_page_layouts_page_number_location_x{\ifdoublesided\c!margintext\else\c!righttext\fi},%
        \v!atmargin=>\let\m_page_layouts_page_number_location_h\v!text
                     \let\m_page_layouts_page_number_location_x\c!marginedgetext,%
      \v!marginedge=>\let\m_page_layouts_page_number_location_h\v!text
                     \let\m_page_layouts_page_number_location_x\c!marginedgetext]}

\lettonothing\p_strc_pagenumbers_page
\lettonothing\p_strc_pagenumbers_location

\protected\def\strc_pagenumbers_set_location
  {\edef\p_strc_pagenumbers_location{\directpagenumberingparameter\c!location}%
   \ifx\p_strc_pagenumbers_location\m_page_layouts_page_number_location
      % unchanged
   \else
     \let\m_page_layouts_page_number_location\p_strc_pagenumbers_location
     \page_layouts_reset_page_number_location
     \ifempty\p_strc_pagenumbers_location
       % set otherwise
     \orelse\ifx\p_strc_pagenumbers_location\v!none
       % set otherwise
     \else
       \page_layouts_identify_page_number_location
       \page_layouts_set_page_number_location
     \fi
   \fi}

\def\page_layouts_place_page_number_left % historic
  {\begingroup
   \setbox\scratchbox\hbox{\ignorespaces\layoutelementparameter\c!marginedgetext\removeunwantedspaces}%
   \ifzeropt\wd\scratchbox
     % nothing
   \orelse\ifchkdimexpr\directpagenumberingparameter\c!width\or
     \hpack to \lastchkdimension{\box\scratchbox\hss}%
   \else
     \box\scratchbox\tfskip
   \fi
   \endgroup}

\def\page_layouts_place_page_number_right % historic
  {\begingroup
   \setbox\scratchbox\hbox{\ignorespaces\layoutelementparameter\c!marginedgetext\removeunwantedspaces}%
   \ifzeropt\wd\scratchbox
     % nothing
   \orelse\ifchkdimexpr\directpagenumberingparameter\c!width\or
     \hpack to \lastchkdimension{\hss\box\scratchbox}%
   \else
     \tfskip\box\scratchbox
   \fi
   \endgroup}

\strc_pagenumbers_set_location % initializes

\newbox\b_page_layouts_element

\def\page_layouts_insert_elements
  {\ifexporting
     % forget about it
   \orelse\ifcase\pageornamentstate
     \page_layouts_place_elements_indeed % we could have a special flag for always ignored
   \fi}

\def\page_layouts_place_elements_indeed
  {\setbox\b_page_layouts_element\vpack
     {\dontcomplain
      \calculatereducedvsizes
      \page_layouts_swap_margins\v!text
      \offinterlineskip
      \vkern{-\topheight-\topdistance}%
      \the\toptextcontent
      \vkern{\topheight+\topdistance}%
      \the\headertextcontent
      \vkern{\headerheight+\headerdistance+\textdistance}%
      \anch_positions_place_anchors
      \vkern{-\textdistance-\textheight}%
      \the\texttextcontent
      \vkern\textheight
      \expand\everyendoftextbody
      \vkern\footerdistance
      \the\footertextcontent
      \vkern{\footerheight+\bottomdistance}%
      \the\bottomtextcontent
      \vkern\bottomheight
      \vfilll}%
  \smashbox\b_page_layouts_element
  \box\b_page_layouts_element}

% only for very special controlled cases or experiments:

\newinteger    \c_page_scale_lines
\newdimension  \d_page_box_stretch_delta
\newdimension  \d_page_box_stretch_criterium
\newconditional\c_page_box_check_stretch

% The stretch setting can depend on the current lineheight and the
% alignment can be set later. So we need to delay.

\def\page_box_check_limit_stretch_indeed#1%
  {\edef\p_limitstretch{\layoutparameter\c!limitstretch}%
   \ifx\p_limitstretch\v!yes
     \d_page_box_stretch_criterium\zeropoint
     \c_page_box_check_stretch\conditionaltrue
   \orelse\ifx\p_limitstretch\v!auto
     % safeguard for depth without limit set
     \ifnum\bottomraggednessmode=\plusthree
       \d_page_box_stretch_criterium2\lineheight % 2 is hardcoded
       \c_page_box_check_stretch\conditionaltrue
     \else
       \d_page_box_stretch_criterium\maxdimen
       \c_page_box_check_stretch\conditionalfalse
     \fi
   \orelse\ifchkdimension\p_limitstretch\or
     \d_page_box_stretch_criterium\p_limitstretch\relax
     \c_page_box_check_stretch\conditionaltrue
   \else
     \d_page_box_stretch_criterium\maxdimen
     \c_page_box_check_stretch\conditionalfalse
   \fi
   \ifconditional\c_page_box_check_stretch
     \boxfixstretch\d_page_box_stretch_criterium#1\relax
     \d_page_box_stretch_delta\boxstretchdelta
   \fi}

\let\page_box_check_limit_stretch\relax % we test for this

\appendtoks
    \edef\p_limitstretch{\layoutparameter\c!limitstretch}%
    \ifx\p_limitstretch\v!yes
      \let\page_box_check_limit_stretch\page_box_check_limit_stretch_indeed
    \orelse\ifx\p_limitstretch\v!auto
      \let\page_box_check_limit_stretch\page_box_check_limit_stretch_indeed
    \orelse\ifchkdimension\p_limitstretch\or
      \let\page_box_check_limit_stretch\page_box_check_limit_stretch_indeed
    \else
      \let\page_box_check_limit_stretch\relax % we test for this
    \fi
\to \everysetuplayout

\def\page_layouts_check_stretch#1%
  {\ifcase\bottomraggednessmode
     \d_page_box_stretch_delta\zeropoint
   \orelse\ifrelax\page_box_check_limit_stretch
     \d_page_box_stretch_delta\zeropoint
   \else
     \page_box_check_limit_stretch{#1}%
   \fi}

\def\page_insert_body#1#2%
  {\setbox\b_page_layouts_element\vpack
     {\offinterlineskip
      \calculatereducedvsizes
      \calculatehsizes
      \page_layouts_swap_margins\v!page
      \vkern{\headerheight+\headerdistance+\textdistance}%
      \dontleavehmode
      \hpack to \makeupwidth
        {\begingroup
         % \page_layouts_swap_margins\v!page
           \goleftonpage
           \ifdim\leftedgewidth>\zeropoint
             \the\leftedgetextcontent
             \kern{\leftedgewidth+\leftedgedistance}%
           \fi
           \ifdim\leftmarginwidth>\zeropoint
             \the\leftmargintextcontent
             \kern{\leftmarginwidth+\leftmargindistance}%
           \fi
         \endgroup
         \page_apply_postprocessors_page{#2}%
         \settextpagecontent\b_page_layouts_element{#1}{#2}%
         \page_backgrounds_add_to_text\b_page_layouts_element
         \page_grids_add_to_box\b_page_layouts_element
         \box\b_page_layouts_element
         \begingroup
           \ifdim\rightmarginwidth>\zeropoint
             \kern\rightmargindistance
             \the\rightmargintextcontent
             \kern\rightmarginwidth
           \fi
           \ifdim\rightedgewidth>\zeropoint
             \kern\rightedgedistance
             \the\rightedgetextcontent
             \kern\rightedgewidth
           \fi
         \endgroup
         \hss}}%
   \smashbox\b_page_layouts_element
   \box\b_page_layouts_element}

%D Long ago (relative to 2023), when Thanh and I were discussing the \PDFTEX\ hz
%D features with Hermann Zapf, we side tracked to vertical alignment. Hermann then
%D suggested to play with vertical scaling because \quotation {No user will notice
%D it}. Some quick experiment at the moment showed that it could work indeed but we
%D left it at that (the code stayed around). It is for that reason that this now
%D present feature has the key \type {vz}, as variant on \type {hz} (a.k.a.\
%D expansion or fontadjust).

\newconditional\c_page_scale_trace_vz

\installtextracker
  {layout.vz}
  {\c_page_scale_trace_vz\conditionaltrue}
  {\c_page_scale_trace_vz\conditionalfalse}

\installcorenamespace{vzdistance}

\def\page_scale_text_box_trace
  {\writestatus{vz page \the\realpageno}{%
      %\s!goal=\the\pagegoal,
     %\s!total=\the\pagetotal,
       \s!page=\the\pagegoal,
       \s!text=\the\textheight,
     \s!height=\the\pagelastheight,
      \s!depth=\the\pagelastdepth,
    \s!stretch=\the\pagelaststretch,
     \s!shrink=\the\pagelastshrink,
       \s!fill=(\thewithoutunit\pagelastfilstretch,\thewithoutunit\pagelastfillstretch,\thewithoutunit\pagelastfilllstretch)%
   }}

\def\page_scale_text_box_register_box#1%
  {\scratchheight\boxrepack#1%
   \scratchdimen{\textheight-\scratchheight}%
   \global\expandafter\dimensiondef\csname\??vzdistance\the\mofcolumns\endcsname
     \ifabsdim\scratchdimen>\c_page_scale_lines\lineheight
       \zeropoint
     \else
       \scratchheight
     \fi
   \relax
   \ifconditional\c_page_scale_trace_vz
     \page_scale_text_box_trace
   \fi}

\def\page_scale_text_box_register_page
  {\scratchdimen{\textheight-\pagelastheight}% not \pagegoal as that includes footnotes
   \global\expandafter\dimensiondef\csname\??vzdistance\the\mofcolumns\endcsname
     \ifabsdim\scratchdimen>\c_page_scale_lines\lineheight
       \zeropoint
     \orelse\ifdim\pagelastshrink>\zeropoint % maybe also stretch
       \zeropoint
     \else
       \pagelastheight
     \fi
   \relax
   \ifconditional\c_page_scale_trace_vz
     \page_scale_text_box_trace
   \fi}

\def\page_scale_text_box
  {\scratchdistance\ifcsname\??vzdistance\the\mofcolumns\endcsname\lastnamedcs\else\zeropoint\fi
   \ifzeropt\scratchdistance
     \expandafter\gobbleoneargument
   \else
     \expandafter\page_scale_text_box_indeed
   \fi}

\def\page_scale_text_box_indeed#1%
  {\scratchdimen{\textheight-\scratchdistance}%
   \scratchheight\ht#1%
   \scratchdepth \dp#1%
   \scratchwidth \wd#1%
   \scratchfloat \floatexpr\textheight/\scratchdistance\relax
   %
   \f_anch_extra_y_scale\scratchfloat % first attempt
   %
   \setbox#1\vpack\bgroup
     \hpack\bgroup
       \expanded{\scale
        %[\c!xscale=\plusthousand,\c!yscale=\scratchcounter]
         [\c!sx=1,\c!sy=\the\scratchfloat]%
         {\box#1}}%
     \egroup
     \ifconditional\c_page_scale_trace_vz
       \nointerlineskip
       \srule
         \s!height   \scratchdimen
         \s!yoffset 2\scratchdimen
         \s!xoffset-2\emwidth
         \s!width   2\emwidth
       \hpack
         \s!yoffset \scratchdimen
         \s!xoffset-2\emwidth
       \bgroup
         \edef\tempstring{\semiexpand\formatone{@0.3f}{\the\scratchfloat}}%
         \writestatus{vz page \the\realpageno}{scaling \tempstring\space applied}%
         \llap{\infofont\tempstring}%
       \egroup
     \fi
   \egroup
   \ht#1\scratchheight
   \dp#1\scratchdepth
   \wd#1\scratchwidth}

\appendtoks
    \edef\p_lines{\layoutparameter\c!vz}%
    \ifx\p_lines\v!yes
        \c_page_scale_lines\plusone
    \orelse\ifchknumber\p_lines\or
        \c_page_scale_lines\lastchknumber
    \else
        \c_page_scale_lines\zerocount
    \fi
\to \everysetuplayout

%D The main text area has to be combined with some additional (tracing) information.
%D
%D This will be stored as normal and overloaded in page-lyr and later in page-spr we
%D overload the the stored version .. eventually i will clear up the experimental
%D mess.

\ifdefined\page_otr_flush_top_content\else \let\page_otr_flush_top_content\relax \fi

\protected\def\settextpagecontent#1#2#3% #2 and #3 will disappear / is overloaded
  {\setbox#1\hpack to \makeupwidth
     {\hss                     % so don't change this
      \setlayoutcomponentattribute{\v!page:\v!text}%
      \vpack \layoutcomponentboxattribute to \textheight
        {\offinterlineskip
         \freezetextwidth
         \hsize\textwidth      % local variant of \sethsize  <<< in columns?
         \boxmaxdepth\maxdepth
         \page_otr_flush_top_content
         \noindent             % content can be < \hsize
         \page_otr_command_package_contents#2#3}% this will vbox
      \hss}%
   \dp#1\zeropoint}

\protect \endinput