%D \module
%D   [       file=pack-bck, % moved from  pack-rul,
%D        version=20111115, % 1998.10.16,
%D          title=\CONTEXT\ Packaging Macros,
%D       subtitle=Simple Backgrounds,
%D         author=Hans Hagen \& Wolfgang Schuster,
%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 Packaging Macros / Simple Backgrounds}

%D The code here is already pretty old and is used for simple backgrounds. As it is
%D still used WS adapted the code to the new command handler methods so that it gets
%D a second life. So it made sense to mkvi as well. Some more code is moved here
%D too.

%D \macros
%D   {setupbackground,startbackground,background}
%D
%D The section deals with backgrounds in the running text. This means that texts is
%D to be collected and split over pages. To show what can be done, we provide this
%D part of the documentation with some gray background and a red frame. Both the
%D background and frame can have all characteristics of \type {\framed}.
%D
%D \starttyping
%D \setupbackground
%D   [backgroundoffset=4pt,
%D    background=color,
%D    frame=on,
%D    framecolor=red,
%D    leftoffset=2pt]
%D \stoptyping
%D
%D The implementation is not that sophisticated, but suffices. The main problem with
%D this kind of functionality is to get the spacing all right.
%D
%D Specifying the background is more or less the same as
%D specifying a framed box.
%D
%D \showsetup{setupbackground}
%D
%D {\em This mechanism is sort of obsolete and textbackgrounds should be used
%D instead.}

\unprotect

\installcorenamespace {background}

\installframedcommandhandler \??background {background} \??background

% The mode is not that public and mostly an initial mode:
%
% 0 : no split
% 1 : no split, honoring leftskip (messy)
% 2 : split
% 3 : split, honoring leftskip (messy)
%
% While processing the modes will change from 3->1 or 2->0. Don't depend on the
% mode being public currently as it could become a key.

\setnewconstant\backgroundsplitmode\plusthree

\appendtoks
    \protected\frozen\instance\edefcsname\e!start\currentbackground\endcsname{\pack_backgrounds_start [\currentbackground]}%
    \protected\frozen\instance\edefcsname\e!stop \currentbackground\endcsname{\pack_backgrounds_stop                      }%
    \protected\frozen\instance\edefcsname        \currentbackground\endcsname{\pack_backgrounds_direct[\currentbackground]}%
\to \everydefinebackground

\protected\def\pack_backgrounds_start[#tag]%
  {\endgraf
   \begingroup
   \cdef\currentbackground{#tag}%
   \ifcstok{\backgroundparameter\c!state}\v!start
     \expandafter\pack_backgrounds_start_indeed
   \else
     \expandafter\pack_backgrounds_start_ignore
   \fi}

\tolerant\def\pack_backgrounds_start_indeed[#S#settings]%
  {\setupcurrentbackground[#settings,\c!state=\v!start,\c!offset=\v!overlay]%
   \let\pack_backgrounds_stop\pack_backgrounds_stop_indeed
   \setbox\scratchboxone\vbox\bgroup
     \strut
     \vskip-2\lineheight
     \strut
     \blank[\v!disable]
     \leftskip \glueexpr\backgroundparameter\c!leftoffset\relax
     \rightskip\glueexpr\backgroundparameter\c!rightoffset\relax}

\tolerant\def\pack_backgrounds_start_ignore[#S#settings]%
  {\let\pack_backgrounds_stop\pack_backgrounds_stop_ignore}

\let\pack_backgrounds_stop\relax

\protected\def\pack_backgrounds_stop_indeed % we should use the fast background variant of framed
  {\endgraf
   \removelastskip
   \strut
   \vskip-2\lineheight
   \strut
   % safeguard added
   \ifdim{\pagetotal+2\lineheight}>\pagegoal
     \page
   \fi
   % till here
   \egroup
   \scratchdistance\leftskip % new **
   \forgetall
   \ifinsidefloat
     \backgroundsplitmode\zerocount
   \fi
   \ifcase\backgroundsplitmode
     \inheritedbackgroundframed{\box\scratchboxone}%
   \or
     \hskip\scratchdistance
     \inheritedbackgroundframed{\box\scratchboxone}%
   \else
     \splitmaxdepth\maxdepth
     \splittopskip\topskip
     \clf_stripinserts\scratchboxone % no inserts in splits so ...
     \doloop
       {\ifzeropt\pagetotal % empty page
          \scratchdimen\textheight
          \backgroundsplitmode\plusone % split to max height
        \else
          \setbox\scratchboxtwo\vbox{\backgroundparameter\c!before}%
          \scratchdimen{\pagegoal-\ht\scratchboxtwo-\pagetotal}%
          \backgroundsplitmode\plustwo % split to partial height
        \fi
        \ifdim\scratchdimen<\zeropoint
            \scratchdimen\pagegoal
        \fi
        \advanceby\scratchdimen{-\backgroundparameter\c!topoffset-\backgroundparameter\c!bottomoffset}%
        \ifdim\scratchdimen>2\lineheight\relax % reasonable, will be configurable
          \ifdim\ht\scratchboxone>\scratchdimen % larger than page
            \setbox\scratchboxtwo\vsplit\scratchboxone to \scratchdimen
          \else
            \setbox\scratchboxtwo\box\scratchboxone
            \backgroundsplitmode\zerocount % no split
          \fi
          \setbox\scratchboxtwo\vbox \ifcase\backgroundsplitmode\or to \textheight \fi % max split
            {\vskip{\backgroundparameter\c!topoffset}% or \vkern
             %\unvcopy\scratchboxtwo
             %\prevdepth\dp\scratchboxtwo
             \scratchdepth\dp\scratchboxtwo
             \unvbox\scratchboxtwo
             \prevdepth\scratchdepth
             %
             \obeydepth
             \vskip{\backgroundparameter\c!bottomoffset}% or \vkern
             \vfill}
          \backgroundparameter\c!before
          \ifcase\backgroundsplitmode\or\or % partial split
            \ifdim\pagegoal<\maxdimen
              \pagegoal=1.2\pagegoal % be a bit more tolerant
            \fi
          \fi
          \startlinecorrection
            \ifnum\backgroundsplitmode=\plusthree
              \hskip\scratchdistance % new ** % or \hkern
            \fi
            \inheritedbackgroundframed{\box\scratchboxtwo}%
          \stoplinecorrection
          \ifcase\backgroundsplitmode % no split
            \backgroundparameter\c!after
          \else % some split
            \page_otr_fill_and_eject_page % no \page !
          \fi
        \else
          \page
        \fi
        \ifdim\ht\scratchboxone>\zeropoint \else
          \exitloop
        \fi}%
        \clf_unstripinserts % ... we flush them afterwards
   \fi
   \endgroup
   \endgraf}


\protected\def\pack_backgrounds_stop_ignore
  {\endgroup
   \endgraf}

\protected\def\pack_backgrounds_direct[#tag]%
  {\begingroup
   \cdef\currentbackground{#tag}%
   \ifcstok{\backgroundparameter\c!state}\c!start
     \expandafter\pack_backgrounds_direct_indeed
   \else
     \expandafter\pack_backgrounds_direct_ignore
   \fi}

\def\pack_backgrounds_direct_indeed
  {\dowithnextboxcs\pack_backgrounds_direct_finish\vbox}

\def\pack_backgrounds_direct_finish
  {\setupcurrentbackground[\c!offset=\v!overlay]%
   \inheritedbackgroundframed{\flushnextbox}%
   \endgroup}

\def\pack_backgrounds_direct_ignore
  {\endgroup}

\definebackground[\v!background]

\ifdefined\startbackground \else
    \permanent\expandafter\let\expandafter\startbackground\csname\e!start\v!background\endcsname
    \permanent\expandafter\let\expandafter\stopbackground \csname\e!stop \v!background\endcsname
    \permanent\expandafter\let\expandafter\background     \csname        \v!background\endcsname
\fi

\setupbackground
  [\c!leftoffset=.5\bodyfontsize,
   \c!rightoffset=\backgroundparameter\c!leftoffset,
   \c!topoffset=\zeropoint,
   \c!bottomoffset=\backgroundparameter\c!topoffset,
   \c!state=\v!start,
   \c!radius=.5\bodyfontsize,
   \c!corner=\v!rectangular,
   \c!frame=\v!off,
   \c!depth=\zeropoint,
 % \c!color=,
   \c!background=\v!color,
   \c!backgroundcolor=lightgray,
   \c!before=,
   \c!after=]

%D \startbuffer
%D \setupbackground[state=start,frame=on]
%D
%D \startbackground
%D \input ward
%D \stopbackground
%D
%D \background{\input ward\par}
%D
%D \setupbackground[state=stop]
%D
%D \startbackground
%D \input ward
%D \stopbackground
%D
%D \background{\input ward\par}
%D \stopbuffer
%D
%D \typebuffer \getbuffer

\protect \endinput
