%D \module
%D   [       file=page-box,
%D        version=2011.12.05, % moved from other page-* files
%D          title=\CONTEXT\ Page Macros,
%D       subtitle=Page Boxing,
%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 / Boxing}

\unprotect

%D The often two step approach (_indeed) saves skipping tokens
%D which is nicer for tracing.

%D Centering the paper area on the print area is determined
%D by the \type {top}, \type {bottom}, \type {left} and \type
%D {right} parameters.

\def\page_boxes_apply_center#box% we could test for a difference (saves packing)
  {\printpaperwidth \v_page_target_scale\printpaperwidth \relax
   \printpaperheight\v_page_target_scale\printpaperheight\relax
   \ifdim\printpaperheight>\ht#box\relax
     \page_boxes_apply_center_indeed#box%
   \else\ifdim\printpaperwidth>\wd#box\relax
     \page_boxes_apply_center_indeed#box%
   \fi\fi}

\def\page_boxes_apply_center_indeed_l_r#box%
  {\v_page_target_left
   \v_page_target_left_fill
   \box#box%
   \v_page_target_right_fill
   \v_page_target_right}

\def\page_boxes_apply_center_indeed_r_l#box%
  {\v_page_target_right
   \v_page_target_right_fill
   \box#box%
   \v_page_target_left_fill
   \v_page_target_left}

\def\page_boxes_apply_center_indeed#box% we could test for a difference (saves packing)
  {\setbox#box\vpack to \printpaperheight
     {\v_page_target_top
      \v_page_target_top_fill
      \hpack to \printpaperwidth
        {\ifconditional\c_page_target_print_doublesided
           \doifbothsides
             {\page_boxes_apply_center_indeed_l_r#box}%
             {\page_boxes_apply_center_indeed_l_r#box}%
             {\page_boxes_apply_center_indeed_r_l#box}%
         \else
              \page_boxes_apply_center_indeed_l_r#box%
         \fi}%
      \par
      \v_page_target_bottom_fill
      \v_page_target_bottom}}

\def\page_boxes_apply_offset % #box
  {\ifzeropt\topoffset
     \ifzeropt\backoffset
       \doubleexpandafter\gobbleoneargument
     \else
       \doubleexpandafter\page_boxes_apply_offset_indeed
     \fi
   \else
     \expandafter\page_boxes_apply_offset_indeed
   \fi}

\def\page_boxes_apply_offset_indeed#box%
  {\scratchwidth \wd#box%
   \scratchheight\ht#box%
   \scratchdepth \dp#box%
   \setbox#box\vpack
     {\offinterlineskip
      \vskip\topoffset
      \hskip\doifbothsides\backoffset\backoffset{-\backoffset}%
      \box#box}%
   \wd#box\scratchwidth
   \ht#box\scratchheight
   \dp#box\scratchdepth}

\def\page_boxes_apply_replicate
  {\ifnum\layoutparameter\c!nx>\plusone
     \expandafter\page_boxes_apply_replicate_indeed
   \else\ifnum\layoutparameter\c!ny>\plusone
     \doubleexpandafter\page_boxes_apply_replicate_indeed
   \else
     \doubleexpandafter\gobbleoneargument
   \fi\fi}

\def\page_boxes_apply_replicate_indeed#box%
  {\setbox#box\vpack
     {\offinterlineskip
      \dorecurse{\layoutparameter\c!ny}
        {\hpack{\dorecurse{\layoutparameter\c!nx}{\copy#box\kern\layoutparameter\c!dx}\unskip}%
         \vskip\layoutparameter\c!dy}
      \unskip}}

\def\page_boxes_apply_orientate_paper#box%
  {\ifnum\number\c_page_target_paper_orientation\number\c_page_target_paper_reverse>\zerocount
     \page_boxes_apply_orientate_indeed\c_page_target_paper_orientation\c_page_target_paper_reverse{#box}%
   \fi}

\def\page_boxes_apply_orientate_print#box%
  {\ifnum\number\c_page_target_print_orientation\number\c_page_target_print_reverse>\zerocount
     \page_boxes_apply_orientate_indeed\c_page_target_print_orientation\c_page_target_print_reverse{#box}%
   \fi}

\def\page_boxes_apply_orientate_indeed#odd#even#box%
  {\setbox#box\vpack
     {\edef\somerotation{\number\ifdoublesided\ifodd\realpageno#odd\else#even\fi\else#odd\fi}%
      \dorotatebox\somerotation\hpack{\box#box}}}

\def\page_boxes_apply_mirror#box%
  {\setbox#box\vpack{\mirror{\box#box}}}

\def\page_boxes_apply_mirror_paper#box{\ifconditional\c_page_target_paper_mirror\page_boxes_apply_mirror{#box}\fi}
\def\page_boxes_apply_mirror_print#box{\ifconditional\c_page_target_print_mirror\page_boxes_apply_mirror{#box}\fi}

\let\page_boxes_apply_negate\negatecolorbox

\def\page_boxes_apply_negate_print#box%
  {\ifconditional\c_page_target_print_negate
     \page_boxes_apply_negate#box%
   \else\ifconditional\c_page_target_paper_negate
     \page_boxes_apply_negate#box%
   \fi\fi}

\let\p_page_layouts_scale\relax
\let\p_page_layouts_sx   \relax
\let\p_page_layouts_sy   \relax

\def\page_boxes_apply_scale#box%
  {\edef\p_page_layouts_scale{\layoutparameter\c!scale}%
   \ifdim\p_page_layouts_scale\points=\onepoint
     \edef\p_page_layouts_sx{\layoutparameter\c!sx}%
     \edef\p_page_layouts_sy{\layoutparameter\c!sy}%
     \ifdim\p_page_layouts_sx\points=\onepoint
       \ifdim\layoutparameter\c!sy\points=\onepoint
         % no scaling done (and no copying either)
       \else
         \page_boxes_apply_scale_indeed\p_page_layouts_sx\p_page_layouts_sy{#box}%
       \fi
     \else
       \page_boxes_apply_scale_indeed\p_page_layouts_sx\p_page_layouts_sy{#box}%
     \fi
   \else
     \page_boxes_apply_scale_indeed\p_page_layouts_scale\p_page_layouts_scale{#box}%
   \fi}

\def\page_boxes_apply_scale_indeed#sx#sy#box%
  {\setbox#box\vpack{\scale[\c!sx=#sx,\c!sy=#sy]{\box#box}}% can be a fast one
   \paperwidth #sx\paperwidth
   \paperheight#sy\paperheight}

% \setuppagenumbering[alternative=doublesided]
% \setupcolors[state=start]
% \setuppapersize[A4][A4,oversized]
% \setuplayout[location=middle,clipoffset=5mm]
% \setupbackgrounds
%   [page]
%   [frame=on,rulethickness=1mm,
%    backgroundoffset=10mm,background=color,backgroundcolor=red]
% \starttext \dorecurse{10}{\input tufte \par} \stoptext

% best use private variables

\newconditional\c_page_boxes_clip_print \settrue\c_page_boxes_clip_print

\def\page_boxes_apply_clip_print_left  % box
  {\ifconditional\c_page_boxes_clip_print
     \expandafter\page_boxes_apply_clip_print_indeed\expandafter\conditionalfalse
   \else
     \expandafter\gobbleoneargument
   \fi}

\def\page_boxes_apply_clip_print_right % box
  {\ifconditional\c_page_boxes_clip_print
     \expandafter\page_boxes_apply_clip_print_indeed\expandafter\conditionaltrue
   \else
     \expandafter\gobbleoneargument
   \fi}

\def\page_boxes_apply_clip_print_indeed#right#box% can be made more efficient, see other clipper
  {\scratchoffset\pagebackgroundoffset % can be zero which is valid % maybe another variable
   \scratchwidth \wd#box%
   \scratchheight\ht#box%
   \scratchdepth \dp#box%
   \setbox#box\hpack
     {\advance\scratchheight\dimexpr\scratchdepth+2\scratchoffset\relax
      \advance\scratchwidth \scratchoffset
      \ifconditional#right\relax
         \scratchdimen-\scratchoffset
         \kern\scratchdimen
      \else
         \scratchdimen\zeropoint
      \fi
      \lower\scratchoffset\hpack
        {\clip
           [\c!hoffset=\scratchdimen,
            \c!voffset=-\scratchoffset,
              \c!width=\scratchwidth,
             \c!height=\scratchheight]%
           {\box#box}}}%
   \wd#box\scratchwidth
   \ht#box\scratchheight
   \dp#box\scratchdepth}

\def\page_boxes_apply_clip_paper
  {\scratchoffset\layoutparameter\c!clipoffset\relax
   \ifdim\scratchoffset>\zeropoint
      \expandafter\page_boxes_apply_clip_paper_indeed
   \else
      \expandafter\gobbleoneargument
   \fi}

\def\page_boxes_apply_clip_paper_indeed#box%
  {\scratchwidth \wd#box%
   \scratchheight\ht#box%
   \scratchdepth \dp#box%
   \setbox#box\hpack
     {\advance\scratchheight\dimexpr\scratchdepth+2\scratchoffset\relax
      \advance\scratchwidth \scratchoffset
      \doifbothsides
        {\advance\scratchwidth\scratchoffset
         \scratchdimen-\scratchoffset
         \kern\scratchdimen}%
        {\scratchdimen\zeropoint}
        {\scratchdimen-\scratchoffset
         \kern\scratchdimen}%
      \lower\scratchoffset\hpack
        {\clip
           [\c!hoffset=\scratchdimen,
            \c!voffset=-\scratchoffset,
              \c!width=\scratchwidth,
             \c!height=\scratchheight]%
           {\box#box}}}%
   \wd#box\scratchwidth
   \ht#box\scratchheight
   \dp#box\scratchdepth}

% nearly always some displacement so no speedup test needed

\def\page_boxes_apply_offsets#1%
  {\setbox#1\vpack to \paperheight
     {\hsize\paperwidth
      \vkern\topspace
      \hkern\doifbothsides\backspace\backspace{\dimexpr\paperwidth-\backspace-\makeupwidth\relax}%
      \box#1}%
   \dp#1\zeropoint}

% \def\page_boxes_apply_offset#box%
%   {\scratchwidth \wd#box%
%    \scratchheight\ht#box%
%    \scratchdepth \dp#box%
%    \setbox#box\vpack
%      {\offinterlineskip
%       \vkern\topoffset
%       \hkern\doifbothsides\backoffset\backoffset{-\backoffset}%
%       \box#box}%
%    \wd#box\scratchwidth
%    \ht#box\scratchheight
%    \dp#box\scratchdepth}

% \let\page_boxes_apply_clip_paper      \gobbleoneargument
% \let\page_boxes_apply_clip_print_left \gobbleoneargument
% \let\page_boxes_apply_clip_print_right\gobbleoneargument

%D This is rather specialized:

\newconditional\c_page_areas_enabled
\newbox        \b_page_areas_registered

\def\enabletextarearegistration
  {\global\settrue\c_page_areas_enabled}

\def\page_areas_registered_box
  {\ifconditional\c_page_areas_enabled
     \expandafter\page_areas_registered_box_indeed
   \else
     \expandafter\page_areas_registered_box_forget
   \fi}

\def\page_areas_registered_box_forget#1#2#3% #1=lower-dp #2=correct-ht #3=box
  {\box#3}

\def\page_areas_registered_box_indeed#1#2#3% #1=lower-dp #2=correct-ht #3=box
  {\anch_mark_flow_box{#3}}

\def\page_areas_register_boxed#1%
  {\begingroup
   \setbox\scratchbox\vpack{#1}%
   \wd\scratchbox\makeupwidth % somehow a space creeps in
   \vpack{\page_areas_registered_box00\scratchbox}% 0 0 will go
   \endgroup}

% \def\page_areas_register_direct#1%
%   {\xypos{pbd:\realfolio:b}% we could save bytes by only saving the y
%    \endgraf
%    \begingroup
%    \scratchdimen\dimexpr\MPy{pbd:\realfolio:b}-\MPy{pbd:\realfolio:e}\relax
%    \setbox\scratchbox\emptyhbox
%    \wd\scratchbox\makeupwidth
%    \ht\scratchbox\scratchdimen
%    \vsmash{\page_areas_registered_box00\scratchbox}%
%    \endgroup
%    #1%
%    \endgraf
%    \xypos{pbd:\realfolio:e}}

\def\page_areas_register_direct#1#2%
  {\scratchdepth\dp#2%
   \dp#2\strutdepth
   \anch_mark_flow_only{#2}%
   \dp#2\scratchdepth
   #1#2}

\protect \endinput

