%D \module
%D   [       file=page-flt,
%D        version=2010.04.08,
%D          title=\CONTEXT\ Page Macros,
%D       subtitle=Float Management,
%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 / Float Management}

%D This module has code that previously was in other modules. There is also float
%D related code in \type {strc-flt.mkiv}.

\registerctxluafile{page-flt}{}

\unprotect

\defineinsertion[\s!topfloat]
\defineinsertion[\s!bottomfloat]
\defineinsertion[\s!pagefloat]    % not used

\newdimension\d_page_floats_inserted_bottom
\newdimension\d_page_floats_inserted_top
\newdimension\d_page_floats_inserted_page
\newinteger  \c_page_floats_n_of_top           \c_page_floats_n_of_top   \plustwo
\newinteger  \c_page_floats_n_of_bottom        \c_page_floats_n_of_bottom\zerocount
\newinteger  \c_page_floats_n_of_page          \c_page_floats_n_of_page  \plustwo

\newconstant\c_page_floats_insertions_topskip_mode  % 1 = no topskip

\def\page_floats_report_total
  {\showmessage\m!floatblocks4%
     {\the\totalnoffloats
      \ifempty\floatlocationmethod
        \ifempty\floatlocation\else,\floatlocation\fi
      \else
        ,\floatlocationmethod
      \fi}}

\def\page_floats_report_flushed
  {\showmessage\m!floatblocks3%
     {\the\numexpr\totalnoffloats-\savednoffloats\relax}}

%D Extra float registers.

\newconditional\c_page_floats_room
\newconditional\c_page_floats_some_waiting
\newconditional\c_page_floats_not_permitted
\newconditional\c_page_floats_flushing
\newconditional\c_page_floats_center_box          \c_page_floats_center_box\conditionaltrue
\newconditional\c_page_floats_center_box_local
\newconditional\c_page_floats_center_box_global
\newconditional\c_page_floats_compress_flushed    \c_page_floats_compress_flushed\conditionaltrue

\newdimension  \d_page_floats_compress_distance

%D For the moment we keep this but they will become private too.

\newinteger  \totalnoffloats           % these will be redone ... handled at the lua end anyway
\newinteger  \savednoffloats           % these will be redone ... handled at the lua end anyway
\newinteger  \nofcollectedfloats       % communication channel
\newdimension\maxcollectedfloatstotal  % communication channel
\newinteger  \noffloatinserts          % these will be redone ... handled at the lua end anyway

\newbox      \floattext

\newdimension\floatwidth
\newdimension\floatheight
\newdimension\floatdepth
\newdimension\floattextwidth
\newdimension\floattextheight

\newbox  \floatbox
\newbox  \savedfloatbox

%D From now on we manage the float stack at the \LUA\ end instead of packing
%D them in a box and splitting off stacked floats. It's not so much less code
%D but it's cleaner this way. It also opens op some posibilities as we can now
%D more conveniently cary additional information around.

\newtoks \everyfloatscheck

\appendtoks
   \ifcase\savednoffloats
     \global\c_page_floats_some_waiting\conditionalfalse
   \else
     \global\c_page_floats_some_waiting\conditionaltrue
   \fi
\to \everyfloatscheck

\protected\def\page_floats_flush#1#2%
  {\clf_flushfloat{#1}#2\relax
   \expand\everyfloatscheck}

\protected\def\page_floats_flush_by_label#1#2%
  {\clf_flushlabeledfloat{#1}{#2}\relax
   \expand\everyfloatscheck}

\protected\def\page_floats_save#1%
  {\clf_savefloat{#1}\relax
   \expand\everyfloatscheck}

\protected\def\page_floats_resave#1%
  {\clf_resavefloat{#1}\relax
   \expand\everyfloatscheck}

\protected\def\page_floats_push_saved
  {\clf_pushfloat
   \expand\everyfloatscheck}

\protected\def\page_floats_pop_saved
  {\clf_popfloat
   \expand\everyfloatscheck}

\protected\def\page_floats_get_info#1%
  {\clf_consultfloat{#1}}

\protected\def\page_floats_if_else#1%
  {\clf_doifelsestackedfloats{#1}}

\protected\def\page_floats_collect#1#2#3%
  {\clf_collectfloat{#1}{#2}{#3}}

\permanent\def\nofstackedfloatsincategory#1% was singular
  {\clf_nofstackedfloats{#1}}

\let\page_floats_column_push_saved\page_floats_push_saved % overloaded in page-mul
\let\page_floats_column_pop_saved \page_floats_pop_saved  % overloaded in page-mul

%D \starttyping
%D \starttext
%D
%D \samplefile{tufte}
%D \startplacefigure[location=page] \externalfigure[dummy] \stopplacefigure
%D \samplefile{tufte}
%D \dorecurse{6}{
%D     \startplacefigure[location={page,append}] \externalfigure[dummy] \stopplacefigure
%D }
%D \startplacefigure[location=page] \externalfigure[dummy] \stopplacefigure
%D \samplefile{tufte}
%D
%D \page
%D
%D \samplefile{tufte}
%D \startplacefigure[location=page] \externalfigure[dummy] \stopplacefigure
%D \samplefile{tufte}
%D \dorecurse{5}{
%D     \startplacefigure[location={page,append}] \externalfigure[dummy] \stopplacefigure
%D }
%D \startplacefigure[location=page] \externalfigure[dummy] \stopplacefigure
%D \samplefile{tufte}
%D
%D \stoptext
%D \stoptyping

\protected\def\page_floats_save_page_float#1#2%
  {\ifconditional\c_floats_append_to_stored
     \scratchcounter\nofstackedfloatsincategory{#1}\relax
     \ifcase\scratchcounter\else
       \setbox\scratchboxtwo\box\floatbox
       \clf_flushfloat{#1}\scratchcounter
       \setbox\scratchboxone\box\floatbox
       \setbox\scratchboxthree\vbox\bgroup
          \blank[\rootfloatparameter\c!spaceafter ]% a bit of a hack
          \blank[\rootfloatparameter\c!spacebefore]%
       \egroup
       \scratchdimen\ifconditional\c_floats_force\maxdimen\else\textheight\fi
       \ifdim{\htdp\scratchboxone+\htdp\scratchboxtwo+\htdp\scratchboxthree}>\scratchdimen
         \setbox\floatbox\box\scratchboxone
         \clf_savespecificfloat{#1}{specification{#2}}\relax
         \setbox\floatbox\box\scratchboxtwo
       \else
         \setbox\floatbox\vbox\bgroup
            \box   \scratchboxone
            \unvbox\scratchboxthree
            \box   \scratchboxtwo
         \egroup
       \fi
     \fi
   \fi
   \clf_savespecificfloat{#1}{specification{#2}}\relax}

\protected\def\page_floats_save_somewhere_float#1#2% #1=method
  {\clf_savespecificfloat{#1}{specification{#2}label{\floatlabel}}\relax}

%D This is an experimental new feature (for Alan Braslau), a prelude to more:
%D
%D \starttyping
%D test \placefigure{}{}
%D test \placefigure[somewhere:alpha][whatever]{}{}
%D test \placefigure[somewhere:beta] [whatever]{}{}
%D test \placefigure[somewhere:gamma][whatever]{}{}
%D test \placefigure[somewhere:delta][whatever]{}{}
%D test \placefigure{}{}
%D
%D in \in{figure}[whatever] bla bla
%D
%D \placenamedfloat[figure][*l*]
%D \placenamedfloat[figure][gamma]
%D \placenamedfloat[figure][beta]
%D \stoptyping

\permanent\tolerant\protected\def\placenamedfloat[#1]#*[#2]%
  {\doloop
     {\page_floats_flush_by_label\s!somewhere{#2}%
      \ifvoid\floatbox
        \exitloop
      \else
        \cdef\currentfloat{#1}%
        \blank[\rootfloatparameter\c!spacebefore]%
        \box\floatbox
        \blank[\rootfloatparameter\c!spaceafter]%
      \fi}}

%D Not the best name for a command:
%D
%D \starttyping
%D \samplefile{tufte}
%D \placefigure[somewhere:a]{}{\externalfigure[dummy-001]}
%D \samplefile{tufte}
%D \placefigure{}{\externalfigure[dummy-002]}
%D \samplefile{tufte}
%D \startplacefigure[location={somewhere:b,tight}]
%D     \externalfigure[dummy-003]
%D \stopplacefigure
%D \samplefile{tufte}
%D \placefigure{}{\externalfigure[dummy-004]}
%D \page
%D \placesavedfloat[figure][b][location={none,left}] \samplefile{tufte}
%D \placesavedfloat[figure][a]
%D % \placenamedfloat[figure][*]
%D % \placenamedfloat[figure][b]
%D \stoptyping

\newbox\b_strc_float_saved

\permanent\tolerant\protected\def\placesavedfloat[#1]#*[#2]#*[#S#3]% experiment for Alan B
  {\clf_flushlabeledfloat\s!somewhere{#2}\relax
  %\cdef\currentfloat{#1}%
   \setbox\b_strc_float_saved\vpack{\box\floatbox}%
   \startplacefloat[#1][\c!location=\v!none,#3]%
     \box\b_strc_float_saved
   \stopplacefloat}

% \setupcaption [figure]   [align=flushleft]
% \setupcaption [figure-1] [align=flushleft,leftmargin=10mm]
% \setupcaption [figure-2] [align=flushleft,leftmargin=10mm,rightmargin=-10mm,width=\textwidth]
%
% \startsetups somefigure
%     \ifdim\floatsetupwidth>\textwidth
%         \placesetupfloat[figure-2]
%     \else
%         \placesetupfloat[figure-1]
%     \fi
% \stopsetups
%
% \placefloatwithsetups[somefigure]{}{\externalfigure[dummy][width=5cm,height=2cm]}

\mutable\lettonothing\floatsetupcaption
\mutable\lettonothing\floatsetupcontent
\mutable\lettonothing\floatsetupwidth
\mutable\lettonothing\floatsetupheight

\aliased\let\placesetupfloat\gobbleoneoptional

\permanent\tolerant\protected\def\placefloatwithsetups[#1]#*[#S#2]#*[#S#3]#:#4%
  {\def\floatsetupcaption{#4}%
   \def\floatsetupcontent{\copy\nextbox}%
   \def\floatsetupwidth  {\wd\nextbox}%
   \def\floatsetupheight {\ht\nextbox}%
   \enforced\permanent\protected\def\placesetupfloat[##1]%
     {\placefloat[##1][#2][#3]{#4}{\floatsetupcontent}}% #4 and not \floatsetupcaption (protected)
   \dowithnextbox{\setups[#1]}\vbox}

%D The following code is in transition as we don't want to break the current single
%D column, multi column, and columnset mechanism.
%D
%D First we reimplement some helpers.

\def\page_floats_get_used_hsize{\hsize}

\protected\def\page_floats_get
  {\ifconditional\c_page_floats_some_waiting
     \page_floats_flush\s!text\plusone
     \ifconditional\c_page_floats_center_box
       \ifdim\wd\globalscratchbox<\page_floats_get_used_hsize
         \global\setbox\floatbox\hpack to \page_floats_get_used_hsize{\hss\box\floatbox\hss}%
       \orelse\ifinsidecolumns
         % retain special alignments
         \ifdim\wd\floatbox>\makeupwidth
           \wd\floatbox\makeupwidth
         \fi
       \fi
     \fi
   \else
     \global\savednoffloats\zerocount
     \global\setbox\floatbox\emptybox
   \fi}

\protected\def\page_floats_flush_saved
  {\doloop
     {\ifconditional\c_page_floats_some_waiting
        \page_otr_command_check_if_float_fits
        \ifconditional\c_page_floats_room
          \page_floats_get
          \doplacefloatbox
        \else
          \exitloop
        \fi
      \else
      % \ifconditional\c_page_margin_blocks_present % not here, here just as many floats as fit
      %   \page_otr_command_flush_margin_blocks
      % \else
          \exitloop
      % \fi
      \fi}}

%D This is a future mechamism that will be integrated once we're sure about it:
%D
%D \starttyping
%D \dorecurse{10}
%D   {\input thuan
%D    \placefigure{}{\framed[height=1.5cm]{test}}
%D    \placefloatplaceholder}
%D \stoptyping

\permanent\protected\def\placefloatplaceholder
  {\ifconditional\c_page_floats_room \else
     \ifdim{\pagegoal-\pagetotal-3\lineheight}>\zeropoint
       \startlinecorrection[blank]
       \mhbox{\inframed{\labeltexts{placeholder}{\m_strc_floats_last_caption_tag}}}%
       \stoplinecorrection
     \else
       \allowbreak
     \fi
   \fi}

\setuplabeltext
  [placeholder={\Word{\lastplacedfloat}~, moved}]

%D Page floats use different stacks.

\newtoks\everybeforeflushedpagefloat

\let\m_page_otr_checked_page_float\relax

\newconditional\c_page_floats_flushed

\def\page_floats_flush_page_floats_inject#1% future releases can do more clever things
  {\page_floats_flush{#1}\plusone
   \edef\floatspecification{\clf_getfloatvariable{specification}}% Is this okay?
   \expand\everybeforeflushedpagefloat
   \vpack to \textheight
     {\ifinset\v!high\floatspecification\else\vfill\fi
      \box\floatbox
      \ifinset\v!low \floatspecification\else\vfill\fi}%
   \page_otr_fill_and_eject_page % needed
   \global\c_page_floats_flushed\conditionaltrue}

\protected\def\page_floats_flush_page_floats % used in postpone
  {\global\c_page_floats_flushed\conditionalfalse
   \page_floats_flush_page_floats_indeed
   \ifconditional\c_page_floats_flushed
     \page_otr_fill_and_eject_page
   \fi}

\protected\def\page_floats_flush_page_floats_indeed % used in postpone
  {\edef\m_page_otr_checked_page_float{\clf_checkedpagefloat}%
   \ifempty\m_page_otr_checked_page_float
     % nothing
   \orelse\ifx\m_page_otr_checked_page_float\v!empty
      \emptyhbox \page_otr_fill_and_eject_page % why not dummy_page
      \expandafter\page_floats_flush_page_floats
   \else
      \page_floats_flush_page_floats_inject\m_page_otr_checked_page_float
      \expandafter\page_floats_flush_page_floats
   \fi}

% temp hack, needed to prevent floatbox being forgotten during
% output, this will change to using another box for flushing
%
% \dorecurse{700}{text } \placefigure[top][]{First} {\framed{bla 1}}
%                        \placefigure[top][]{Second}{\framed{bla 2}}
% \dorecurse {40}{text } \placefigure[top][]{Third} {\framed{bla 3}}

\appendtoks
    \global\setbox\savedfloatbox\box\floatbox
\to \everybeforeoutput

\appendtoks
    \global\setbox\floatbox\box\savedfloatbox
\to \everyafteroutput

\protect \endinput

% hm, where is this one used (was in save/restore, see old implementation)
%
% \permanent\protected\def\uncenteredfloatbox
%   {\ifconditional\c_page_floats_center_box
%      \ifhbox\floatbox\relax % remove centering
%        \ifdim\wd\floatbox=\hsize
%          \ifhbox\floatbox
%            \setbox\scratchbox\hbox
%              {\unhbox\floatbox
%               \unskip\unskip
%               \global\setbox\globalscratchbox\lastbox}%
%            \box\globalscratchbox
%          \else
%            \box\floatbox
%          \fi
%        \else
%          \box\floatbox
%        \fi
%      \else
%        \box\floatbox
%      \fi
%    \else
%      \box\floatbox
%    \fi}
