page-lay.mkiv / last modification: 2020-01-30 14:16
%D \module
%D   [       file=page-lay,
%D        version=2000.10.20, % copied from main-001
%D          title=\CONTEXT\ Page Macros,
%D       subtitle=Layout Specification,
%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 / Layout Specification}

%D Before you start wondering why some of the page related modules skip upward or
%D left in order to place elements, you must realize that the reference point is the
%D top left corner of the main typesetting area. One reason for this choice is that
%D it suited some viewers that displayed page areas. Another reason is that margins,
%D edges and top and bottom areas are kind of virtual, while the header, text and
%D footer areas normally determine the text flow.

\unprotect

%D The dimensions related to layout areas are represented by real dimensions.

\newdimen\paperheight          \paperheight          = 297mm
\newdimen\paperwidth           \paperwidth           = 210mm
\newdimen\paperoffset          \paperoffset          = \zeropoint
\newdimen\paperbleed           \paperbleed           = \zeropoint
\newdimen\spinewidth           \spinewidth           = \zeropoint

\newdimen\printpaperheight     \printpaperheight     = \paperheight
\newdimen\printpaperwidth      \printpaperwidth      = \paperwidth

\newdimen\makeupheight                               % calculated
\newdimen\makeupwidth                                % calculated

\newdimen\textheight                                 % calculated
\newdimen\textwidth                                  % calculated

\newdimen\topspace             \topspace             = 2cm
\newdimen\backspace            \backspace            = \topspace
\newdimen\cutspace             \cutspace             = \zeropoint
\newdimen\bottomspace          \bottomspace          = \zeropoint

\newdimen\headerheight         \headerheight         = 2cm
\newdimen\footerheight         \footerheight         = \headerheight

\newdimen\topoffset            \topoffset            = \zeropoint
\newdimen\backoffset           \backoffset           = \topoffset

\newdimen\leftmarginwidth      \leftmarginwidth      = 3cm
\newdimen\rightmarginwidth     \rightmarginwidth     = \leftmarginwidth

\newdimen\leftedgewidth        \leftedgewidth        = 3cm
\newdimen\rightedgewidth       \rightedgewidth       = \leftedgewidth

\newdimen\topheight            \topheight            = \zeropoint
\newdimen\bottomheight         \bottomheight         = \topheight

\newcount\layoutlines          \layoutlines          = \zerocount
\newcount\layoutcolumns        \layoutcolumns        = \zerocount
\newdimen\layoutcolumndistance \layoutcolumndistance = \zeropoint
\newdimen\layoutcolumnwidth    \layoutcolumnwidth    = \zeropoint

\newdimen\totaltextwidth

%D The next series of dimensions are complemented by left and rights ones.

\newdimen\margindistance
\newdimen\edgedistance
\newdimen\marginwidth
\newdimen\edgewidth

%D Because a distance does not really makes sense when there is no area, we use a
%D zero distance in case there is no area.

%D The horizontal distances are:

\newdimen\leftedgedistance
\newdimen\rightedgedistance
\newdimen\leftmargindistance
\newdimen\rightmargindistance

%D The vertical distances are:

\newdimen\topdistance
\newdimen\headerdistance
\newdimen\textdistance
\newdimen\footerdistance
\newdimen\bottomdistance

\newdimen\textovershoot % available in pagebuilder

%D We need to calculate the extra distances:

\newdimen\naturalmarginwidth
\newdimen\naturaledgewidth
\newdimen\naturalmargindistance
\newdimen\naturaledgedistance
\newdimen\naturalleftedgedistance
\newdimen\naturalrightedgedistance
\newdimen\naturalleftmargindistance
\newdimen\naturalrightmargindistance
\newdimen\naturaltopdistance
\newdimen\naturalheaderdistance
\newdimen\naturaltextdistance
\newdimen\naturalfooterdistance
\newdimen\naturalbottomdistance

%D Now we've come to the setup and definition commands.

\installcorenamespace{layout}
\installcorenamespace{layoutlocation}
\installcorenamespace{layoutalternative}
\installcorenamespace{layoutcolumn}
\installcorenamespace{layoutmethod}

\installswitchcommandhandler \??layout {layout} \??layout

\appendtoks
    \doifnothing{\directlayoutparameter\c!state}{\letlayoutparameter\c!state\v!start}%
\to \everydefinelayout

\appendtoks
    \ifcase\layoutsetupmode
        % can't happen
    \or % \setuplayout[name][key=value]
      \ifx\previouslayout\currentlayout
        \letlayoutparameter\c!state\v!normal % global ? still needed ?
        \let\currentlayout\currentlayout
        \page_layouts_synchronize
        \page_layouts_check_next
      \fi
    \or % \setuplayout[key=value]
      % we can inherit so we always synchronize
      \letlayoutparameter\c!state\v!normal % global ? still needed ?
      \let\currentlayout\previouslayout
      \page_layouts_synchronize
      \page_layouts_check_next
    \or % \setuplayout[name]
      \ifx\currentlayout\v!reset
        \let\currentlayout\empty
      \fi
      \letlayoutparameter\c!state\v!normal % global ? still needed ?
      \glet\currentlayout\currentlayout % global
      \page_layouts_synchronize
      \page_layouts_check_next
    \or % \setuplayout (reverts to main layout)
      \letlayoutparameter\c!state\v!normal % global ? still needed ?
      \glet\currentlayout\empty % global
      \page_layouts_synchronize
      \page_layouts_check_next
    \fi
\to \everysetuplayout

\def\doifelselayoutdefined#1%
  {\ifcsname\namedlayouthash{#1}\c!state\endcsname % maybe a helper
      \expandafter\firstoftwoarguments
   \else
      \expandafter\secondoftwoarguments
   \fi}

\let\doiflayoutdefinedelse\doifelselayoutdefined

\def\layoutdistance#1#2{\ifdim\zeropoint<#1#2\else\zeropoint\fi}

% \newconditional\reverselayout

\def\page_layouts_set_dimensions
  {\global\naturalmarginwidth        \layoutparameter\c!margin
   \global\naturaledgewidth          \layoutparameter\c!edge
   \global\naturalmargindistance     \layoutparameter\c!margindistance
   \global\naturaledgedistance       \layoutparameter\c!edgedistance
   \global\naturalleftedgedistance   \layoutparameter\c!leftedgedistance
   \global\naturalrightedgedistance  \layoutparameter\c!rightedgedistance
   \global\naturalleftmargindistance \layoutparameter\c!leftmargindistance
   \global\naturalrightmargindistance\layoutparameter\c!rightmargindistance
   \global\naturaltopdistance        \layoutparameter\c!topdistance
   \global\naturalheaderdistance     \layoutparameter\c!headerdistance
   \global\naturaltextdistance       \layoutparameter\c!textdistance
   \global\naturalfooterdistance     \layoutparameter\c!footerdistance
   \global\naturalbottomdistance     \layoutparameter\c!bottomdistance
   %
   \global\marginwidth               \naturalmarginwidth
   \global\edgewidth                 \naturaledgewidth
   \global\margindistance            \naturalmargindistance
   \global\edgedistance              \naturaledgedistance
   %
   \global\leftedgedistance          \layoutdistance\leftedgewidth   \naturalleftedgedistance
   \global\rightedgedistance         \layoutdistance\rightedgewidth  \naturalrightedgedistance
   \global\leftmargindistance        \layoutdistance\leftmarginwidth \naturalleftmargindistance
   \global\rightmargindistance       \layoutdistance\rightmarginwidth\naturalrightmargindistance
   \global\topdistance               \layoutdistance\topheight       \naturaltopdistance
   \global\headerdistance            \layoutdistance\headerheight    \naturalheaderdistance
   \global\textdistance                                              \naturaltextdistance
   \global\footerdistance            \layoutdistance\footerheight    \naturalfooterdistance
   \global\bottomdistance            \layoutdistance\bottomheight    \naturalbottomdistance}

\def\page_layouts_set_distances % local in \setreducedvsize
  {\headerdistance\layoutdistance\headerheight\naturalheaderdistance
   \footerdistance\layoutdistance\footerheight\naturalfooterdistance}

% these are wrong in the running text, assumes some swapping, needs a cleanup

\def\outermarginwidth   {\rightorleftpageaction\rightmarginwidth   \leftmarginwidth }
\def\innermarginwidth   {\rightorleftpageaction\leftmarginwidth    \rightmarginwidth}
\def\outermargindistance{\rightorleftpageaction\rightmargindistance\leftmargindistance }
\def\innermargindistance{\rightorleftpageaction\leftmargindistance \rightmargindistance}

\def\outeredgewidth     {\rightorleftpageaction\rightedgewidth   \leftedgewidth }
\def\inneredgewidth     {\rightorleftpageaction\leftedgewidth    \rightedgewidth}
\def\outeredgedistance  {\rightorleftpageaction\rightedgedistance\leftedgedistance }
\def\inneredgedistance  {\rightorleftpageaction\leftedgedistance \rightedgedistance}

\def\outerspacewidth    {\rightorleftpageaction\cutspace\backspace}
\def\innerspacewidth    {\rightorleftpageaction\backspace\cutspace}

\newtoks\extralayoutcalculations

\def\page_layouts_calculate_extras
  {\the\extralayoutcalculations}

\newtoks\everyswapmargins % watch the order !

\appendtoks
    \swapdimens\leftmargindistance\rightmargindistance
    \swapdimens\leftedgedistance  \rightedgedistance
    \swapdimens\leftmarginwidth   \rightmarginwidth
    \swapdimens\leftedgewidth     \rightedgewidth
    %
    \swapmacros\leftmargintotal   \rightmargintotal
    \swapmacros\leftedgetotal     \rightedgetotal
    \swapmacros\leftsidetotal     \rightsidetotal
    \swapmacros\leftcombitotal    \rightcombitotal
    \swapmacros\innermargintotal  \outermargintotal
    \swapmacros\inneredgetotal    \outeredgetotal
    \swapmacros\innercombitotal   \outercombitotal
    \swapmacros\innersidetotal    \outersidetotal
\to \everyswapmargins

%D The papersize macros have a long history and we don't want to change the commands
%D so they keep looking a bit complex.

%D \macros
%D   {definepapersize}
%D
%D Before we start calculating layout dimensions, we will first take care of paper
%D sizes. The first argument can be either an assignment (for defaults) or an
%D identifier, in which case the second argument is an assignment.
%D
%D \showsetup{definepapersize}
%D
%D Yet undocumented, let's see if it gets noticed.
%D
%D \starttyping
%D \definepapersize[main] [A4]          [A4]
%D \definepapersize[extra][A4,landscape][A4,landscape]
%D
%D \starttext
%D     \setuppapersize[main]
%D     Page 1. \page
%D     Page 2. \page
%D     \setuppapersize[extra]
%D     Page 2 \page
%D     \setuppapersize[main]
%D     Page 3. \page
%D     Page 4. \page
%D     \adaptpapersize[extra]
%D     Page 5. \page
%D     Page 6. \page
%D \stoptext
%D \stoptyping
%D
%D \macros
%D   {setuppaper,setuppapersize}
%D
%D When setting up the papersize on which to typeset and print, we can also
%D determine some more characteristics.
%D
%D \showsetup{setuppapersize}
%D
%D We keep track of these features with the following
%D variables.

\installcorenamespace{layouttarget}
\installcorenamespace{layoutpaper}
\installcorenamespace{layoutprint}
\installcorenamespace{layoutcurrent}

\installcommandhandler \??layouttarget {layouttarget} \??layouttarget % so this is a sort of mix, not really a user command / maybe switch handler

\newconditional\c_page_target_paper_mirror
\newconstant   \c_page_target_paper_orientation
\newconstant   \c_page_target_paper_reverse
\newconditional\c_page_target_paper_landscape
\newconditional\c_page_target_paper_negate

\newconditional\c_page_target_print_mirror
\newconstant   \c_page_target_print_orientation
\newconstant   \c_page_target_print_reverse
\newconditional\c_page_target_print_landscape
\newconditional\c_page_target_print_negate
\newconditional\c_page_target_print_doublesided

\let\v_page_target_left_fill  \relax
\let\v_page_target_right_fill \relax
\let\v_page_target_top_fill   \relax
\let\v_page_target_bottom_fill\relax

\let\papersize     \empty
\let\printpapersize\empty

\def\v_page_target_top      {\namedlayouttargetparameter\papersize\c!top   }
\def\v_page_target_bottom   {\namedlayouttargetparameter\papersize\c!bottom}
\def\v_page_target_left     {\namedlayouttargetparameter\papersize\c!left  }
\def\v_page_target_right    {\namedlayouttargetparameter\papersize\c!right }
\def\v_page_target_method   {\rootlayouttargetparameter           \c!method}
\def\v_page_target_scale    {\rootlayouttargetparameter           \c!scale }
\def\v_page_target_nx       {\numexpr\rootlayouttargetparameter   \c!nx       \relax}
\def\v_page_target_ny       {\numexpr\rootlayouttargetparameter   \c!ny       \relax}
\def\v_page_target_dx       {\dimexpr\rootlayouttargetparameter   \c!dx       \relax}
\def\v_page_target_dy       {\dimexpr\rootlayouttargetparameter   \c!dy       \relax}
\def\v_page_target_width    {\dimexpr\rootlayouttargetparameter   \c!width    \relax}
\def\v_page_target_height   {\dimexpr\rootlayouttargetparameter   \c!height   \relax}
\def\v_page_target_topspace {\dimexpr\rootlayouttargetparameter   \c!topspace \relax}
\def\v_page_target_backspace{\dimexpr\rootlayouttargetparameter   \c!backspace\relax}
\def\v_page_target_offset   {\dimexpr\rootlayouttargetparameter   \c!offset   \relax}

\def\v_page_target_xy       {\numexpr\v_page_target_nx*\v_page_target_ny\relax}

%D Normally we will not use this command directly but for now it works out okay. In
%D the future we might use more of the related commands.

\setuplayouttarget
  [% these are rather special
   \c!nx=1,
   \c!ny=1,
   \c!dx=\zeropoint,
   \c!dy=\zeropoint,
   \c!topspace=\zeropoint,
   \c!backspace=\zeropoint,
   \c!width=\zeropoint,
   \c!height=\zeropoint,
   %
   \c!method=\v!normal,
   \c!option=\v!max,
   \c!alternative=\v!normal,
   %
   \c!scale=1,
   \c!offset=\zeropoint,
   %
   \c!top=,
   \c!bottom=,
   \c!left=,
   \c!right=,
   %
   \c!location=]

% \definepapersize[name][A4][A3]
% \definepapersize[name][settings]

\unexpanded\def\definepapersize
  {\dotripleempty\page_paper_define_size}

\def\page_paper_define_size[#1][#2][#3]%
  {\edef\currentlayouttarget{#1}%
   \ifx\currentlayouttarget\empty
     % invalid target
   \else\ifcondition\validassignment{#2}%
     \definelayouttarget[#1][#2]%
   \else
     \setevalue{\??layoutpaper#1}{#2}%
     \ifthirdargument
       \setevalue{\??layoutprint#1}{#3}%
     \else
       \setevalue{\??layoutprint#1}{#2}%
     \fi
   \fi\fi}

\appendtoks
    \letvalue{\??layoutcurrent\currentlayouttarget}\relax
\to \everydefinelayouttarget

%def\page_paper_the_paper_size#1{\ifcsname\??layoutpaper#1\endcsname\csname\??layoutpaper#1\endcsname\else#1\fi}
%def\page_paper_the_print_size#1{\ifcsname\??layoutprint#1\endcsname\csname\??layoutprint#1\endcsname\else#1\fi}

\def\page_paper_the_paper_size#1{\ifcsname\??layoutpaper#1\endcsname\lastnamedcs\else#1\fi}
\def\page_paper_the_print_size#1{\ifcsname\??layoutprint#1\endcsname\lastnamedcs\else#1\fi}

% \setuppaper    [page=A4,paper=A3] % the k/v variant, changes the current page mapping
% \setuppapersize[A4][a=b,c=d]      % the k/v variant, changes nothing, just settings
% \setuppapersize[A4][A3]           % changes the current page mapping

\let\page_paper_reinstate\relax
\let\page_paper_restore  \relax

\unexpanded\def\setuppapersize
  {\dodoubleempty\page_paper_setup_size}

\unexpanded\def\page_paper_setup_size[#1][#2]%
  {\iffirstargument
     \ifcondition\validassignment{#1}%
       \page_paper_setup_size_settings[#1]%
     \else\ifcondition\validassignment{#2}%
       \page_paper_setup_size_settings_by_name[#1][#2]%
     \else
       \page_paper_setup_size_change_size[#1][#2]%
     \fi\fi
   \else
     \page_paper_restore
   \fi}

\unexpanded\def\page_paper_setup_size_settings[#1]% sometimes used to set paper/print size
  {\let\currentlayouttarget\empty
   \edef\m_layouttarget_paper_saved{\page_paper_the_paper_size{\layouttargetparameter\c!page }}%
   \edef\m_layouttarget_print_saved{\page_paper_the_print_size{\layouttargetparameter\c!paper}}%
   \setupcurrentlayouttarget[#1]%
   \edef\m_layouttarget_paper{\page_paper_the_paper_size{\layouttargetparameter\c!page }}%
   \edef\m_layouttarget_print{\page_paper_the_print_size{\layouttargetparameter\c!paper}}%
   \ifx\m_layouttarget_paper_saved\m_layouttarget_paper
     \ifx\m_layouttarget_print_saved\m_layouttarget_print
       % we didn't change the size, maybe only sx or sy or so
     \else
       \page_paper_setup_size_settings_recalibrate
     \fi
   \else
     \page_paper_setup_size_settings_recalibrate
   \fi}

\def\page_paper_setup_size_settings_recalibrate
  {\ifx\m_layouttarget_paper\empty
     % forget about it
   \else
     \ifx\m_layouttarget_print\empty
        \let\m_layouttarget_print\m_layouttarget_paper
     \fi
     \page_paper_set_current[\m_layouttarget_paper][\m_layouttarget_print]%
   \fi
   \letlayouttargetparameter\c!page \papersize
   \letlayouttargetparameter\c!paper\printpapersize}

\unexpanded\def\page_paper_setup_size_settings_by_name[#1][#2]%
  {\def\currentlayouttarget{\page_paper_the_paper_size{#1}}%
   \setuplayouttarget[#2]}

\unexpanded\def\page_paper_setup_size_change_size[#1][#2]%
  {\doifelsenothing{#2}
     {\page_paper_set_current[#1][#1]}
     {\page_paper_set_current[#1][#2]}}

\let\setuppaper\page_paper_setup_size_settings

\unexpanded\def\adaptpapersize
  {\glet\page_paper_reinstate\page_paper_restore
   \setuppapersize}

\appendtoks
    \page_paper_reinstate
    \glet\page_paper_reinstate\relax
\to \everyaftershipout

\unexpanded\def\page_paper_set_restore#1#2%
  {\xdef\page_paper_restore{\page_paper_set_current_indeed[#1][#2]}}

\unexpanded\def\page_paper_set_current[#1][#2]%
  {\normalexpanded{\page_paper_set_current_indeed
     [\page_paper_the_paper_size{#1}]%
     [\page_paper_the_print_size{#2}]}}

\unexpanded\def\page_paper_reset_paper
  {\global\setfalse\c_page_target_paper_landscape
   \global\setfalse\c_page_target_paper_mirror
   \global\setfalse\c_page_target_paper_negate
   \global\c_page_target_paper_orientation\uprotationangle
   \global\c_page_target_paper_reverse    \uprotationangle}

\unexpanded\def\page_paper_reset_print
  {\global\setfalse\c_page_target_print_landscape
   \global\setfalse\c_page_target_print_mirror
   \global\setfalse\c_page_target_print_negate
   \global\c_page_target_print_orientation\uprotationangle
   \global\c_page_target_print_reverse    \uprotationangle}

\letvalue{\??layoutpaper\v!reset}\page_paper_reset_paper
\letvalue{\??layoutprint\v!reset}\page_paper_reset_print

\setvalue{\??layoutpaper\v!landscape              }{\global\settrue\c_page_target_paper_landscape}
\setvalue{\??layoutpaper\v!mirrored               }{\global\settrue\c_page_target_paper_mirror}
\setvalue{\??layoutpaper\v!negative               }{\global\settrue\c_page_target_paper_negate}
\setvalue{\??layoutpaper\v!rotated                }{\global\c_page_target_paper_orientation\rightrotationangle
                                                    \global\c_page_target_paper_reverse    \leftrotationangle}
\setvalue{\??layoutpaper\number\rightrotationangle}{\global\c_page_target_paper_orientation\rightrotationangle
                                                    \global\c_page_target_paper_reverse    \leftrotationangle}
\setvalue{\??layoutpaper\number\downrotationangle }{\global\c_page_target_paper_orientation\downrotationangle
                                                    \global\c_page_target_paper_reverse    \zerocount}
\setvalue{\??layoutpaper\number\leftrotationangle }{\global\c_page_target_paper_orientation\leftrotationangle
                                                    \global\c_page_target_paper_reverse    \rightrotationangle}

\setvalue{\??layoutprint\v!landscape              }{\global\settrue\c_page_target_print_landscape}
\setvalue{\??layoutprint\v!mirrored               }{\global\settrue\c_page_target_print_mirror}
\setvalue{\??layoutprint\v!negative               }{\global\settrue\c_page_target_print_negate}
\setvalue{\??layoutprint\v!rotated                }{\global\c_page_target_print_orientation\rightrotationangle
                                                    \global\c_page_target_print_reverse    \leftrotationangle}
\setvalue{\??layoutprint\number\rightrotationangle}{\global\c_page_target_print_orientation\rightrotationangle
                                                    \global\c_page_target_print_reverse    \leftrotationangle}
\setvalue{\??layoutprint\number\downrotationangle }{\global\c_page_target_print_orientation\downrotationangle
                                                    \global\c_page_target_print_reverse    \zerocount}
\setvalue{\??layoutprint\number\leftrotationangle }{\global\c_page_target_print_orientation\leftrotationangle
                                                    \global\c_page_target_print_reverse    \rightrotationangle}

%def\page_paper_handle_page_option #1{\ifcsname\??layoutpaper#1\endcsname\csname\??layoutpaper#1\endcsname\fi}
%def\page_paper_handle_print_option#1{\ifcsname\??layoutprint#1\endcsname\csname\??layoutprint#1\endcsname\fi}

\def\page_paper_handle_page_option #1{\begincsname\??layoutpaper#1\endcsname}
\def\page_paper_handle_print_option#1{\begincsname\??layoutprint#1\endcsname}

\unexpanded\def\page_paper_identify_target#1%
  {\ifcsname\??layoutcurrent#1\endcsname
     \edef\currentlayouttarget{#1}%
   \fi}

\unexpanded\def\page_paper_set_current_indeed[#1][#2]%
  {\edef\m_page_asked_paper{#1}% can be the restores
   \edef\m_page_asked_print{#2}%
   %
   \page_paper_set_restore\m_page_asked_paper\m_page_asked_print
   %
   % locate page target
   \let\currentlayouttarget\empty
   \page_paper_reset_paper
   \processcommacommand[\m_page_asked_paper]\page_paper_identify_target
   \ifx\currentlayouttarget\empty
     \let\currentlayouttarget\currentpage
   \fi
   \glet\papersize\currentlayouttarget
   \page_paper_reset_paper
   \processcommacommand[\m_page_asked_paper]\page_paper_handle_page_option
   \global\paperwidth \layouttargetparameter\c!width \relax
   \global\paperheight\layouttargetparameter\c!height\relax
   \ifdim\paperwidth<\onepoint
     \global\paperwidth\onepoint
   \fi
   \ifdim\paperheight<\onepoint
     \global\paperheight\onepoint
   \fi
   \ifconditional\c_page_target_paper_landscape
     \doglobal\swapdimens\paperwidth\paperheight
   \fi
   \ifinpagebody % local freeze
     \normalexpanded{\setlayouttargetparemeter\c!height{\the\paperheight}}%
     \normalexpanded{\setlayouttargetparemeter\c!width {\the\paperwidth }}%
   \fi
   %
   \page_paper_set_offsets
   %  locate paper target
   \page_paper_reset_print
   \processcommacommand[\m_page_asked_print]\page_paper_identify_target
   \glet\printpapersize\currentlayouttarget
   \page_paper_reset_print
   \processcommacommand[\m_page_asked_print]\page_paper_handle_print_option
   \global\printpaperwidth \layouttargetparameter\c!width \relax
   \global\printpaperheight\layouttargetparameter\c!height\relax
   \ifdim\printpaperwidth<\onepoint
     \global\printpaperwidth\paperwidth
   \fi
   \ifdim\printpaperheight<\onepoint
     \global\printpaperheight\paperheight
   \fi
   \ifconditional\c_page_target_print_landscape
     \globalswapdimens\printpaperwidth\printpaperheight
   \fi
   % this check can be confusing, so we've added the possibility
   % to bypass this test: \setuppapersize[option=fit]
   \edef\m_page_asked_option{\rootlayouttargetparameter\c!option}%
   \ifx\m_page_asked_option\v!max % \v!fit is
      \begingroup
      % we need to pre-swap else we get the wrong paper size
      \ifnum\c_page_target_paper_orientation=\rightrotationangle
        \swapdimens\paperwidth\paperheight
      \else\ifnum\c_page_target_paper_orientation=\leftrotationangle
        \swapdimens\paperwidth\paperheight
      \fi\fi
      \ifnum\c_page_target_print_orientation=\rightrotationangle
        \swapdimens\printpaperwidth\printpaperheight
      \else\ifnum\c_page_target_print_orientation=\leftrotationangle
        \swapdimens\printpaperwidth\printpaperheight
      \fi\fi
      \ifdim\paperheight>\printpaperheight
        \global\printpaperheight\paperheight
        \writestatus\m!system{print height forced to paper height}%
      \fi
      \ifdim\paperwidth>\printpaperwidth
        \global\printpaperwidth\paperwidth
        \writestatus\m!system{print width forced to paper width}%
      \fi
      \endgroup
   \fi
  %\writestatus{layout target}{(\the\paperwidth,\the\paperheight) -> (\the\printpaperwidth,\the\printpaperheight)}%
   \page_layouts_synchronize
   % new but we assume \setuplayout
   \scrn_canvas_synchronize_only}

\ifdefined\scrn_canvas_synchronize_only \else
    \let\scrn_canvas_synchronize_only\relax
\fi

\ifdefined\page_paper_set_offsets \else

  \def\page_paper_set_offsets % will move
    {\global\paperoffset\v_page_target_offset
     \global\advance\paperwidth -2\paperoffset
     \global\advance\paperheight-2\paperoffset}

\fi

\ifdefined\synchronizegridsnapping \else
    \let\synchronizegridsnapping\relax
\fi

\let\p_page_layouts_width \empty
\let\p_page_layouts_height\empty

\def\page_layouts_synchronize
  {\setups[\layoutparameter\c!preset]\relax
   \global\leftmarginwidth \layoutparameter\c!leftmargin
   \global\rightmarginwidth\layoutparameter\c!rightmargin
   \global\leftedgewidth   \layoutparameter\c!leftedge
   \global\rightedgewidth  \layoutparameter\c!rightedge
   \global\headerheight    \layoutparameter\c!header
   \global\footerheight    \layoutparameter\c!footer
   \global\bottomheight    \layoutparameter\c!bottom
   \global\topheight       \layoutparameter\c!top
   \global\backspace       \layoutparameter\c!backspace
   \global\topspace        \layoutparameter\c!topspace
   \page_layouts_set_dimensions
   \synchronizegridsnapping
   \usesetupsparameter\layoutparameter % depends on gridsnapping !
   \synchronizewhitespace
   \synchronizeblank
   \setupinterlinespace[\v!reset]% \synchronizegloballinespecs
   \global\cutspace\layoutparameter\c!cutspace\relax
   \edef\p_page_layouts_width{\layoutparameter\c!width}%
   \ifx\p_page_layouts_width\v!middle
     \ifzeropt\cutspace
       \global\cutspace\backspace
     \fi
     \global\makeupwidth\dimexpr\paperwidth-\backspace-\cutspace\relax
   \else\ifx\p_page_layouts_width\v!fit
     \ifzeropt\cutspace
       \global\cutspace\backspace
     \fi
     \global\makeupwidth\dimexpr\paperwidth-\cutspace\relax
     \scratchdimen\dimexpr\backspace
       -\leftedgewidth  -\leftedgedistance
       -\leftmarginwidth-\leftmargindistance\relax
     \ifdim\scratchdimen<\zeropoint
       \scratchdimen\zeropoint
     \fi
     \global\advance\makeupwidth\dimexpr
       -\rightmargindistance-\rightmarginwidth
       -\rightedgedistance  -\rightedgewidth
       -\scratchdimen\relax
   \else
     \global\makeupwidth\p_page_layouts_width\relax
     \ifzeropt\cutspace
       \global\cutspace\dimexpr\paperwidth-\makeupwidth-\backspace\relax
   % \else
       % A kind of inconsistent specification, but used
       % in for instance s-pre-19.tex; the cutspace is
       % used only for determining some kind of right
       % margin; don't use this in doublesided mode
     \fi
   \fi\fi
   \scratchdimen\layoutparameter\c!bottomspace\relax
  %\ifzeropt\scratchdimen
  %  \scratchdimen\topspace
  %\fi
   \global\bottomspace\layoutparameter\c!bottomspace\relax
   \global\layoutlines0\number\layoutparameter\c!lines\relax % may be empty
   \ifcase\layoutlines
     \edef\p_page_layouts_height{\layoutparameter\c!height}%
     \ifx\p_page_layouts_height\v!middle
       \ifzeropt\bottomspace
         \global\bottomspace\topspace
       \fi
       \global\makeupheight\dimexpr\paperheight-\topspace-\bottomspace\relax
     \else\ifx\p_page_layouts_height\v!fit
       \ifzeropt\bottomspace
         \global\bottomspace\topspace
       \fi
       \global\makeupheight\dimexpr\paperheight-\bottomspace\relax
       \scratchdimen\dimexpr\topspace-\topheight-\topdistance\relax
       \ifdim\scratchdimen<\zeropoint
         \scratchdimen\zeropoint
       \fi
       \global\advance\makeupheight\dimexpr-\bottomdistance-\bottomheight-\scratchdimen\relax
     \else
       \global\makeupheight\layoutparameter\c!height\relax
       \ifzeropt\bottomspace
         \global\bottomspace\dimexpr\paperheight-\makeupheight-\topspace\relax
     % \else
         % inconsistent specification
       \fi
     \fi\fi
   \else
     % beware, when the bodyfont changes (switched) this will change as well; implementing
     % a global lineheight is tricky: should we take the bodyfont interlinespace or the one set
     % independent of the bodyfont (before or after a layout spec); way too fuzzy, so we
     % stick to the current method (after a night of experimenting ...2003/10/13)
     \global\makeupheight\dimexpr
        \layoutparameter\c!lines\lineheight-\strutheight+\topskip+
        \headerdistance+\headerheight+\footerdistance+\footerheight\relax
   \fi
   \backoffset\layoutparameter\c!horoffset\relax
   \topoffset \layoutparameter\c!veroffset\relax
   \ifdim\makeupwidth<\onepoint
     \global\makeupwidth\onepoint
   \fi
   \ifdim\makeupheight<\onepoint
     \global\makeupheight\onepoint
   \fi
   % handy in page builder
   \global\totaltextwidth\dimexpr
      \leftedgetotal
     +\leftmargintotal
     +\makeupwidth
     +\rightmargintotal
     +\rightedgetotal
   \relax
   % \page_layouts_check_next % here ?
   \page_layouts_check_direction
   \page_layouts_calculate_extras
   \page_target_check_centering
   \calculatehsizes
   \calculatevsizes
   \page_layouts_check_pseudo_columns
   \page_backgrounds_recalculate}

\def\page_layouts_check_direction
  {\edef\p_direction{\layoutparameter\c!direction}%
   \ifx\p_direction\v!reverse
     \globalswapdimens\naturalleftedgedistance  \naturalrightedgedistance
     \globalswapdimens\naturalleftmargindistance\naturalrightmargindistance
     \globalswapdimens\leftedgedistance         \rightedgedistance
     \globalswapdimens\leftmargindistance       \rightmargindistance
     \globalswapdimens\leftmarginwidth          \rightmarginwidth
     \globalswapdimens\leftedgewidth            \rightedgewidth
     \globalswapdimens\backspace                \cutspace
     \expandafter\setsystemmode
   \else
     \expandafter\resetsystemmode
   \fi{reverselayout}}

\def\page_layouts_check_pseudo_columns
  {\global\layoutcolumns\layoutparameter\c!columns
   \global\layoutcolumndistance\layoutparameter\c!columndistance
   \global\layoutcolumnwidth\dimexpr\makeupwidth-\layoutcolumns\layoutcolumndistance+\layoutcolumndistance\relax
   \ifnum\layoutcolumns>\plusone
     \global\divide\layoutcolumnwidth\layoutcolumns
     \dorecurse\layoutcolumns\page_layouts_check_pseudo_column
   \fi}

\def\page_layouts_check_pseudo_column
  {\setxvalue{\??layoutcolumn\recurselevel}%
     {\the\numexpr\recurselevel-\plusone\relax\dimexpr\layoutcolumnwidth+\layoutcolumndistance\relax}}

\letvalue{\??layoutcolumn0}\zeropoint

\def\layoutcolumnoffset#1% can travel around so we can't use \lastnamedcs
  {\csname\??layoutcolumn\ifcsname\??layoutcolumn#1\endcsname#1\else0\fi\endcsname}

\def\page_layouts_synchronize_at_start
  {\ifdim\makeupheight=\layoutlines\lineheight \else % weird check
     \page_layouts_synchronize
   \fi}

\appendtoks
    \page_layouts_synchronize_at_start % still needed?
\to \everystarttext

% document:
%
% \setuplayout[odd][state=stop] \setuplayout[even][state=stop] \setuplayout[page]
%
% \startstandardmakeup[page=blank] ... \stopstandardmakeup

\ifdefined\lastpage \else \let\lastpage\!!plusone \fi

\def\page_layouts_change#1%
  {%\writestatus\m!layouts{changing to layout #1}%
   \xdef\currentlayout{#1}%
   \page_layouts_synchronize}

\let\changetolayout\page_layouts_change % also public

\def\v_real_page_normal {\the\realpageno}
\def\v_real_page_reverse{-\the\numexpr\lastpage-\realpageno\relax}

\def\v_real_page_odd_or_even
  {\ifodd\pagenoshift
     \ifodd\realpageno\v!even\else\v!odd \fi
   \else
     \ifodd\realpageno\v!odd \else\v!even\fi
   \fi}

\let\v_real_page_current\v!current

\def\v_real_page_named
  {\ifnum\lastpage=\realpageno
     \v!last
   \else\ifnum\plusone=\realpageno
     \v!first
   \else
     \__unknown__
   \fi\fi}

\let\v_page_layouts_pre_check\relax

\def\page_layouts_check_default_indeed#1%
  {\edef\m_page_check{#1}
   \edef\m_page_state{\namedlayoutparameter\m_page_check\c!state}%
   \ifx\m_page_state\v!start
     \glet\v_page_layouts_pre_check\currentlayout
     \glet\currentlayout\m_page_check
     \page_layouts_synchronize
   \else\ifx\m_page_state\v!repeat
     \glet\v_page_layouts_pre_check\relax
     \glet\currentlayout\m_page_check
     \page_layouts_synchronize
   \fi\fi}

\def\page_layouts_check_revert
  {\glet\currentlayout\v_page_layouts_pre_check
   \glet\v_page_layouts_pre_check\relax
   \page_layouts_synchronize}

\def\page_layouts_check_default
  {\ifcsname\namedlayouthash\v_real_page_normal\c!state\endcsname
     \page_layouts_check_default_indeed\v_real_page_normal
   \else\ifcsname\namedlayouthash\v_real_page_reverse\c!state\endcsname
     \page_layouts_check_default_indeed\v_real_page_reverse
   \else\ifcsname\namedlayouthash\v_real_page_named\c!state\endcsname
     \page_layouts_check_default_indeed\v_real_page_named
   \else\ifcsname\namedlayouthash\v_real_page_current\c!state\endcsname
     \page_layouts_check_default_indeed\v_real_page_current
   \else\ifcsname\namedlayouthash\v_real_page_odd_or_even\c!state\endcsname
     \page_layouts_check_default_indeed\v_real_page_odd_or_even
   \else\ifx\v_page_layouts_pre_check\relax
     % okay
   \else
     \page_layouts_check_revert
   \fi\fi\fi\fi\fi\fi}

\unexpanded\def\installlayoutmethod#1#2%
  {\setgvalue{\??layoutmethod#1}{#2}}

\installlayoutmethod\v!default{\page_layouts_check_default}
\installlayoutmethod\v!normal {\page_layouts_check_default}

% \def\page_layouts_check_next
%   {\csname\??layoutmethod\ifcsname\??layoutmethod\layoutparameter\c!method\endcsname
%      \layoutparameter\c!method
%    \else
%      \v!normal
%    \fi\endcsname}

\def\page_layouts_check_next
  {\ifcsname\??layoutmethod\layoutparameter\c!method\endcsname
     \lastnamedcs
   \else
     \page_layouts_check_default
   \fi}

\let\checkcurrentlayout\page_layouts_check_next % public and used in naw, so this synonym will stay

% inheritance
%
% \definelayout
%   [test]
%   [width=12cm,
%    height=10cm]
%
% \definelayout
%   [more]
%   [test]
%   [height=12cm]
%
% testcase
%
% \setuppagenumbering[alternative=doublesided]
%
% \setuplayout         [width=11cm]
% \definelayout [odd]  [backspace=1cm]
% \definelayout [even] [backspace=4cm]
% \definelayout [5]    [backspace=5cm]
% \definelayout [6]    [backspace=5cm]
% \definelayout [-2]   [backspace=0cm,cutspace=0cm]
% \definelayout [last] [backspace=0cm,cutspace=0cm]
%
% \checkcurrentlayout \showframe
%
% \starttext
%     \dorecurse{20} {\input knuth \endgraf \input tufte \endgraf}
% \stoptext

% Because we want to keep the set parameters as they are we use some
% helpers to communicate between the several page building related
% mechanism.

\appendtoks \page_layouts_check_next \to \everystarttext
\appendtoks \page_layouts_check_next \to \everyaftershipout

\newconditional\c_page_layouts_location_is_set
\newconditional\c_page_layouts_location_is_middle

\def\page_layouts_location_reset % we start in the left top and mirror right pages
  {\setfalse\c_page_layouts_location_is_set
   \setfalse\c_page_layouts_location_is_middle
   \let\v_page_target_left_fill  \relax
   \let\v_page_target_right_fill \hss % ? \relax
   \let\v_page_target_top_fill   \relax
   \let\v_page_target_bottom_fill\vss} % \relax}

\setvalue{\??layoutlocation\v!right      }{\settrue\c_page_layouts_location_is_set
                                           \setfalse\c_page_layouts_location_is_middle
                                           \let\v_page_target_left_fill  \hss
                                           \let\v_page_target_right_fill \relax}
\setvalue{\??layoutlocation\v!left       }{\settrue\c_page_layouts_location_is_set
                                           \setfalse\c_page_layouts_location_is_middle
                                           \let\v_page_target_left_fill  \relax
                                           \let\v_page_target_right_fill \hss}
\setvalue{\??layoutlocation\v!bottom     }{\settrue\c_page_layouts_location_is_set
                                           \setfalse\c_page_layouts_location_is_middle
                                           \let\v_page_target_top_fill   \vss
                                           \let\v_page_target_bottom_fill\relax}
\setvalue{\??layoutlocation\v!top        }{\settrue\c_page_layouts_location_is_set
                                           \setfalse\c_page_layouts_location_is_middle
                                           \let\v_page_target_top_fill   \relax
                                           \let\v_page_target_bottom_fill\vss}
\setvalue{\??layoutlocation\v!middle     }{\settrue\c_page_layouts_location_is_set
                                           \settrue\c_page_layouts_location_is_middle
                                           \let\v_page_target_left_fill  \hss
                                           \let\v_page_target_right_fill \hss
                                           \let\v_page_target_top_fill   \vss
                                           \let\v_page_target_bottom_fill\vss}
\setvalue{\??layoutlocation\empty        }{\setfalse\c_page_layouts_location_is_set % default also signal to scrn_
                                           \setfalse\c_page_layouts_location_is_middle
                                           \let\v_page_target_right_fill \hss
                                           \let\v_page_target_bottom_fill\hss}
\setvalue{\??layoutlocation\v!doublesided}{\settrue \c_page_target_print_doublesided}
\setvalue{\??layoutlocation\v!singlesided}{\setfalse\c_page_target_print_doublesided}

\def\page_target_check_centering_indeed#1%
 % {\ifcsname\??layoutlocation#1\endcsname\csname\??layoutlocation#1\endcsname\fi}
  {\begincsname\??layoutlocation#1\endcsname}

\unexpanded\def\page_target_check_centering
  {\setfalse\c_page_target_print_doublesided
   \page_layouts_location_reset
   \processcommacommand[\layoutparameter\c!location]\page_target_check_centering_indeed}

% installers

\def\installlayoutalternative#1#2%
  {\setgvalue{\??layoutalternative#1}{#2}}

\def\page_boxes_construct_content_default#1#2#3% targetbox flusher box
  {\setbox#1\vpack % was \vbox
     {\offinterlineskip
      \begingroup % needed ?
      \uselayoutstyleandcolor\c!style\c!color
      \offinterlineskip
      \page_layouts_insert_elements % zero size
      \endgroup
      \page_insert_body#2#3}}% including footnotes

\installlayoutalternative\v!default{\page_boxes_construct_content_default}
\installlayoutalternative\v!normal {\page_boxes_construct_content_default}

% \def\page_boxes_construct_content % targetbox flusher box
%   {\csname\??layoutalternative\ifcsname\??layoutalternative\layoutparameter\c!alternative\endcsname
%      \layoutparameter\c!alternative
%    \else
%      \v!normal
%    \fi\endcsname}

\def\page_boxes_construct_content % targetbox flusher box
  {\ifcsname\??layoutalternative\layoutparameter\c!alternative\endcsname
     \expandafter\lastnamedcs
   \else
     \expandafter\page_boxes_construct_content_default
   \fi}

%D \macros
%D   {adaptlayout}

\installcorenamespace{adaptlayout}
\installcorenamespace{pageadaptations}

\installsetuponlycommandhandler \??adaptlayout {adaptlayout}

\newdimen\d_page_adepts_pushed_text_height
\newdimen\d_page_adepts_pushed_footer_height
\newdimen\d_page_adepts_height
\newdimen\d_page_adapts_delta

\unexpanded\def\adaptlayout
  {\dodoubleempty\page_adapts_layout}

\def\page_adapts_layout[#1][#2]%
  {\ifsecondargument
     \processcommalist[#1]{\page_adapts_layout_register{#2}}%
     \page_adapts_check
   \else
     \page_adapts_layout_indeed{#1}%
   \fi}

\def\page_adapts_layout_register#1#2%
  {\setgvalue{\??pageadaptations#2}{\page_adapts_layout_indeed{#1}}}

\let\p_adapts_height\zeropoint
\let\p_adapts_lines \zerocount

\def\page_adapts_layout_indeed#1%
  {\setupcurrentadaptlayout[\c!height=\zeropoint,\c!lines=\zerocount,#1]%
   \page_adepts_push
   \edef\p_adapts_height{\adaptlayoutparameter\c!height}%
   \edef\p_adapts_lines {\adaptlayoutparameter\c!lines}%
   \ifx\p_adapts_height\v!max
     \global\d_page_adepts_height\footerheight
   \else
     \global\d_page_adepts_height\dimexpr
        \ifnum\p_adapts_lines=\zerocount
          \p_adapts_height
        \else
          \p_adapts_lines\openlineheight
        \fi
      \relax
      \ifdim\d_page_adepts_height>\footerheight
        \global\d_page_adepts_height\footerheight
      \fi
   \fi
   \global\advance\textheight   \d_page_adepts_height
   \global\advance\footerheight-\d_page_adepts_height
   \showmessage\m!layouts1{\the\d_page_adepts_height,\the\realpageno}%
   % this will become a better one (do we need insert correction?)
   \page_otr_command_set_vsize
   %
   \page_backgrounds_recalculate
   \glet\page_adepts_push\relax
   \glet\page_adepts_pop\page_adepts_pop_indeed}

% \def\page_adapts_check
%   {\csname\??pageadaptations\the\ifcsname\??pageadaptations\the\realpageno\endcsname\realpageno\else\zerocount\fi\endcsname}
%
% \def\page_adapts_reset
%   {\ifcsname\??pageadaptations\the\realpageno\endcsname
%      \global\undefinevalue{\??pageadaptations\the\realpageno}%
%    \fi}

\def\page_adapts_check
  {\begincsname\??pageadaptations\the\realpageno\endcsname}

\def\page_adapts_reset
  {\ifcsname\??pageadaptations\the\realpageno\endcsname
     \expandafter\glet\csname\??pageadaptations\the\realpageno\endcsname\relax
   \fi}

\def\page_adepts_push_indeed
  {\global\d_page_adepts_pushed_text_height  \textheight
   \global\d_page_adepts_pushed_footer_height\footerheight}

\def\page_adepts_pop_indeed
  {\global\textheight  \d_page_adepts_pushed_text_height
   \global\footerheight\d_page_adepts_pushed_footer_height
   \page_layouts_synchronize
   \glet\page_adepts_push\page_adepts_push_indeed
   \glet\page_adepts_pop\relax}

\appendtoks \page_adapts_check \to \everystarttext
\appendtoks \page_adapts_reset \to \everyshipout

\let\page_adepts_pop \relax
\let\page_adepts_push\page_adepts_push_indeed

\unexpanded\def\page_adapts_synchronize % used elsewhere
  {\page_adepts_pop
   \page_adapts_check}

\def\page_adapts_status_info % used elsewhere
  {\ifx\page_adepts_pop\relax \else
     \space(adept: \the\d_page_adepts_height)\space
   \fi
   \the\realpageno}

%D \macros
%D   {startlayout,stoplayout}

\unexpanded\def\startlayout[#1]%
  {\page
   \globalpushmacro\currentlayout
   \doifelselayoutdefined{#1}{\setuplayout[#1]}\donothing} % {\setuplayout[\currentlayout]}}

\unexpanded\def\stoplayout
  {\page
   \globalpopmacro\currentlayout
   \setuplayout[\currentlayout]}

% NOG EENS NAGAAN WANNEER NU GLOBAL EN WANNEER NIET

\ifx\doifelselayoutsomeline\undefined % defined in page-txt
    \let\doifelselayoutsomeline\secondofthreearguments
\fi

\def\compensatevsizeheader             {\advance\textheight-\dimexpr\headerheight+\headerdistance\relax}
\def\compensatevsizefooter             {\advance\textheight-\dimexpr\footerheight+\footerdistance\relax}
\def\globalcompensatevsizeheader{\global\advance\textheight-\dimexpr\headerheight+\headerdistance\relax}
\def\globalcompensatevsizefooter{\global\advance\textheight-\dimexpr\footerheight+\footerdistance\relax}

\def\compensatevsizeheaderzero{\headerheight\zeropoint\page_layouts_set_distances}
\def\compensatevsizefooterzero{\footerheight\zeropoint\page_layouts_set_distances}

\def\page_layouts_set_modes
  {\ifzeropt\headerheight
     \resetsystemmode\v!header
   \else
     \setsystemmode\v!header
   \fi
   \ifzeropt\footerheight
     \resetsystemmode\v!footer
   \else
     \setsystemmode\v!footer
   \fi}

\unexpanded\def\calculatevsizes % name will change
  {\textheight\makeupheight
   \doifelselayoutsomeline\v!header\compensatevsizeheader\donothing
   \doifelselayoutsomeline\v!footer\compensatevsizefooter\donothing
   \page_layouts_set_modes
   \resetglobal
   \page_otr_command_set_vsize}

\unexpanded\def\calculateglobalvsizes % name will change
  {\global\textheight\makeupheight
   \doifelselayoutsomeline\v!header\globalcompensatevsizeheader\donothing
   \doifelselayoutsomeline\v!footer\globalcompensatevsizefooter\donothing
   \page_layouts_set_modes
   \page_otr_command_set_vsize}

\unexpanded\def\calculatereducedvsizes % name will change
  {\textheight\makeupheight
   \doifelselayoutsomeline\v!header\compensatevsizeheader\compensatevsizeheaderzero
   \doifelselayoutsomeline\v!footer\compensatevsizefooter\compensatevsizefooterzero}

\newdimen\innermakeupwidth  % special purpose
\newdimen\innermakeupmargin % special purpose

\newconditional\innermakeupcompensation \settrue\innermakeupcompensation

\def\compensatedinnermakeupmargin
  {\dimexpr\ifconditional\innermakeupcompensation+\innermakeupmargin\else\zeropoint\fi\relax}

\unexpanded\def\freezetextwidth % name will change % \makeupwidth may be set to \textwidth
  {\textwidth\makeupwidth                          % which is a tricky but valid value
   \edef\m_currentlayout_text_width {\layoutparameter\c!textwidth }%
   \edef\m_currentlayout_text_margin{\layoutparameter\c!textmargin}%
   \ifx\m_currentlayout_text_width\empty \else
     \textwidth\m_currentlayout_text_width % local
   \fi
   \global\innermakeupwidth\textwidth
   \ifx\m_currentlayout_text_margin\empty
     \global\innermakeupmargin\zeropoint
   \else
     \global\innermakeupmargin\m_currentlayout_text_margin\relax
   \fi
   \scratchdimen\dimexpr\innermakeupmargin+\innermakeupmargin\relax
   \global\advance\innermakeupwidth-\scratchdimen
   \advance\textwidth-\scratchdimen}   % local

\unexpanded\def\calculatehsizes % name will change
  {\freezetextwidth
   \page_otr_command_set_hsize}

%D When we start at an even page, we need to swap the layout differently. We cannot
%D adapt the real page number, since it is used in cross referencing. The next
%D switch is set when we start at an even page.

% #single #left #right

\def\doifelseoddpage
  {\ifodd\pagenoshift
     \expandafter\page_layouts_if_odd_else_yes
   \else
     \expandafter\page_layouts_if_odd_else_nop
   \fi}

\let\doifoddpageelse\doifelseoddpage

\def\page_layouts_if_odd_else_yes
  {\ifodd\realpageno
     \expandafter\secondoftwoarguments
   \else
     \expandafter\firstoftwoarguments
   \fi}

\def\page_layouts_if_odd_else_nop
  {\ifodd\realpageno
     \expandafter\firstoftwoarguments
   \else
     \expandafter\secondoftwoarguments
   \fi}

\def\page_layouts_if_odd_else_again#1{\doifelseoddpage}

\def\doifbothsidesoverruled
  {\ifdoublesided
     \expandafter\page_layouts_if_odd_else_again
   \else
     \expandafter\firstofthreearguments
   \fi}

\def\doifbothsides% #1 #2 #3
  {\ifdoublesided
     \expandafter\page_layouts_if_both_sides
   \else
     \expandafter\firstofthreearguments
   \fi}

\def\page_layouts_if_both_sides
  {\ifsinglesided
     \expandafter\firstofthreearguments
   \else
     \expandafter\page_layouts_if_odd_else_again
   \fi}

\newdimen\texthoffset

\def\settexthoffset % name will change
  {\texthoffset\doifbothsides\backspace\backspace{\dimexpr\paperwidth-\backspace-\makeupwidth\relax}}

% The next hack is too tricky as we may shipout more pages:
%
% \def\freezepagestatechecks
%   {\the\everyfreezepagestatechecks}
%
% \newtoks \everyfreezepagestatechecks
%
% \appendtoks
%     \doifbothsides
%       {\let\doifbothsides\firstofthreearguments}%
%       {\let\doifbothsides\secondofthreearguments}%
%       {\let\doifbothsides\thirdofthreearguments}%
%     \rightorleftpageaction
%       {\let\rightorleftpageaction\firstoftwoarguments}%
%       {\let\rightorleftpageaction\secondoftwoarguments}%
%     \doifmarginswapelse
%       {\let\doifmarginswapelse\firstoftwoarguments}%
%       {\let\doifmarginswapelse\secondoftwoarguments}%
% \to \everyfreezepagestatechecks
%
% \prependtoks
%     \freezepagestatechecks
% \to \everybeforeshipout

\def\goleftonpage % name will change (we could cache)
  {\hkern-\dimexpr\leftmargindistance+\leftmarginwidth+\leftedgedistance+\leftedgewidth\relax}

\def\doifelsemarginswap#1#2%
  {\doifbothsides{#1}{#1}{#2}}

\let\doifmarginswapelse\doifelsemarginswap

\def\swapmargins % name will change
  {\doifelsemarginswap\relax\doswapmargins}

\def\doswapmargins % name will change
  {\let\swapmargins  \relax % to prevent local swapping
   \let\doswapmargins\relax % to prevent local swapping
   \the\everyswapmargins}

\def\rightorleftpageaction
  {\ifdoublesided
     \expandafter\page_layouts_right_or_left_page_action
   \else
     \expandafter\firstoftwoarguments
   \fi}

\def\page_layouts_right_or_left_page_action
  {\ifsinglesided
     \expandafter\firstoftwoarguments
   \else
     \expandafter\doifelseoddpage
   \fi}

\def\outermarginwidth   {\rightorleftpageaction\rightmarginwidth   \leftmarginwidth }
\def\innermarginwidth   {\rightorleftpageaction\leftmarginwidth    \rightmarginwidth}
\def\outermargindistance{\rightorleftpageaction\rightmargindistance\leftmargindistance }
\def\innermargindistance{\rightorleftpageaction\leftmargindistance \rightmargindistance}

\def\outeredgewidth     {\rightorleftpageaction\rightedgewidth   \leftedgewidth }
\def\inneredgewidth     {\rightorleftpageaction\leftedgewidth    \rightedgewidth}
\def\outeredgedistance  {\rightorleftpageaction\rightedgedistance\leftedgedistance }
\def\inneredgedistance  {\rightorleftpageaction\leftedgedistance \rightedgedistance}

\def\outerspacewidth    {\rightorleftpageaction\cutspace \backspace}
\def\innerspacewidth    {\rightorleftpageaction\backspace\cutspace }

\def\leftmargintotal    {\dimexpr\leftmarginwidth +\leftmargindistance \relax}
\def\rightmargintotal   {\dimexpr\rightmarginwidth+\rightmargindistance\relax}
\def\leftedgetotal      {\dimexpr\leftedgewidth   +\leftedgedistance   \relax}
\def\rightedgetotal     {\dimexpr\rightedgewidth  +\rightedgedistance  \relax}

\def\leftsidetotal      {\dimexpr\leftmarginwidth +\leftedgetotal \relax}
\def\rightsidetotal     {\dimexpr\rightmarginwidth+\rightedgetotal\relax}
\def\leftcombitotal     {\dimexpr\leftmargintotal +\leftedgetotal \relax}
\def\rightcombitotal    {\dimexpr\rightmargintotal+\rightedgetotal\relax}

\def\innermargintotal   {\dimexpr\innermarginwidth+\innermargindistance\relax}
\def\outermargintotal   {\dimexpr\outermarginwidth+\outermargindistance\relax}
\def\inneredgetotal     {\dimexpr\inneredgewidth  +\inneredgedistance  \relax}
\def\outeredgetotal     {\dimexpr\outeredgewidth  +\outeredgedistance  \relax}

\def\innercombitotal    {\dimexpr\innermargintotal+\inneredgetotal\relax}
\def\outercombitotal    {\dimexpr\outermargintotal+\outeredgetotal\relax}
\def\innersidetotal     {\dimexpr\innermarginwidth+\inneredgetotal\relax}
\def\outersidetotal     {\dimexpr\outermarginwidth+\outeredgetotal\relax}

%D \macros
%D   {startlocallayout}
%D
%D These macros should be used with care. They permit local layouts (as used in
%D fitting pages, see \type {page-app.tex}). This is kind of obsolete now that we
%D have \type {\definelayout}, so this hack will disappear in future versions.

\unexpanded\def\startlocallayout
  {\globalpushmacro\page_paper_restore
   \globalpushmacro\currentlayout}

\unexpanded\def\stoplocallayout
  {\globalpopmacro\currentlayout
   \globalpopmacro\page_paper_restore
   \page_paper_restore
   \setuplayout[\currentlayout]\relax} % explicit !

%D \macros
%D   {showprint, showframe, showlayout, showsetups}
%D
%D We predefine a couple of tracing macros.
%D
%D \showsetup{showprint}
%D \showsetup{showframe}
%D \showsetup{showlayout}
%D \showsetup{showsetups}
%D %showsetup{showmargins}
%D %showsetup{showgrid}
%D %showsetup{showusage}

\fetchruntimecommand \showprint   \f!page_run
\fetchruntimecommand \showframe   \f!page_run
\fetchruntimecommand \showlayout  \f!page_run
\fetchruntimecommand \showsetups  \f!page_run
\fetchruntimecommand \showmargins \f!page_run
\fetchruntimecommand \showgrid    \f!page_run
\fetchruntimecommand \showusage   \f!page_run

\glet\page_grids_add_to_box\gobbleoneargument
\glet\page_grids_add_to_one\gobbleoneargument
\glet\page_grids_add_to_mix\gobbleoneargument

%D The default dimensions are quite old and will not change. The funny fractions
%D were introduced when we went from fixed dimensions to relative ones. Since
%D \CONTEXT\ is a dutch package, the dimensions are based on the metric system. The
%D asymmetrical layout is kind of handy for short quick||and||dirty stapled
%D documents.
%D
%D Although valid, it is not a real good idea to use dimensions based on the \type
%D {em} unit. First of all, since there are no fonts loaded yet, this dimension
%D makes no sense, and second, you would loose track of values, since they could
%D change while going to a new page, depending on the current font setting.

\setuplayout
  [             \c!topspace=.08417508418\paperheight,  %  2.5cm
                     \c!top=\zeropoint,
             \c!topdistance=\zeropoint,
                  \c!header=.06734006734\paperheight,  %  2.0cm
          \c!headerdistance=\zeropoint,
                  \c!height=.84175084175\paperheight,  % 25.0cm
          \c!footerdistance=\layoutparameter\c!headerdistance,
                  \c!footer=.06734006734\paperheight,  %  2.0cm
          \c!bottomdistance=\layoutparameter\c!topdistance,
                  \c!bottom=\zeropoint,
               \c!backspace=.11904761905\paperwidth, %  2.5cm
                    \c!edge=\zeropoint,
            \c!edgedistance=\layoutparameter\c!margindistance,
                  \c!margin=.12649983170\paperwidth, %  snijwit-2*afstand
          \c!margindistance=.02008341748\paperwidth, %  12.0pt
                \c!leftedge=\layoutparameter\c!edge,
        \c!leftedgedistance=\layoutparameter\c!edgedistance,
              \c!leftmargin=\layoutparameter\c!margin,
      \c!leftmargindistance=\layoutparameter\c!margindistance,
                   \c!width=.71428571429\paperwidth, %  15.0cm \dimexpr\
     \c!rightmargindistance=\layoutparameter\c!margindistance,
             \c!rightmargin=\layoutparameter\c!margin,
       \c!rightedgedistance=\layoutparameter\c!edgedistance,
               \c!rightedge=\layoutparameter\c!edge,
               \c!veroffset=\zeropoint,
             \c!bottomspace=\zeropoint,
               \c!horoffset=\zeropoint,
                \c!cutspace=\zeropoint,
               \c!textwidth=, % dangerous option -> centered / local
              \c!textmargin=, % dangerous option -> both sides
            \c!textdistance=\zeropoint, % shift down on grid
                   \c!style=,
                   \c!color=,
                 \c!marking=\v!off,
                \c!location=,% \v!singlesided, but unset is signal (no other default, spoils arrange)
                   \c!state=\v!start,
                   \c!scale=1,
                      \c!sx=1,
                      \c!sy=1,
                      \c!nx=1,
                      \c!ny=1,
                      \c!dx=\zeropoint,
                      \c!dy=\zeropoint,
                    \c!grid=\v!no,
               \c!direction=\v!normal,
                  \c!preset=,
                  \c!setups=\systemsetupsprefix\s!default,
              \c!clipoffset=\zeropoint,
                   \c!lines=0,
                   \c!paper=, % for foxet
                    \c!page=, % for foxet
                 \c!columns=\plusone,
          \c!columndistance=\zeropoint]

%D First we define a whole range of (DIN) papersizes, of which the A-series makes
%D most sense. We enable checking.

\definepapersize [A0]  [\c!width=841mm,\c!height=1189mm]
\definepapersize [A1]  [\c!width=594mm,\c!height=841mm]
\definepapersize [A2]  [\c!width=420mm,\c!height=594mm]
\definepapersize [A3]  [\c!width=297mm,\c!height=420mm]
\definepapersize [A4]  [\c!width=210mm,\c!height=297mm]
\definepapersize [A5]  [\c!width=148mm,\c!height=210mm]
\definepapersize [A6]  [\c!width=105mm,\c!height=148mm]
\definepapersize [A7]  [\c!width=74mm,\c!height=105mm]
\definepapersize [A8]  [\c!width=52mm,\c!height=74mm]
\definepapersize [A9]  [\c!width=37mm,\c!height=52mm]
\definepapersize [A10] [\c!width=26mm,\c!height=37mm]

\definepapersize [A4/2][\c!width=\dimexpr297mm/2\relax,\c!height=210mm] % 148.5mm
%definepapersize [2A5] [\c!width=296mm,\c!height=210mm] % doublewide

\definepapersize [B0]  [\c!width=1000mm,\c!height=1414mm]
\definepapersize [B1]  [\c!width=707mm,\c!height=1000mm]
\definepapersize [B2]  [\c!width=500mm,\c!height=707mm]
\definepapersize [B3]  [\c!width=353mm,\c!height=500mm] % [\c!width=354mm,\c!height=500mm]
\definepapersize [B4]  [\c!width=250mm,\c!height=353mm] % [\c!width=250mm,\c!height=354mm]
\definepapersize [B5]  [\c!width=176mm,\c!height=250mm] % [\c!width=177mm,\c!height=250mm]
\definepapersize [B6]  [\c!width=125mm,\c!height=176mm] % [\c!width=125mm,\c!height=177mm]
\definepapersize [B7]  [\c!width=88mm,\c!height=125mm]
\definepapersize [B8]  [\c!width=62mm,\c!height=88mm]   % [\c!width=63mm,\c!height=88mm]
\definepapersize [B9]  [\c!width=44mm,\c!height=62mm]   % [\c!width=44mm,\c!height=63mm]
\definepapersize [B10] [\c!width=31mm,\c!height=44mm]

\definepapersize [C0]  [\c!width=917mm,\c!height=1297mm]
\definepapersize [C1]  [\c!width=648mm,\c!height=917mm] % [\c!width=649mm,\c!height=917mm]
\definepapersize [C2]  [\c!width=458mm,\c!height=648mm] % [\c!width=459mm,\c!height=649mm]
\definepapersize [C3]  [\c!width=324mm,\c!height=458mm] % [\c!width=324mm,\c!height=459mm]
\definepapersize [C4]  [\c!width=229mm,\c!height=324mm]
\definepapersize [C5]  [\c!width=162mm,\c!height=229mm]
\definepapersize [C6]  [\c!width=114mm,\c!height=162mm] % [\c!width=115mm,\c!height=162mm]
\definepapersize [C7]  [\c!width=81mm,\c!height=114mm]  % [\c!width=81mm,\c!height=115mm]
\definepapersize [C8]  [\c!width=57mm,\c!height=81mm]
\definepapersize [C9]  [\c!width=40mm,\c!height=57mm]
\definepapersize [C10] [\c!width=28mm,\c!height=40mm]

%D Per August 2004 the rounding of some (seldom used) sizes were corrected top the
%D latest DIN specifications. Peter Rolf came up with these and a few more missing
%D sizes. Watch out: spaces and slashes!

\definepapersize [4 A0]  [\c!width=1682mm,\c!height=2378mm]
\definepapersize [2 A0]  [\c!width=1189mm,\c!height=1682mm]
\definepapersize [C6/C5] [\c!width=114mm,\c!height=229mm]

%D Because there are no standardized screen sizes, we define a bunch of sizes with
%D $4:3$ ratios. The \type {S6} size is nearly as wide as a sheet of \type {A4}
%D paper.

\definepapersize [S3]  [\c!width=300pt,\c!height=225pt]
\definepapersize [S4]  [\c!width=400pt,\c!height=300pt]
\definepapersize [S5]  [\c!width=500pt,\c!height=375pt]
\definepapersize [S6]  [\c!width=600pt,\c!height=450pt]
\definepapersize [S8]  [\c!width=800pt,\c!height=600pt]
\definepapersize [SL]  [\c!width=640pt,\c!height=400pt] % low
\definepapersize [SM]  [\c!width=720pt,\c!height=450pt] % medium
\definepapersize [SW]  [\c!width=800pt,\c!height=450pt] % wide
\definepapersize [HD]  [\c!width=1920pt,\c!height=1080pt]
\definepapersize [HD+] [\c!width=1920pt,\c!height=1200pt]
\definepapersize [HD-] [\c!width=960pt,\c!height=540pt]

%D These are handy too:

\definepapersize [S33] [\c!width=300pt,\c!height=300pt]
\definepapersize [S44] [\c!width=400pt,\c!height=400pt]
\definepapersize [S55] [\c!width=500pt,\c!height=500pt]
\definepapersize [S66] [\c!width=600pt,\c!height=600pt]

%D One may wonder if \TEX\ should be used for typesetting \CDROM\ covers, but it
%D does not hurt to have the paper size ready.

\definepapersize [CD] [\c!width=120mm,\c!height=120mm]

%D The next series is for our English speaking friends who decided to stick to non
%D metric values. Thanks to Nelson Beebe for completing the inch based list.

\definepapersize [letter]    [\c!width=8.5in,\c!height=11in]
\definepapersize [ledger]    [\c!width=11in,\c!height=17in]
\definepapersize [tabloid]   [\c!width=17in,\c!height=11in]

\definepapersize [legal]     [\c!width=8.5in,\c!height=14in]
\definepapersize [folio]     [\c!width=8.5in,\c!height=13in]
\definepapersize [executive] [\c!width=7.25in,\c!height=10.5in]

\definepapersize [A] [\c!width=8.5in,\c!height=11in] % 1 sheet
\definepapersize [B] [\c!width=11in,\c!height=17in]  % 2 sheets
\definepapersize [C] [\c!width=17in,\c!height=22in]  % 4 sheets

%D The next set is for Tobias Burnus, who gave me the sizes.

\definepapersize [envelope 9]  [\c!width=8.88in,\c!height=3.88in]
\definepapersize [envelope 10] [\c!width=9.5in,\c!height=4.13in]
\definepapersize [envelope 11] [\c!width=10.38in,\c!height=4.5in]
\definepapersize [envelope 12] [\c!width=11.0in,\c!height=4.75in]
\definepapersize [envelope 14] [\c!width=11.5in,\c!height=5.0in]
\definepapersize [monarch]     [\c!width=7.5in,\c!height=3.88in]
\definepapersize [check]       [\c!width=8.58in,\c!height=3.88in]
\definepapersize [DL]          [\c!width=110mm,\c!height=220mm] % [\c!width=220mm,\c!height=110mm]
\definepapersize [E4]          [\c!width=280mm,\c!height=400mm]

%D The next three sets are supplied by Taco:

\definepapersize [RA0]  [\c!width=860mm,\c!height=1220mm]
\definepapersize [RA1]  [\c!width=610mm,\c!height=860mm]
\definepapersize [RA2]  [\c!width=430mm,\c!height=610mm]
\definepapersize [RA3]  [\c!width=305mm,\c!height=430mm]
\definepapersize [RA4]  [\c!width=215mm,\c!height=305mm]

%D ISO SRA (supplementary raw A) sizes:

\definepapersize [SRA0]  [\c!width=900mm,\c!height=1280mm]
\definepapersize [SRA1]  [\c!width=640mm,\c!height=900mm]
\definepapersize [SRA2]  [\c!width=450mm,\c!height=640mm]
\definepapersize [SRA3]  [\c!width=320mm,\c!height=450mm]
\definepapersize [SRA4]  [\c!width=225mm,\c!height=320mm]

%D Swedish thesis formats:

\definepapersize [G5]  [\c!width=169mm,\c!height=239mm]
\definepapersize [E5]  [\c!width=155mm,\c!height=220mm]

%D Industry invention:

\definepapersize [A3plus] [\c!width=329mm,\c!height=483mm]

%D For Alan:

\definepapersize [business]   [\c!width=85mm,\c!height=55mm]
\definepapersize [businessUS] [\c!width=3.5in,\c!height=2in]

%D We can now default to a reasonable size. We match the print paper size with the
%D typeset paper size. This setting should come after the first layout specification
%D (already done).

% \definepapersize
%   [\v!default]
%   [ \c!width=\paperwidth,
%    \c!height=\paperheight]

% \definepapersize
%   [samesized]
%   [ \c!width=\paperwidth,
%    \c!height=\paperheight]

\setuppapersize
  [\c!distance=1.5cm] % offset is already taken

\definepapersize
  [oversized]
  [ \c!width=\dimexpr\paperwidth +\layouttargetparameter\c!distance\relax,
   \c!height=\dimexpr\paperheight+\layouttargetparameter\c!distance\relax]

\definepapersize
  [undersized]
  [ \c!width=\dimexpr\paperwidth -\layouttargetparameter\c!distance\relax,
   \c!height=\dimexpr\paperheight-\layouttargetparameter\c!distance\relax]

\definepapersize
  [doublesized]
  [ \c!width=\dimexpr \paperwidth \relax,
   \c!height=\dimexpr2\paperheight\relax]

\definepapersize
  [doubleoversized]
  [ \c!width=\dimexpr \paperwidth +\layouttargetparameter\c!distance\relax,
   \c!height=\dimexpr2\paperheight+\layouttargetparameter\c!distance\relax]

\definepapersize
  [doublewide]
  [ \c!width=\dimexpr2\paperwidth \relax,
   \c!height=\dimexpr \paperheight\relax]

% \setuppapersize
%   [A4][A4]

\setuppapersize
  [A4] % [samesized]

%D A few goodies, first a full page layout:

\definelayout
  [\v!page]

\setuplayout
  [\v!page]
  [\c!backspace=\zeropoint,
   \c!cutspace=\zeropoint,
   \c!topspace=\zeropoint,
   \c!bottomspace=\zeropoint,
   \c!margin=\zeropoint,
   \c!edge=\zeropoint,
   \c!header=\zeropoint,
   \c!footer=\zeropoint,
   \c!top=\zeropoint,
   \c!bottom=\zeropoint,
   \c!leftmargin=\zeropoint,
   \c!rightmargin=\zeropoint,
   \c!leftedge=\zeropoint,
   \c!rightedge=\zeropoint,
   \c!textdistance=\zeropoint,
   \c!width=\v!middle,
   \c!height=\v!middle,
   \c!lines=0,
   \c!grid=\v!no]

%D A quick and dirty one:

\definelayout
  [\v!middle]
  [\c!width=\v!middle,
   \c!height=\v!middle]

%D One for testing examples (5mm is often the non printable area):

\definelayout
  [\v!tight]

\definelayout
  [\v!tight]
  [\v!page]
  [\c!backspace=5mm,
   \c!cutspace=5mm,
   \c!topspace=5mm,
   \c!bottomspace=5mm]

\protect \endinput