%D \module
%D   [       file=page-mbk,   % was part of page-mis.mkiv / 2008.11.17
%D        version=2011.11.23, % was part of page-flt.tex  / 2000.10.20
%D          title=\CONTEXT\ Page Macros,
%D       subtitle=Margin Floats,
%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 / Margin Floats}

\unprotect

%D This is an old mechanism that is quite independent of other floats. There is for
%D instance no save/restore used here. When there is need (and demand) we can use
%D the float cache and then flush them in the text when they are left over. On the
%D other hand, margin float are somewhat manual so it does not make too much sense
%D to complicate the code. As an alternative users can fall back on margin texts:
%D they do stack but don't float.
%D
%D \starttyping
%D \dorecurse{9} {
%D   \placefigure[margin]{#1}{}
%D   \input ward
%D }
%D \page \null % will flush them
%D \stoptyping

% status=start: in margin
% status=stop : in text
%
% todo: flush margin floats at end of text
% todo: separate boxes for left and right

\installcorenamespace{marginblock}
\installcorenamespace{marginblocklocation}

\installcommandhandler \??marginblock {marginblock} \??marginblock

\aliased\let\setupmarginblocks\setupmarginblock

\newconditional\c_page_margin_blocks_enabled % not really needed as we can check each time
\newconditional\c_page_margin_blocks_present

\newbox        \b_page_margin_blocks
\newbox        \b_page_margin_blocks_prepared

\appendtoks
   \ifcstok{\rootmarginblockparameter\c!state}\v!start
     \c_page_margin_blocks_enabled\conditionaltrue
   \else
     \c_page_margin_blocks_enabled\conditionalfalse
   \fi
\to \everysetupmarginblock

\setupmarginblocks
  [\c!state=\v!start,
   \c!location=\v!inmargin,
   \c!width=\rightmarginwidth,
  %\c!style=,
  %\c!color=,
  %\c!align=,
  %\c!left=,
  %\c!right=,
  %\c!top=,
  %\c!before=,
  %\c!after=,
   \c!inbetween=\blank,
   \c!bottom=\vfill]

\definesystemconstant{marginblock}
\definesystemconstant{leftmarginblock}
\definesystemconstant{rightmarginblock}

\resetboxesincache \s!marginblock      \s!marginblock
\resetboxesincache \s!leftmarginblock  \s!leftmarginblock
\resetboxesincache \s!rightmarginblock \s!rightmarginblock

\c_page_margin_blocks_enabled\conditionalfalse

\let\page_margin_blocks_stop_block\relax

\permanent\tolerant\protected\def\startmarginblock[#tag]%
  {\begingroup
   \cdef\currentmarginblock{#tag}%
   \ifcstok{\marginblockparameter\c!state}\v!start
     \expandafter\page_margin_blocks_start_block_yes
   \else
     \expandafter\page_margin_blocks_start_block_nop
   \fi}

\permanent\protected\def\stopmarginblock
  {\page_margin_blocks_stop_block
   \endgroup}

\def\page_margin_blocks_start_block_yes
  {%\showmessage\m!layouts4\empty
   \global\c_page_margin_blocks_enabled\conditionaltrue
   \dowithnextboxcs
     \page_margin_blocks_start_block_save
     \vbox\bgroup
       \let\page_margin_blocks_stop_block\page_margin_blocks_stop_block_yes
       \hsize{\marginblockparameter\c!width}%
       \usealignparameter\marginblockparameter
       \usemarginblockstyleandcolor\c!style\c!color
       \begstrut
       \ignorespaces}

\def\page_margin_blocks_stop_block_yes
  {\removeunwantedspaces
   \endstrut
   \egroup}

\def\page_margin_blocks_start_block_save
  {\putboxincache\s!marginblock{+}\nextbox}

\def\page_margin_blocks_start_block_nop
  {%\showmessage\m!layouts5\empty
   \marginblockparameter\c!before
   \bgroup
   \let\page_margin_blocks_stop_block\page_margin_blocks_stop_block_nop
   \usemarginblockstyleandcolor\c!style\c!color}

\def\page_margin_blocks_stop_block_nop
  {\egroup
   \marginblockparameter\c!after}

\permanent\protected\def\checkmarginblocks
  {\ifconditional\c_page_margin_blocks_enabled\ifcase\getboxcountfromcache\s!marginblock\else
     \expandafter\page_margin_blocks_check_indeed
   \fi\fi}

\def\page_margin_blocks_check_indeed
  {\ifcsname\??marginblocklocation\marginblockparameter\c!location\endcsname
     \page_margin_blocks_prepare_box
     \csname\??marginblocklocation\marginblockparameter\c!location\endcsname
   \else
     \global\setbox\b_page_margin_blocks\emptybox
   \fi}

\def\page_margin_blocks_prepare_box
  {\begingroup
   \scratchcounter\zerocount
   \localcontrolledloop \plusone \getboxcountfromcache\s!marginblock \plusone
     {\scratchcounter\currentloopiterator
      \setbox\scratchbox\vbox\bgroup
        \marginblockparameter\c!top
        \localcontrolledloop \plusone \scratchcounter \plusone
          {\ifcase\currentloopiterator\or
             \marginblockparameter\c!before
           \else
             \marginblockparameter\c!inbetween
           \fi
           \setbox\scratchbox\emptyvbox
           \ht\scratchbox\getboxhtfromcache\s!marginblock{\the\currentloopiterator}%
           \dp\scratchbox\getboxdpfromcache\s!marginblock{\the\currentloopiterator}%
           \box\scratchbox
           \marginblockparameter\c!after}%
       \marginblockparameter\c!bottom
      \egroup
      \ifdim\htdp\scratchbox>\textheight
        \advanceby\scratchcounter\minusone
       %\writestatus{quit}{\the\scratchcounter=>\the\htdp\scratchbox}
        \quitloop
      \else
       %\writestatus{progress}{\the\htdp\scratchbox}
      \fi}%
   \ifcase\scratchcounter\else
     \global\setbox\b_page_margin_blocks_prepared\vbox to \textheight\bgroup
       \marginblockparameter\c!top
       \localcontrolledloop \plusone \scratchcounter \plusone
         {\ifcase\currentloopiterator\or
            \marginblockparameter\c!before
          \else
            \marginblockparameter\c!inbetween
          \fi
          \getboxfromcache\s!marginblock{\the\currentloopiterator}\scratchbox
          \box\scratchbox
          \marginblockparameter\c!after}%
       \marginblockparameter\c!bottom
    \egroup
    \pruneboxesincache\s!marginblock
    \ifcase\getboxcountfromcache\s!marginblock\relax
      \global\c_page_margin_blocks_enabled\conditionaltrue
    \fi
  \fi
  \endgroup}

% inner outer

\permanent\protected\def\page_margin_blocks_place_r_yes
  {\setbox\b_page_margin_blocks_prepared\hbox to \rightmarginwidth
     {\marginblockparameter\c!left
      \box\b_page_margin_blocks_prepared
      \marginblockparameter\c!right}%
   \vsmashbox\b_page_margin_blocks_prepared
   \box\b_page_margin_blocks_prepared}

\permanent\protected\def\page_margin_blocks_place_l_yes
  {\setbox\b_page_margin_blocks_prepared\hbox to \leftmarginwidth
     {\marginblockparameter\c!right
      \box\b_page_margin_blocks_prepared
      \marginblockparameter\c!left}%
   \vsmashbox\b_page_margin_blocks_prepared
   \box\b_page_margin_blocks_prepared}

\permanent\protected\def\page_margin_blocks_place_r_nop{\hskip\rightmarginwidth}
\permanent\protected\def\page_margin_blocks_place_l_nop{\hskip\leftmarginwidth}

\aliased\let\placerightmarginblock\page_margin_blocks_place_r_nop
\aliased\let\placeleftmarginblock \page_margin_blocks_place_l_nop

\def\page_margin_blocks_set_r_box{\enforced\aliased\let\placerightmarginblock\page_margin_blocks_place_r_yes}
\def\page_margin_blocks_set_l_box{\enforced\aliased\let\placeleftmarginblock \page_margin_blocks_place_l_yes}

\letcsname\??marginblocklocation\v!left \endcsname\page_margin_blocks_set_l_box
\letcsname\??marginblocklocation\v!right\endcsname\page_margin_blocks_set_r_box

\defcsname\??marginblocklocation\v!inmargin\endcsname
  {\doifbothsidesoverruled
     \page_margin_blocks_set_r_box
     \page_margin_blocks_set_r_box
     \page_margin_blocks_set_l_box}

\defcsname\??marginblocklocation\v!middle\endcsname
  {\doifbothsidesoverruled
     \page_margin_blocks_set_r_box
     \page_margin_blocks_set_l_box
     \page_margin_blocks_set_r_box}

% margin floats (keyword 'margin' in option list)

\protected\def\page_margin_blocks_process_float
  {\ifcstok{\marginblockparameter\c!state}\v!start
     \page_margin_blocks_process_float_yes
   \else
     \page_margin_blocks_process_float_nop
   \fi}

\def\page_margin_blocks_process_float_yes
  {\global\c_page_margin_blocks_enabled\conditionaltrue
   \putboxincache\s!marginblock{+}\floatbox}

\def\page_margin_blocks_process_float_nop
  {\handlefloatmethod\v!here}

\appendtoks
   \ifcase\getboxcountfromcache\s!marginblock\else
     \writestatus\m!layouts{beware: there are left-over margin floats!}%
   \fi
\to \everystoptext

\permanent\protected\def\flushmarginblocks
 {\ifconditional\c_page_margin_blocks_enabled
    \page_otr_command_flush_margin_blocks
  \fi}

\permanent\tolerant\protected\def\flushallmarginblocks[#1]%
  {\ifconditional\c_page_margin_blocks_enabled
     \begingroup
     \scratchcounterone\getboxcountfromcache\s!marginblock\relax
     \ifcase\scratchcounterone\else
       \scratchcountertwo\ifparameter#1\or{\scratchcounterone-#1+\plusone}\else\plusone\fi
       \localcontrolledloop \scratchcountertwo \scratchcounterone \plusone
         {\ifcase\currentloopiterator\or
            \marginblockparameter\c!before
          \else
            \marginblockparameter\c!inbetween
          \fi
          \getboxfromcache\s!marginblock{\the\currentloopiterator}\scratchbox
          \box\scratchbox
          \marginblockparameter\c!after}%
       \pruneboxesincache\s!marginblock
     \fi
     \endgroup
   \fi}

\protect \endinput
