% 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,
%D   setupfooter, setupbottom}
%D
%D The macros in this module sometimes look a bit more complicated
%D than needed, which is a direct result of the fact that their
%D ancestors are quite old and 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=]

\unexpanded\def\setuplayouttext
  {\dotripleempty\page_layouts_setup_text}

\def\page_layouts_setup_text[#vertical][#horizontal][#settings]%
  {\ifthirdargument
     \setuplayoutelement[#vertical:#horizontal][#settings]%
   \else
     \setuplayoutelement[#vertical][#horizontal]%
   \fi}

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

\def\page_layouts_reset_element_status#vertical%
  {\expandafter\normalgdef\csname\??layouttextsreset#vertical\endcsname{\page_layouts_set_element_status_normal#vertical}}

\def\page_layouts_set_element_status_normal#vertical%
  {\global\expandafter\let\csname\namedlayoutelementhash#vertical\c!state\endcsname\v!normal
   \global\expandafter\let\csname\??layouttextsreset#vertical\endcsname\relax
   \page_layouts_synchronize_element{#vertical}}

\def\page_layouts_synchronize_element#vertical%
  {\xdef\previoustextstate{\csname\??layouttextssynchronize#vertical\endcsname}% can be a let
   \edef\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 \else
   \ifx\previoustextstate\v!high \calculatevsizes\page_backgrounds_recalculate \else
   \ifx\currenttextstate \v!none \calculatevsizes\page_backgrounds_recalculate \else
   \ifx\previoustextstate\v!none \calculatevsizes\page_backgrounds_recalculate \fi\fi\fi\fi
   \letgvalue{\??layouttextssynchronize#vertical}\currenttextstate}

\unexpanded\def\setuptop   {\dotripleempty\page_layouts_setup_text[\v!top   ]}
\unexpanded\def\setupheader{\dotripleempty\page_layouts_setup_text[\v!header]}
\unexpanded\def\setuptext  {\dotripleempty\page_layouts_setup_text[\v!text  ]}
\unexpanded\def\setupfooter{\dotripleempty\page_layouts_setup_text[\v!footer]}
\unexpanded\def\setupbottom{\dotripleempty\page_layouts_setup_text[\v!bottom]}

%D We inherit some settings:

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

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

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

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

%D \macros
%D  {setuptoptexts, setupheadertexts, setuptexttexts,
%D   setupfootertexts, setupbottomtexts}
%D
%D The next macros take one or more arguments. The exact setup
%D depends on the number of arguments. Although not that
%D intuitive, the current scheme evolved out of the original.
%D When margin and edge texts as well as middle texts showed
%D up, the current odd|/|even scheme surfaced.
%D
%D \showsetup{setuptoptexts}
%D \showsetup{setupheadertexts}
%D \showsetup{setuptexttexts}
%D \showsetup{setupfootertexts}
%D \showsetup{setupbottomtexts}

\unexpanded\def\setuptoptexts   {\dosixtupleempty\page_layouts_setup_texts[\v!top    ]}
\unexpanded\def\setupheadertexts{\dosixtupleempty\page_layouts_setup_texts[\v!header ]}
\unexpanded\def\setuptexttexts  {\dosixtupleempty\page_layouts_setup_texts[\v!text   ]}
\unexpanded\def\setupfootertexts{\dosixtupleempty\page_layouts_setup_texts[\v!footer ]}
\unexpanded\def\setupbottomtexts{\dosixtupleempty\page_layouts_setup_texts[\v!bottom ]}

% todo: \setuplayoutelementtext

% An alternative approach is to have more variables but that does not
% make the code less complex (probably more).

\def\page_layouts_setup_texts[#vertical][#horizontal][#a][#b][#c][#d]%
  {\ifsixthargument
     \edef\currentlayoutelement{#vertical:#horizontal}%
     \setlayoutelementparameter\c!lefttext
       {\page_layouts_process_element_double
          \c!leftstyle \c!leftcolor \c!leftwidth {#a}%
          \c!rightstyle\c!rightcolor\c!rightwidth{#d}}%
     \setlayoutelementparameter\c!righttext
       {\page_layouts_process_element_double
          \c!rightstyle\c!rightcolor\c!rightwidth{#b}%
          \c!leftstyle \c!leftcolor \c!leftwidth {#c}}%
   \else\iffifthargument
     \edef\currentlayoutelement{#vertical:\v!text}%
     \setlayoutelementparameter\c!lefttext
       {\page_layouts_process_element_double
          \c!leftstyle \c!leftcolor \c!leftwidth {#horizontal}%
          \c!rightstyle\c!rightcolor\c!rightwidth{#c}}%
     \setlayoutelementparameter\c!righttext
       {\page_layouts_process_element_double
          \c!rightstyle\c!rightcolor\c!rightwidth{#a}%
          \c!leftstyle \c!leftcolor \c!leftwidth {#b}}%
   \else\iffourthargument
     \edef\currentlayoutelement{#vertical:#horizontal}%
     \doifelsenothing{\detokenize{#a}}
       {\resetlayoutelementparameter\c!lefttext}
       {\setlayoutelementparameter\c!lefttext
          {\page_layouts_process_element_double
             \c!leftstyle\c!leftcolor\c!leftwidth{#a}%
             \c!leftstyle\c!leftcolor\c!leftwidth{#a}}}%
     \doifelsenothing{\detokenize{#b}}
       {\resetlayoutelementparameter\c!righttext}
       {\setlayoutelementparameter\c!righttext
          {\page_layouts_process_element_double
             \c!rightstyle\c!rightcolor\c!rightwidth{#b}%
             \c!rightstyle\c!rightcolor\c!rightwidth{#b}}}%
   \else\ifthirdargument
     \edef\currentlayoutelement{#vertical:\v!text}%
     \doifelsenothing{\detokenize{#horizontal}}
       {\resetlayoutelementparameter\c!lefttext}
       {\setlayoutelementparameter\c!lefttext
          {\page_layouts_process_element_double
             \c!leftstyle\c!leftcolor\c!leftwidth{#horizontal}%
             \c!leftstyle\c!leftcolor\c!leftwidth{#horizontal}}}%
     \doifelsenothing{\detokenize{#a}}
       {\resetlayoutelementparameter\c!righttext}
       {\setlayoutelementparameter\c!righttext
          {\page_layouts_process_element_double
             \c!rightstyle\c!rightcolor\c!rightwidth{#a}%
             \c!rightstyle\c!rightcolor\c!rightwidth{#a}}}%
   \else\ifsecondargument
     \edef\currentlayoutelement{#vertical:\v!text}%
     \resetlayoutelementparameter\c!lefttext
     \resetlayoutelementparameter\c!righttext
     \doifelsenothing{\detokenize{#horizontal}}
       {\resetlayoutelementparameter\c!middletext}
       {\setlayoutelementparameter\c!middletext
          {\page_layouts_process_element_single\c!style\c!color\c!width{#horizontal}}}%
   \else
     \edef\currentlayoutelement{#vertical:\v!text}%
     \resetlayoutelementparameter\c!lefttext
     \resetlayoutelementparameter\c!righttext
     \resetlayoutelementparameter\c!middletext
     \edef\currentlayoutelement{#vertical:\v!margin}%
     \resetlayoutelementparameter\c!lefttext
     \resetlayoutelementparameter\c!righttext
     \resetlayoutelementparameter\c!middletext
     \edef\currentlayoutelement{#vertical:\v!edge}%
     \resetlayoutelementparameter\c!lefttext
     \resetlayoutelementparameter\c!righttext
     \resetlayoutelementparameter\c!middletext
   \fi\fi\fi\fi\fi}

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

\unexpanded\def\page_layouts_process_element_double
  {\doifelseoddpage
     \page_layouts_process_element_double_odd
     \page_layouts_process_element_double_even}

\def\page_layouts_process_element_double_odd #lstyle#lcolor#lwidth#lcontent#rstyle#rcolor#rwidth#rcontent%
  {\page_layouts_process_element_single#lstyle#lcolor#lwidth{#lcontent}}

\def\page_layouts_process_element_double_even#lstyle#color#lwidth#lcontent#rstyle#rcolor#rwidth#rcontent%
  {\page_layouts_process_element_single#rstyle#rcolor#rwidth{#rcontent}}

%D The next macro will be cleaned up and made less messy and
%D dependent.

\let\m_page_layouts_element_content\empty

\unexpanded\def\page_layouts_process_element_single#style#color#width#content%
  {\edef\m_page_layouts_element_content{\detokenize{#content}}% so no \v!xxx
   \ifx\m_page_layouts_element_content\empty
     % should not happen too often
   \else
     \page_layouts_process_element_single_indeed#style#color#width{#content}%
   \fi}

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

\def\page_layouts_process_element_single_indeed#style#color#width#content%
  {\begingroup
   \uselayoutelementstyleandcolor#style#color%
   \csname\??layouttextstrut\layoutelementparameter\c!strut\endcsname
   \ifcsname\??layouttextspecial\m_page_layouts_element_content\endcsname
     \csname\??layouttextspecial\m_page_layouts_element_content\endcsname
   \else
     \edef\currentlayoutelementwidth{\layoutelementparameter#width}%
     \ifx\currentlayoutelementwidth\empty
       \expandafter\page_layouts_process_element_single_normal
     \else
       \expandafter\page_layouts_process_element_single_limited
     \fi{#content}%
   \fi
   \endgroup}

% {}{}{} prevents lookahead issues ... this will go away

\def\page_layouts_process_element_single_normal#content%
  {\doifelsemarking\m_page_layouts_element_content
     {\getmarking[\m_page_layouts_element_content][\v!first]}
     {\ignorecrlf#content{}{}{}}}

\def\page_layouts_process_element_single_limited#content%
  {\doifelsemarking\m_page_layouts_element_content
     {\limitatetext{\getmarking[\m_page_layouts_element_content][\v!first]}\currentlayoutelementwidth\unknown}
     {\ignorecrlf\limitatetext{#content{}{}{}}\currentlayoutelementwidth\unknown}}

\setvalue{\??layouttextspecial\v!pagenumber}{\page_layouts_place_page_number}
\setvalue{\??layouttextspecial\v!date      }{\currentdate}

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

% % where used ?
%
% \def\page_layouts_limitate_element_text#width%
%   {\edef\currentlayoutelementwidth{\layoutelementparameter#width}%
%    \ifx\currentlayoutelementwidth\empty
%      \expandafter\firstofoneargument
%    \else
%      \expandafter\page_layouts_limitate_element_text_indeed
%    \fi}
%
% \def\page_layouts_limitate_element_text_indeed#content%
%   {\limitatetext{#content}\currentlayoutelementwidth\unknown}

%D The placement of text is hooked into the token lists
%D associated to the area at hand.

\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
%D the \type {status} variable. This is handled by the next
%D couple of macros.

\newcount\c_page_layouts_element_state_n

\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
     \setxvalue{\namedlayoutelementhash#vertical\c!n}{\the\numexpr\c_page_layouts_element_state_n+\minusone}%
     \let\textlinestatus\v!stop
   \fi}

\appendtoks
   \doifinset\v!header\floatspecification{\setxvalue{\namedlayoutelementhash\v!header\c!n}{1}}%
   \doifinset\v!footer\floatspecification{\setxvalue{\namedlayoutelementhash\v!footer\c!n}{1}}%
\to \everybeforeflushedpagefloat

\unexpanded\def\page_layouts_place_text_line#vertical%
  {\page_layouts_set_element_status#vertical%
   \csname\??layouttextsline\ifcsname\??layouttextsline\textlinestatus\endcsname\textlinestatus\else\s!unknown\fi\endcsname#vertical}

\unexpanded\def\doifelselayouttextline#vertical% shown or not
  {\edef\currentlayoutelementstate{\namedlayoutelementparameter{#vertical}\c!state}%
   \ifx\currentlayoutelementstate\v!normal
      \expandafter\firstoftwoarguments
   \else\ifx\currentlayoutelementstate\v!start
      \doubleexpandafter\firstoftwoarguments
   \else
      \doubleexpandafter\secondoftwoarguments
   \fi\fi}

\unexpanded\def\doifelselayoutsomeline#vertical% present or not
  {\edef\currentlayoutelementstate{\namedlayoutelementparameter{#vertical}\c!state}%
   \ifx\currentlayoutelementstate\v!none
     \expandafter\secondoftwoarguments
   \else\ifx\currentlayoutelementstate\v!high
     \doubleexpandafter\secondoftwoarguments
   \else
     \doubleexpandafter\firstoftwoarguments
   \fi\fi}

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

\newconditional\resyncaftertextline

\setvalue{\??layouttextsline\v!normal}{\page_layouts_place_text_line_indeed}
\setvalue{\??layouttextsline\empty   }{\page_layouts_place_text_line_indeed}

\letvalue{\??layouttextsline\v!none}\gobbletwoarguments
\letvalue{\??layouttextsline\v!stop}\gobbletwoarguments

\setvalue{\??layouttextsline\v!high}#vertical#height%
  {\global\settrue\resyncaftertextline
   \page_layouts_reset_element_status#vertical}

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

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

\setvalue{\??layouttextsline\v!nomarking}#vertical#height%
  {\bgroup
   \page_layouts_reset_element_status#vertical%
   \settrue\inhibitgetmarking
   \page_layouts_place_text_line_indeed#vertical#height%
   \egroup}

\setvalue{\??layouttextsline\s!unknown}#vertical#height%
  {\global\settrue\resyncaftertextline
   \begingroup % new
   \page_layouts_reset_element_status#vertical%
   \csname\namedlayoutelementhash#vertical\textlinestatus\endcsname
   \csname\namedlayoutelementhash#vertical\v!text  \textlinestatus\endcsname
   \csname\namedlayoutelementhash#vertical\v!margin\textlinestatus\endcsname
   \csname\namedlayoutelementhash#vertical\v!edge  \textlinestatus\endcsname
   \page_layouts_place_text_line_indeed#vertical#height%
   \endgroup}

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

\unexpanded\def\resetlayouttextlines % public
  {\csname\??layouttextsreset\v!top   \endcsname
   \csname\??layouttextsreset\v!header\endcsname
   \csname\??layouttextsreset\v!text  \endcsname
   \csname\??layouttextsreset\v!footer\endcsname
   \csname\??layouttextsreset\v!bottom\endcsname
   \ifconditional\resyncaftertextline
     \calculateglobalvsizes
     \page_backgrounds_recalculate
     \global\setfalse\resyncaftertextline
   \fi}

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

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

\unexpanded\def\settextcontent
  {\doquintupleempty\page_layouts_set_text_content}

\def\page_layouts_set_text_content[#vertical][#horizontal][#one][#two][#three]% header text middle text/text
  {\iffifthargument
     \setvalue{\namedlayoutelementhash{#vertical:#horizontal}\executeifdefined{\??layouttextcontent\v!text:#one}\c!middletext}%
       {\page_layouts_process_element_double
          \c!leftstyle \c!leftcolor \c!leftwidth {#two}%
          \c!rightstyle\c!rightcolor\c!rightwidth{#three}}%
   \else\iffourthargument
     \setvalue{\namedlayoutelementhash{#vertical:#horizontal}\executeifdefined{\??layouttextcontent\v!text:#one}\c!middletext}%
       {\page_layouts_process_element_double
          \c!leftstyle \c!leftcolor \c!leftwidth {#two}%
          \c!rightstyle\c!rightcolor\c!rightwidth{#two}}%
   \else\ifthirdargument
     \setvalue{\namedlayoutelementhash{#vertical:#horizontal}\c!middletext}%
       {\page_layouts_process_element_double
          \c!leftstyle \c!leftcolor \c!leftwidth {#one}%
          \c!rightstyle\c!rightcolor\c!rightwidth{#one}}%
   \fi\fi\fi}

\unexpanded\def\resettextcontent
  {\dotripleempty\page_layouts_reset_text_content}

\def\page_layouts_reset_text_content[#vertical][#horizontal][#tag]% header text middle
  {\edef\currentlayoutelement{#vertical:#horizontal}%
   \ifthirdargument
     \letvalueempty{\layoutelementhash\executeifdefined{\??layouttextcontent\v!text:#tag}\c!middletext}%
   \else\ifsecondargument
     \resetlayoutelementparameter\c!lefttext
     \resetlayoutelementparameter\c!middletext
     \resetlayoutelementparameter\c!righttext
   \fi\fi}

\letvalue{\??layouttextcontent\c!middle:\v!text}\c!middletext
\letvalue{\??layouttextcontent\c!left  :\v!text}\c!lefttext
\letvalue{\??layouttextcontent\c!right :\v!text}\c!righttext

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

\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
      \let\\\ignoredlinebreak
      \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
      \kern\zeropoint}% keep the \dp, beware of \vtops, never change this!
   \dp\b_page_layouts_element\zeropoint
   \box\b_page_layouts_element
   \vskip-#height\relax}

\let\page_layouts_extra_at_margin_left \plusone
\let\page_layouts_extra_at_margin_right\plustwo

\let\page_layouts_place_extra_text_left \relax % historic
\let\page_layouts_place_extra_text_right\relax % historic

\def\page_layouts_place_text_line_right
  {\hbox
     {\ifdim\leftedgewidth>\zeropoint
        \page_layouts_left_edge_element\c!lefttext
      \fi
      \ifdim\leftmarginwidth>\zeropoint
       %\page_layouts_left_margin_element\c!lefttext\page_layouts_extra_at_margin_left
        \page_layouts_left_margin_element\c!lefttext\page_layouts_extra_at_margin_right
      \fi
      \ifdim\makeupwidth>\zeropoint
        \page_layouts_text_body_element\c!lefttext\c!middletext\c!righttext\page_layouts_extra_at_margin_left
      \fi
      \ifdim\rightmarginwidth>\zeropoint
       %\page_layouts_right_margin_element\c!righttext\page_layouts_extra_at_margin_left
        \page_layouts_right_margin_element\c!righttext\page_layouts_extra_at_margin_right
      \fi
      \ifdim\rightedgewidth>\zeropoint
       %\page_layouts_right_edge_element\c!lefttext
        \page_layouts_right_edge_element\c!righttext
      \fi}}

\def\page_layouts_place_text_line_left
  {\hbox
     {\ifdim\leftedgewidth>\zeropoint
        \page_layouts_left_edge_element\c!righttext
      \fi
      \ifdim\leftmarginwidth>\zeropoint
       %\page_layouts_left_margin_element\c!righttext\page_layouts_extra_at_margin_right
        \page_layouts_left_margin_element\c!righttext\page_layouts_extra_at_margin_left
      \fi
      \ifdim\makeupwidth>\zeropoint
        \page_layouts_text_body_element\c!righttext\c!middletext\c!lefttext\page_layouts_extra_at_margin_right
      \fi
      \ifdim\rightmarginwidth>\zeropoint
       %\page_layouts_right_margin_element\c!lefttext\page_layouts_extra_at_margin_right
        \page_layouts_right_margin_element\c!lefttext\page_layouts_extra_at_margin_left
      \fi
      \ifdim\rightedgewidth>\zeropoint
       %\page_layouts_right_edge_element\c!righttext
        \page_layouts_right_edge_element\c!lefttext
      \fi}}

\def\page_layouts_left_edge_element#parameter%
  {\edef\currentlayoutelement{\currentlayouttextline:\v!edge}%
   \page_layouts_place_element_indeed\leftedgewidth
     {\hss\layoutelementparameter#parameter}%
   \kern\leftedgedistance}

\def\page_layouts_left_margin_element#parameter#extrastate%
  {\edef\currentlayoutelement{\currentlayouttextline:\v!margin}%
   \page_layouts_place_element_indeed\leftmarginwidth
     {\hbox to \leftmarginwidth{\hss\layoutelementparameter#parameter}%
      \ifnum#extrastate=\page_layouts_extra_at_margin_left
        \kern-\leftmarginwidth
        \hbox to \leftmarginwidth{\hss\layoutelementparameter\c!margintext}%
      \fi}%
   \kern\leftmargindistance}

\def\page_layouts_text_body_element#left#middle#right#extrastate%
  {\edef\currentlayoutelement{\currentlayouttextline:\v!text}%
   \page_layouts_place_element_indeed\makeupwidth
     {\hbox to \makeupwidth{\ifnum#extrastate=\page_layouts_extra_at_margin_left\page_layouts_place_extra_text_left\fi\layoutelementparameter#left\hss}%
      \kern-\makeupwidth
      \hbox to \makeupwidth{\hss\layoutelementparameter#middle\hss}%
      \kern-\makeupwidth
      \hbox to \makeupwidth{\hss\layoutelementparameter#right\ifnum#extrastate=\page_layouts_extra_at_margin_right\page_layouts_place_extra_text_right\fi}}}

\def\page_layouts_right_margin_element#parameter#extrastate%
  {\edef\currentlayoutelement{\currentlayouttextline:\v!margin}%
   \kern\rightmargindistance
   \page_layouts_place_element_indeed\rightmarginwidth
     {\hbox to \rightmarginwidth{\layoutelementparameter#parameter\hss}%
      \ifnum#extrastate=\page_layouts_extra_at_margin_right
        \kern-\rightmarginwidth
        \hbox to \rightmarginwidth{\layoutelementparameter\c!margintext\hss}%
      \fi}}

\def\page_layouts_right_edge_element#parameter%
  {\edef\currentlayoutelement{\currentlayouttextline:\v!edge}%
   \kern\rightedgedistance
   \page_layouts_place_element_indeed\rightedgewidth
     {\layoutelementparameter#parameter\hss}}

\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
%D purpose, one can add a rule in the following way. This
%D method makes the rules disappear in case of an empty text
%D 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
%D \type {unknown}. This one is used to take care of
%D symbolic texts handlers.
%D
%D \showsetup{definetext}
%D
%D The next example demonstrates how we can use this
%D mechanism to provide page (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

\unexpanded\def\definetext
  {\doseventupleempty\page_layouts_define_text}

\def\page_layouts_define_text[#tag][#vertical][#horizontal][#a][#b][#c][#d]%
  {\ifseventhargument
     \setvalue{\namedlayoutelementhash{#vertical:#horizontal}#tag}%
       {\dosixtupleempty\page_layouts_setup_texts[#vertical][#horizontal][#a][#b][#c][#d]}%
   \else\ifsixthargument
     \setvalue{\namedlayoutelementhash{#vertical}#tag}%
       {\dosixtupleempty\page_layouts_setup_texts[#vertical][#horizontal][#a][#b][#c]}%
   \else\iffifthargument
     \setvalue{\namedlayoutelementhash{#vertical:#horizontal}#tag}%
       {\dosixtupleempty\page_layouts_setup_texts[#vertical][#horizontal][#a][#b]}%
   \else\iffourthargument
     \setvalue{\namedlayoutelementhash{#vertical}#tag}%
       {\dosixtupleempty\page_layouts_setup_texts[#vertical][#horizontal][#a]}%
   \else
     \setvalue{\namedlayoutelementhash{#vertical}#tag}%
       {\dosixtupleempty\page_layouts_setup_texts[#vertical][#horizontal]}%
   \fi\fi\fi\fi}

%D A few more page breakers:

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

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

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

%D While the header and footer lines are moved away from the
%D main text, the top and 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:

% We reset a previous location but only when it has a pagenumber
% associated. This is a rather messy test but better than the MkII
% way where we use states and keep 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 \unexpanded else
  {\strc_pagenumbers_place_location}  % test below fails

\def\page_layouts_reset_page_number_location
  {\ifx\m_page_layouts_page_number_location_v\relax\else
     \edef\currentlayoutelement{\m_page_layouts_page_number_location_v:\m_page_layouts_page_number_location_h}%
     \edef\page_layouts_previous_page_number_locator{\detokenizedlayoutelementparameter\m_page_layouts_page_number_location_x}%
     \doif{\meaning\page_layouts_previous_page_number_locator}{\meaning\page_layouts_place_page_number}
       {\resetlayoutelementparameter\m_page_layouts_page_number_location_x}%
   \fi}

\def\page_layouts_set_page_number_location
  {\edef\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
     \let\page_layouts_place_extra_text_left \relax
     \let\page_layouts_place_extra_text_right\relax
   \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]}

\unexpanded\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
     \ifx\p_strc_pagenumbers_location\empty
       % set otherwise
     \else\ifx\p_strc_pagenumbers_location\v!none
       % set otherwise
     \else
       \page_layouts_identify_page_number_location
       \page_layouts_set_page_number_location
     \fi\fi
   \fi}

\def\page_layouts_place_page_number_left % historic
  {\begingroup
   \setbox\scratchbox\hbox{\ignorespaces\layoutelementparameter\c!marginedgetext\removeunwantedspaces}%
   \ifzeropt\wd\scratchbox\else
     \edef\p_strc_pagenumbers_width{\directpagenumberingparameter\c!width}%
     \ifx\p_strc_pagenumbers_width\empty
       \box\scratchbox\tfskip
     \else
       \hbox to \p_strc_pagenumbers_width{\box\scratchbox\hss}%
     \fi
   \fi
   \endgroup}

\def\page_layouts_place_page_number_right % historic
  {\begingroup
   \setbox\scratchbox\hbox{\ignorespaces\layoutelementparameter\c!marginedgetext\removeunwantedspaces}%
   \ifzeropt\wd\scratchbox\else
     \edef\p_strc_pagenumbers_width{\directpagenumberingparameter\c!width}%
     \ifx\p_strc_pagenumbers_width\empty
       \tfskip\box\scratchbox
     \else
       \hbox to \p_strc_pagenumbers_width{\hss\box\scratchbox}%
     \fi
   \fi
   \endgroup}

\strc_pagenumbers_set_location % initializes

% will go to page-box.mkiv

% the next macros will be redone (less boxing)

\newbox\b_page_layouts_element

\def\page_layouts_insert_elements
  {\ifcase\pageornamentstate
     \page_layouts_place_elements_indeed
   \fi}

\def\page_layouts_place_elements_indeed
  {\setbox\b_page_layouts_element\vbox
     {\dontcomplain
      \calculatereducedvsizes
      \swapmargins
      \offinterlineskip
      \vskip\dimexpr-\topheight-\topdistance\relax
      \the\toptextcontent
      \vskip\dimexpr\topheight+\topdistance\relax
      \the\headertextcontent
      \vskip\dimexpr\headerheight+\headerdistance\relax
      \anch_positions_place_anchors
      \vskip-\textheight
      \the\texttextcontent
      \vskip\textheight
      \the\everyendoftextbody
      \vskip\footerdistance
      \the\footertextcontent
      \vskip\dimexpr\footerheight+\bottomdistance\relax
      \the\bottomtextcontent
      \vskip\bottomheight
      \vfilll}%
  \smashbox\b_page_layouts_element
  \box\b_page_layouts_element}

\def\page_insert_body#1#2%
  {\setbox\b_page_layouts_element\vbox
     {\offinterlineskip
      \calculatereducedvsizes
      \calculatehsizes
      \swapmargins
      \vskip\dimexpr\headerheight+\headerdistance+\layoutparameter\c!textdistance\relax
      \dontleavehmode
      \hbox to \makeupwidth
        {\begingroup
           \swapmargins
           \goleftonpage
           \ifdim\leftedgewidth>\zeropoint
             \the\leftedgetextcontent
             \kern\dimexpr\leftedgewidth+\leftedgedistance\relax
           \fi
           \ifdim\leftmarginwidth>\zeropoint
             \the\leftmargintextcontent
             \kern\dimexpr\leftmarginwidth+\leftmargindistance\relax
           \fi
         \endgroup
         \page_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 The main text area has to be combined with some additional
%D (tracing) information.

% will be stored as normal and overloaded in page-lyr and later in
% page-spr we overload the the stored version .. evenatually i will
% clear up the experimental mess

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

\protect \endinput

