%D \module
%D   [       file=strc-flt,
%D        version=2008.10.20,
%D          title=\CONTEXT\ Structure Macros,
%D       subtitle=Float Numbering,
%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.

%D This module will be redone with conditionals and everythings. Anyway, text floats
%D are a rather historic feature so changing something is also braking something.

\writestatus{loading}{ConTeXt Structure Macros / Float Numbering}

\unprotect

\ifdefined\d_page_sides_vsize \else \newdimension\d_page_sides_vsize \fi

\registerctxluafile{strc-flt}{autosuffix}

% todo: a keyword for this (and then a settings->hash for speed)
%
% \setuplayout[width=middle,backspace=3cm]
%
% \appendtoks
%     \inhibitmargindata\conditionaltrue
% \to \everyinsidefloat
%
% \starttext
%     \dorecurse{20}{
%         \par \inleft{\red\infofont<#1>} \par
%         \placefigure[leftmargin]{}{\framed[height=1cm,width=2cm]{}}
%       % \placefigure{#1}{\framed[height=1cm,width=2cm]{}}
%         \par line #1.1 \par line #1.2 \par
%     }
% \stoptext

% todo: delay caption creation and make setups for each method instead
%       so that we can have a list of methods and redo them as we can
%       keep the list or even better: recreate it
%
% todo: strc_floats_analyze_variables_two could trigger a setup
%       and we could have nofmethods of them
%
% todo: move variables from page-flt to strc-flt
%
% todo: p_name etc
%
% todo: less globals!
%
% todo: do all options in lua

%D This module is being converted into a mkvi one.
%D
%D - rename macros
%D - get rid of dead code
%D - less gobal mess
%D - more mkiv-ish

\installcorenamespace{float}
\installcorenamespace{floatbuilder}
\installcorenamespace{floatcaption}
\installcorenamespace{floatframed}

\installframedcommandhandler \??float        {float}        \??float
\installframedcommandhandler \??floatcaption {floatcaption} \??floatcaption
\installframedcommandhandler \??floatframed  {floatframed}  \??floatframed

\aliased\let\setupfloats  \setupfloat
\aliased\let\setupcaption \setupfloatcaption
\aliased\let\setupcaptions\setupfloatcaption

\permanent\protected\def\dohandlenextfloatindent
  {\useindentnextparameter\floatparameter
   \dorechecknextindentation}

\setupcaptions
  [\c!location=\v!bottom,
   \c!grid=,
   \c!before=, % not used (yet)
   \c!inbetween={\blank[\v!medium]},
   \c!after=, % not used (yet)
   \c!spacebefore=,
   \c!spaceinbetween=, % replaces fuzzy inbetween dual usage
   \c!spaceafter=,
   \c!width=\v!fit,
   \c!minwidth=\v!fit, % id est: the width of the floatbox in some cases
   \c!headstyle=\v!bold,
   \c!headcolor=,
   \c!leftmargin=\zeropoint,
   \c!rightmargin=\zeropoint,
   \c!outermargin=\zeropoint,
   \c!innermargin=\zeropoint,
   \c!setups=,
   \c!style=\v!normal,
   \c!color=,
   \c!textstyle=,
   \c!textcolor=,
   \c!align=,
   \c!number=\v!yes,
   \c!offset=\v!overlay,
   \c!frame=\v!off,
 % \c!expansion=,
 % \c!prefix=,
 % \c!prefixconnector=,
 % \c!way=,
 % \c!prefixsegments=,
 % \c!way=,
 % \c!blockway=,
 % \c!sectionnumber=,
 % \c!separator=,
 % \c!starter=,
 % \c!stopper=,
   \c!suffixseparator=, % currently rather hard coded
   \c!suffix=\floatcaptionsuffix,
   \c!distance=\emwidth, % plus .5\emwidth minus .25\emwidth
   \c!conversion=\v!numbers,
   \c!maxwidth=\hsize,
   \c!command=]

% we can comment some of these

\setupfloats
  [\c!location=\v!middle,
   \c!width=8\lineheight,
   \c!height=6\lineheight,
   \c!offset=\v!overlay,
   \c!frame=\v!off,
   \c!strut=\v!no,
   \c!radius=.5\bodyfontsize,
   \c!corner=\v!rectangular,
   \c!grid=,
  %\c!background=,
  %\c!backgroundcolor=,
   \c!backgroundoffset=\!!zeropoint,
  %\c!topframe=,
  %\c!bottomframe=,
  %\c!leftframe=,
  %\c!rightframe=,
   \c!frameoffset=\!!zeropoint,
  %\c!before=,
  %\c!after=,
   \c!spacebefore=\v!big,
   \c!spaceafter=\v!big,
   \c!sidespacebefore=\rootfloatparameter\c!spacebefore,
   \c!sidespaceafter=\rootfloatparameter\c!spaceafter,
   \c!sidespaceinbetween=\rootfloatparameter\c!spacebefore,
   \c!spacebeforeside=, % extra, not part of, can be used to add whitespace before text
   \c!spaceafterside=,  % idem
   \c!sidealign=\v!normal,
   \c!textmethod=\ifgridsnapping2\else0\fi, % 0=raw 1=safe (.99pg) 2=tight (-1pt) % THIS WILL CHANGE
   \c!sidemethod=\ifgridsnapping2\else1\fi, % 0=raw 1=safe (.99pg) 2=tight (-1pt) % THIS WILL CHANGE
   \c!indentnext=\v!no,
   \c!margin=\emwidth,
   \c!method=1,
   \c!cache=\v!yes, % when no, then intermediate flush
   \c!leftmargin=\zeropoint,  % displacement in 'normal floats'
   \c!rightmargin=\zeropoint, % idem
   \c!innermargin=\zeropoint, % idem
   \c!outermargin=\zeropoint, % idem
   \c!leftmargindistance=\zeropoint,
   \c!rightmargindistance=\floatparameter\c!leftmargindistance,
   \c!step=\v!small, % the flush side float step (big, medium, small : always depth)
   \c!ntop=2,
   \c!nbottom=0,
   \c!nlines=4, % used?
   \c!topoffset=\zeropoint,
   \c!bottomoffset=\zeropoint,
   \c!freeregion=\v!yes,
  %\c!local=,
  %\c!bottombefore=, % e.g. \vfill
  %\c!bottomafter=,
  %\c!default=, % default location
   \c!sidethreshold=.5\strutdp, % set to "old" to check with old method
   \c!numbering=\v!yes,
   \c!compress=\v!yes, % when possible pack floats when flushing
   \c!compressdistance=\emwidth]

\setupfloatframed
  [\c!frame=\v!off,
   \c!offset=\v!overlay,
   \c!strut=\v!no]

\newconditional\c_page_floats_pack_flushed

\appendtoks
    \ifcstok{\floatparameter\c!compress}\v!yes
      \c_page_floats_pack_flushed\conditionaltrue
    \else
      \c_page_floats_pack_flushed\conditionalfalse
    \fi
    \d_page_floats_compress_distance{\floatparameter\c!compressdistance}%
\to \everysetupfloat

\mutable\lettonothing\currentfloatattribute
\mutable\lettonothing\currentfloatcounter
\mutable\lettonothing\currentfloatgroup
\mutable\lettonothing\currentfloatnumber
\mutable\lettonothing\currentfloatsynchronize

\lettonothing\m_strc_floats_previous_number % we can also just push/pop

%D We need to do it again here:

\setupfloat
  [\c!compress=\v!yes, % when possible pack floats when flushing
   \c!compressdistance=\emwidth]

%D Individial settings:

\installcounterassociation{floatcaption}

\appendtoks
    \let\currentfloat\currentfloatcaption % ?
    \synchronizefloatcaptioncounters
\to \everysetupfloatcaption

\appendtoks
    \let\currentfloat\currentfloatcaption % ?
    \synchronizefloatcaptioncounters
\to \everydefinefloatcaption

%D Definitions:

\let\strc_floats_define_saved\definefloat

\permanent\tolerant\protected\overloaded\def\definefloat[#1]#*[#S#2]#*[#S#3]% name+plural+parent | name+parent+settings
  {\ifarguments\or
     \strc_floats_define_c[#1][#1]%
   \or
     \doifelsecommandhandler\??float{#2}%
       {\strc_floats_define_a[#1][#1][#2]}%
       {\strc_floats_define_c[#1][#2]}%
   \orelse\ifhastok={#3}%
     \strc_floats_define_b[#1][#2][#3]%
   \else
     \strc_floats_define_a[#1][#2][#3]%
   \fi}

\def\strc_floats_define_a[#1][#2][#3]% name names parent
  {\definefloatcaption[#1][#3]%
   \definefloatframed[#1][#3]%
   \definecounter[#1][#3]%
   \definelist[#1][#3]%
   \copylabeltext[#1=#3]%
   \strc_floats_define_saved[#1][#3]%
   \strc_floats_define_commands{#1}{#2}}

\def\strc_floats_define_b[#1][#2][#3]% name parent settings
  {\definefloatcaption[#1][#2]%
   \definefloatframed[#1][#2]%
   \definecounter[#1][#2]%
   \definelist[#1][#2]%
   \copylabeltext[#1=#2]%
   \strc_floats_define_saved[#1][#2][#3]%
   \strc_floats_define_commands{#1}{#1}}

\def\strc_floats_define_c[#1][#2]% name names
  {\registerfloatcaptioncounter{#1}%
   \definefloatcaption[#1]%
   \definefloatframed[#1]%
   \definecounter[#1]%
   \definelist[#1]%
   \presetlabeltext[#1=\Word{#1}~]%
   \presetheadtext[#2=\Word{#2}]%
   \strc_floats_define_saved[#1]%
   \strc_floats_define_commands{#1}{#2}}

\def\strc_floats_define_commands#1#2%
  {\frozen\protected\instance\edefcsname\e!place      \e!listof#2\endcsname{\strc_lists_place[#1]}% call will change
   \frozen\protected\instance\edefcsname\e!complete   \e!listof#2\endcsname{\strc_lists_complete[#1][#2]}% call will change
   \frozen\protected\instance\edefcsname\e!place               #1\endcsname{\placefloat[#1]}%
   \frozen\protected\instance\edefcsname\e!start       \e!place#1\endcsname{\startplacefloat[#1]}%
   \frozen\protected\instance\edefcsname\e!stop        \e!place#1\endcsname{\stopplacefloat}%
   \frozen\protected\instance\edefcsname\e!start        #1\e!text\endcsname{\startfloattext[#1]}%
   \frozen\protected\instance\edefcsname\e!stop         #1\e!text\endcsname{\stopfloattext}%
   \frozen\protected\instance\edefcsname\e!start\e!place#1\e!text\endcsname{\startplacefloattext[#1]}%
   \frozen\protected\instance\edefcsname\e!stop \e!place#1\e!text\endcsname{\stopplacefloattext}%
   % these will become obsolete:
   \frozen\instance\protected\edefcsname\e!reserve               #1\endcsname{\strc_floats_reserve[#1]}%
   \frozen\instance\protected\edefcsname\e!start\e!reserve#1\e!text\endcsname{\strc_floats_start_reserve_text[#1]}%
   \frozen\instance\protected\edefcsname\e!stop \e!reserve#1\e!text\endcsname{\strc_floats_stop_reserve_text}}

%D Fallback float body:

\protected\def\strc_floats_place_empty_box % \inheritedfloatframed
  {\framed
     [\c!frame=\v!on,
      \c!width=\rootfloatparameter\c!width,
      \c!height=\rootfloatparameter\c!height,
      \c!location=\v!normal,
      \c!offset=\rootfloatparameter\c!offset]%
     {\getmessage\m!floatblocks{12}\empty}}

%D Data. We can generalize this to lists.

\newif\ifnofloatcaption
\newif\ifnofloatnumber
\newif\ifemptyfloatcaption

\installstructurelistprocessor\s!float{\usestructurelistprocessor{number+title}}

\permanent\protected\def\thecurrentfloatnumbersuffix
  {\ifempty{\floatcaptionparameter\c!suffix}\else
     \floatcaptionparameter\c!suffixseparator
     \floatcaptionparameter\c!suffix
     \floatcaptionparameter\c!suffixstopper
   \fi}

\permanent\protected\def\thecurrentfloatnumber
  {\ifnofloatcaption \orelse \ifnofloatnumber \orelse \ifrelax\currentfloatnumber \else
     \namedtaggedlabeltexts
       \t!floatlabel \currentfloat
       \t!floatnumber\currentfloat
       {\begstrut
        \floatcaptionparameter\c!numbercommand
          {\clf_savedlistprefixednumber{\currentfloat}\currentfloatnumber\relax
           \thecurrentfloatnumbersuffix}%
        \endstrut}%
   \fi}

\permanent\protected\def\thecurrentfloatcaption
  {\ifnofloatcaption \orelse \ifemptyfloatcaption \orelse \ifrelax\currentfloatnumber \else
     \dostarttaggednodetail\t!floattext
     \begstrut
     \floatcaptionparameter\c!textcommand
       {\clf_savedlisttitle{\currentfloat}{\currentfloatnumber}}%
     \endstrut
     \dostoptagged
   \fi}

%D Captions.

\mutable\lettonothing\floatcaptionarrangement
\mutable\lettonothing\floatcaptionattribute
\mutable\lettonothing\floatcaptiondirectives
\mutable\lettonothing\floatcaptionlocation
\mutable\lettonothing\floatcaptionnumber
\mutable\lettonothing\floatcaptionsuffix

% For a while these were placeholders:
%
%D \starttyping
%D \protected\def\placefloatcaption{\dodoubleempty\strc_floats_place_caption}
%D \protected\def\setfloatcaption  {\dodoubleempty\strc_floats_set_caption}
%D
%D \def\strc_floats_place_caption[#tag][#reference]#caption{[not supported]}
%D \def\strc_floats_set_caption  [#tag][#reference]#caption{[not supported]}
%D
%D \protected\def\placefloatcaptiontext     [#tag]{[not suported yet]}
%D \protected\def\placefloatcaptionnumber   [#tag]{[not suported yet]}
%D \protected\def\placefloatcaptionreference[#tag]{[not suported yet]}
%D \stoptyping
%D
%D because in \MKII\ we had:
%D
%D \starttyping
%D \let\placefloatlabel         \placefloatcaption
%D \let\placefloatlabeltext     \placefloatcaptiontext
%D \let\placefloatlabelreference\placefloatcaptionreference
%D \stoptyping
%D
%D But as it was never advertised we don't provide it in \MKIV. However, at some
%D point HvdM wanted this:
%D
%D \starttyping
%D \placefigure                     {labeltext-1}  {\externalfigure[figure-1]}
%D \placefloatcaption[figure][title={labeltext-2}]  \externalfigure[figure-2]
%D \placefigure                     {labeltext-3}  {\externalfigure[figure-3]}
%D \stoptyping
%D
%D So there you have it:

\def\strc_floats_open_up_caption
  {\vpack\bgroup
     \offinterlineskip
     \vkern\scratchtopoffset
     \strc_floats_make_complete_caption
     \vkern\scratchbottomoffset
   \egroup}

\permanent\tolerant\protected\def\placefloatcaption[#category]#spacer[#S#settings]#spacer[#S#userdata]%
  {\ifarguments\or\else % >= 2
     % we need at least a category and title
     \dontleavehmode
     \bgroup
     \cdef\currentfloat{#category}%
     \let\currentfloatcaption\currentfloat
     \resetfloatcaptionparameter\c!reference
     \resetfloatcaptionparameter\c!title
     \resetfloatcaptionparameter\c!marking
     \resetfloatcaptionparameter\c!list
     \resetfloatcaptionparameter\c!bookmark
     \resetfloatcaptionparameter\c!referencetext
     \setupcurrentfloatcaption[#settings]%
     \edef\currentfloatcounter{\namedcounterparameter\currentfloat\s!name}%
     \iftrialtypesetting\strc_counters_save\currentfloatcounter\fi
% \strc_floats_reset_variables
\global\emptyfloatcaptionfalse
\global\nofloatcaptionfalse
     \ifcstok{\floatcaptionparameter\c!number}\v!yes
       \global\nofloatnumberfalse
     \else
       \global\nofloatnumbertrue
     \fi
     \ifnofloatnumber\else
       \strc_counters_increment\currentfloatcounter
     \fi
     \strc_counters_register_component
       \s!float
       \setupcurrentfloatcaption
       \floatcaptionparameter
       \detokenizedfloatcaptionparameter
       \relax
       \relax
       \relax
       [\s!name=\currentfloat,
        \s!counter=\currentfloatcounter,%
        \s!hascaption=\v!yes,%
        \s!hasnumber=\ifnofloatnumber\v!no\else\v!yes\fi,%
        \s!hastitle=\v!yes]%
       [#userdata]%
     \glet\m_strc_floats_previous_number\m_strc_counters_last_registered_index
     \glet\currentfloatnumber           \m_strc_counters_last_registered_index
     \glet\currentfloatattribute        \m_strc_counters_last_registered_attribute
     \glet\currentfloatsynchronize      \m_strc_counters_last_registered_synchronize
     %
   % \iflocation
   %    \c_attr_destination\currentfloatattribute\relax
   % \fi
     \currentfloatsynchronize
%      \strc_floats_make_complete_caption
 \strc_floats_set_open_up\strc_floats_open_up_caption\strc_floats_make_complete_caption
     %
     \iftrialtypesetting\strc_counters_restore\currentfloatcounter\fi
     \egroup
   \fi}

\newbox      \b_strc_floats_caption
\newbox      \b_strc_floats_content
\newdimension\d_strc_floats_caption_height
\newdimension\d_strc_floats_caption_depth

\lettonothing\m_strc_floats_last_caption_tag

\def\strc_floats_make_incomplete_caption
  {\gdef\m_strc_floats_last_caption_tag{\strut\thecurrentfloatnumber}% was xdef ... needs checking
   \begingroup
     \ifnofloatcaption
       % whatever
     \else
       \usefloatcaptionstyleandcolor\c!style\c!color
       \clf_doifelselisthastitle{\currentfloat}{\currentfloatnumber}%
         \donothing
         \emptyfloatcaptiontrue
       \ifnofloatnumber
         % nothing
       \orelse\ifnofloatcaption
         % nothing
       \orelse\ifemptyfloatcaption
         \hbox{\usefloatcaptionstyleandcolor\c!headstyle\c!headcolor\thecurrentfloatnumber}%
       \else
         \emergencystretch.5\scratchskip % really in lmtx?
         \scratchskip\glueexpr\floatcaptionparameter\c!distance\relax
         \usefloatcaptionstyleandcolor\c!headstyle\c!headcolor
         \thecurrentfloatnumber
         \floatcaptionparameter\c!headseparator
         \dotfskip\scratchskip
       \fi
       \usefloatcaptionstyleandcolor\c!textstyle\c!textcolor
       \thecurrentfloatcaption\endgraf
     \fi
     \global\d_strc_floats_caption_height\zeropoint
     \global\d_strc_floats_caption_depth \zeropoint
   \endgroup}

\def\strc_floats_make_complete_caption
  {% todo: only one of the blanks when empty
   \ifempty{\floatcaptionparameter\c!spacebefore}\else
     \blank[\floatcaptionparameter\c!spacebefore]%
   \fi
   \strc_floats_make_complete_caption_before
   \synchronizedisplaydirection % temp hack, till we have a proper model
   \noindent
   \gdef\m_strc_floats_last_caption_tag{\strut\thecurrentfloatnumber}% was xdef ... needs checking
   \begingroup
     \ifnofloatcaption
       \global\d_strc_floats_caption_height\zeropoint
       \global\d_strc_floats_caption_depth \zeropoint
     \else
       \usefloatcaptionstyleandcolor\c!style\c!color
       \clf_doifelselisthastitle{\currentfloat}{\currentfloatnumber}%
         \donothing
         \emptyfloatcaptiontrue
       \ifnofloatnumber
         % nothing
       \orelse\ifnofloatcaption
         % nothing
       \orelse\ifemptyfloatcaption
         \hbox{\usefloatcaptionstyleandcolor\c!headstyle\c!headcolor\thecurrentfloatnumber}%
       \orelse\ifempty{\floatcaptionparameter\c!spaceinbetween}%
         \scratchskip\glueexpr\floatcaptionparameter\c!distance\relax
         \setbox\scratchbox\hbox
           {\usefloatcaptionstyleandcolor\c!headstyle\c!headcolor
            \thecurrentfloatnumber
            \floatcaptionparameter\c!headseparator
            \dotfskip\scratchskip}%
         \emergencystretch.5\scratchskip % really in lmtx?
         \ifcstok{\floatcaptionparameter\c!hang}\v!yes
           \leftskip\wd\scratchbox
           \llap{\box\scratchbox}%
         \else
           \unhbox\scratchbox
         \fi
       \else
         \hbox{\usefloatcaptionstyleandcolor\c!headstyle\c!headcolor\thecurrentfloatnumber}%
         \blank[\floatcaptionparameter\c!spaceinbetween]%
       \fi
       \usefloatcaptionstyleandcolor\c!textstyle\c!textcolor
       \global\d_strc_floats_caption_height\strutheight
       \global\d_strc_floats_caption_depth \strutdepth
       \thecurrentfloatcaption\endgraf
     \fi
   \endgroup
   \strc_floats_make_complete_caption_after
   \ifempty{\floatcaptionparameter\c!spaceafter}\else
     \blank[\floatcaptionparameter\c!spaceafter]% \expanded{...\lastnamedcs}%
   \fi}

%let\strc_floats_make_complete_caption_before\relax
\let\strc_floats_make_complete_caption_after \relax

\def\strc_floats_make_complete_caption_before
  {\doifelseframed\floatcaptionparameter\strc_floats_make_complete_caption_before_indeed\relax}

\def\strc_floats_make_complete_caption_before_indeed
  {\edef\m_strc_align{\floatcaptionparameter\c!align}%
   \edef\m_strc_strut{\floatcaptionparameter\c!strut}%
   \letfloatcaptionparameter\c!align\v!normal
   \letfloatcaptionparameter\c!strut\v!no
   \inheritedfloatcaptionframed
   \bgroup
   \letfloatcaptionparameter\c!align\m_strc_align
   \letfloatcaptionparameter\c!strut\m_strc_strut
   \let\strc_floats_make_complete_caption_after\egroup}

% \definefloat  [figure-1] [figure]
% \definefloat  [figure-2] [figure]
% \setupfloat   [figure-1] [location=left,leftmargin=10mm]
% \setupfloat   [figure-2] [location=left,leftmargin=-5mm]
% \setupcaption [figure-1] [align=flushleft]
% \setupcaption [figure-2] [align=flushleft,leftmargin=15mm]
%
% \startsetups somefigure
%     \ifdim\wd\nextbox>\textwidth
%         \placefloat[figure-2][][]{}{\box\nextbox}
%     \else
%         \placefloat[figure-1][][]{}{\box\nextbox}
%     \fi
% \stopsetups
%
% \protected\def\setupswithbox[#1]{\dowithnextbox{\setups[#1]}\vbox}
%
% test \setupswithbox[somefigure]{\framed[width=3cm]           {}} test
% test \setupswithbox[somefigure]{\framed[width=\textwidth+3cm]{}} test

% temporary removed ... was not applied systematically
%
% \def\dosetcaptionthings
%   {\usesetupsparameter\floatcaptionparameter}

\def\strc_floats_check_caption_content
  {\ifnofloatcaption
   \orelse\ifconditional\c_strc_floats_ornament_caption
   \else
     \setbox\b_strc_floats_caption\hbox
       {\settrialtypesetting
        \notesenabledfalse
        \strc_floats_make_complete_caption}%
     % new, \placefigure{\xmlfirst{#1}{somecaption}}{} passes earlier empty check
     % so here we misuse the scratch box; actually this means that the previous
     % test can go away (some day, when i redo this module)
     \ifzeropt\wd\b_strc_floats_caption
       \global\emptyfloatcaptiontrue
       \ifnofloatnumber
         \global\nofloatcaptiontrue
       \fi
     \else
       \global\emptyfloatcaptionfalse
       \setbox\b_strc_floats_caption\hpack{\hskip\leftskip\box\b_strc_floats_caption}%
     \fi
   \fi}

\def\strc_floats_apply_caption_command
  {\setbox\b_strc_floats_caption\hbox\bgroup
    %\unless\ifempty{\floatcaptionparameter\c!command}
       \floatcaptionparameter\c!command{\box\b_strc_floats_caption}%
    %\orunless\ifempty{\floatcaptionparameter\c!deeptextcommand}%
    %  \floatcaptionparameter\c!deeptextcommand{\unvbox\b_strc_floats_caption}%
    %\else
    %  \box\b_strc_floats_caption
    %\fi
   \egroup}

%D Some trickery (example by MS):
%D
%D \starttyping
%D \defineframed
%D   [MyCaptionFramed]
%D   [align={lohi,flushleft},
%D    width=fit,
%D    frame=off,
%D    strut=no,
%D    topframe=on,
%D    loffset=1em,
%D    toffset=0.25\lineheight]
%D
%D \starttexdefinition protected MyCaption #1
%D     \MyCaptionFramed {
%D         % we ignore #1 as we want to unpack
%D         \unvbox\floatcaptionbox
%D     }
%D \stoptexdefinition
%D
%D \definefloat[pagefloat][pagefloats][graphic]
%D
%D \setupfloat
%D   [pagefloat]
%D   [default={page,header,footer}]
%D
%D \setupcaption
%D   [pagefloat]
%D   [location={top,inner},
%D    align=inner,
%D    command=\MyCaption,
%D    spaceinbetween=nowhite]
%D \stoptyping

\permanent\protected\def\floatcaptionbox{\b_strc_floats_caption}

%D We can do this ...
%D
%D \starttyping
%D \newinteger\c_strc_floats_n
%D
%D \definedataset[\s!float][\c!delay=\v!yes]
%D
%D \let\strc_float_realpage\realpageno
%D
%D \def\strc_float_save_data
%D   {\setdataset[\s!float][\the\c_strc_floats_n][]}
%D
%D \def\strc_float_load_data % precedes save !
%D   {\global\advanceby\c_strc_floats_n\plusone
%D    \xdef\strc_float_realpage{\datasetvariable\s!float{\the\c_strc_floats_n}\s!page}%
%D    \ifempty\strc_float_realpage
%D      \glet\strc_float_realpage\realpageno % \realfolio
%D    \fi}
%D \stoptyping
%D
%D ... but this is more efficient:

\definepagestate[\s!float][\c!delay=\v!yes]

\newinteger\c_strc_floats_n

\let\strc_float_realpage\realpageno

\def\strc_float_save_data
  {\setpagestate[\s!float][\the\c_strc_floats_n]}

\def\strc_float_load_data % precedes save !
  {\global\advanceby\c_strc_floats_n\plusone
   \xdef\strc_float_realpage{\pagestaterealpage\s!float{\the\c_strc_floats_n}}%
   \ifempty\strc_float_realpage
     \glet\strc_float_realpage\realpageno % \realfolio
   \fi}

%D test case:
%D
%D \starttyping
%D \setupfloat[figure][criterium=\marginwidth,fallback=bottom]
%D \dorecurse{3}{
%D     \chapter{test}
%D     \placefigure[bottom]{1}{\framed{bottom}}
%D     test
%D     \placetable[bottom]{1}{\framed{table}}
%D     test
%D     \placetable{2}{\framed{table}}
%D     test
%D     \placefigure[left]{2}{\framed{left but way too wide}}
%D     \input tufte
%D     \placefigure[left]{3}{\framed{left but ok}}
%D     \input tufte }
%D \stoptyping

% A complication is that we may have to handle a pagebreak first, which in turn may
% issue a (postponed) float. Therefore we may not trust on variable assignments
% before we're really dealing with the float. Some day I'll root out the global
% settings.

\aliased\lettonothing\lastplacedfloat

\def\strc_floats_set_current_tag#tag%
  {\cdef\currentfloat{#tag}%
   \ifempty\currentfloat
     \let\currentfloat\v!figure % a bit of a hack
   \fi
   \doifelsecommandhandler\??float\currentfloat
     \donothing
     {\writestatus\m!floatblocks{unknown float type '\currentfloat'}%
      \let\currentfloat\v!figure}% also a hack
   \enforced\glet\lastplacedfloat\currentfloat
   \lettonothing\m_strc_floats_saved_userdata
   \let\currentfloatcaption\currentfloat}

\mutable\lettonothing\askedfloatmethod
\mutable\lettonothing\askedfloatoptions

\def\strc_floats_reset_variables
  {\global\emptyfloatcaptionfalse
   \global\nofloatcaptionfalse
   \global\nofloatnumberfalse
   \glettonothing\askedfloatmethod
   \glettonothing\askedfloatoptions}

% place

\mutable\lettonothing\floatlabel
\mutable\lettonothing\floatcolumn
\mutable\lettonothing\floatrow
\mutable\lettonothing\floatlocation
\mutable\lettonothing\floatlocationmethod
\mutable\lettonothing\floatlocationdefault

\def\strc_floats_analyze_location
  {% more will be moved here
   \lettonothing\floatlabel
   \lettonothing\floatcolumn
   \lettonothing\floatrow
   %
   \edef\floatcaptionlocation{\floatcaptionparameter\c!location}%
   %
   \setfloatmethodvariables\floatlocation}

\newconditional\c_strc_floats_ornament_caption

\def\strc_floats_analyze_caption
  {% more will be moved here
   \ifcsname\??ornament\floatcaptionlocation\endcsname
     \c_strc_floats_ornament_caption\conditionaltrue
   \else
     \c_strc_floats_ornament_caption\conditionalfalse
   \fi}

\newtoks\t_floats_every_table_float

\appendtoks
    \edef\floatlocation{\v!force,\v!always,\floatlocation}%
    \setupfloat[\c!spacebefore=\v!none,\c!spaceafter=\v!none]%
\to \t_floats_every_table_float

\ifdefined\dotagregisterfloat \else \aliased\let\dotagregisterfloat\gobbletwoarguments \fi

\tolerant\def\strc_floats_place[#tag]#spacer[#location]#spacer[#reference]#:#caption%
  {\strc_floats_set_current_tag{#tag}%
   \strc_floats_reset_variables
   \xdef\askedfloatoptions{#location}%
   \edef\floatlocationdefault{\floatparameter\c!default}%
   \edef\floatlocation{#location}%
   \ifempty\floatlocation
     \let\floatlocation\floatlocationdefault % beware of a clash between alignment locations
   \fi
   \ifintable
     \expand\t_floats_every_table_float
   \fi
   \strc_floats_analyze_location
   \strc_floats_analyze_caption
   % todo: use \lets
   \setupcurrentfloatcaption[\c!reference={#reference},\c!title={#caption},\c!marking=,\c!list=,\c!bookmark=,\c!referencetext=]%
   \ifinset\v!split\floatlocation
     \expandafter\strc_floats_place_next_box_split
   \else
     \expandafter\strc_floats_place_next_box_normal
   \fi}

\permanent\protected\def\placefloat
  {\flushnotes
   \page_otr_command_flush_side_floats % here !
   \strc_floats_begin_group
   \strc_floats_place}

% start-stop

% \startplacefigure[title=oeps][subtitle=whatever]
%     \framed[width=10cm,height=5cm]{\floatuserdataparameter{subtitle}}
% \stopplacefigure

\installcorenamespace{floatuserdata}

\installsetuponlycommandhandler \??floatuserdata {floatuserdata}

\lettonothing\m_strc_floats_saved_userdata % todo: reset this in non start|stop cases

%D We abuse the settings to pick up some float parameters too which makes it
%D messy.

%D Do we need a \setuplayout here (kind of costly) in case we mix multi page text
%D with a side float and less height.

\permanent\tolerant\protected\def\startplacefloat[#tag]#spacer[#S#settings]#spacer[#S#userdata]%
  {\flushnotes
  %\setuplayout
   \page_otr_command_flush_side_floats % here !
   \strc_floats_begin_group
   \strc_floats_set_current_tag{#tag}%
   \strc_floats_reset_variables
   % save
   \edef\p_location    {\floatcaptionparameter\c!location}%
   \edef\p_topoffset   {\floatcaptionparameter\c!topoffset}%
   \edef\p_bottomoffset{\floatcaptionparameter\c!bottomoffset}%
   \edef\p_freeregion  {\floatcaptionparameter\c!freeregion}%
   % preset
   \resetfloatcaptionparameter      \c!location
   \setexpandedfloatcaptionparameter\c!topoffset   {\floatparameter\c!topoffset}%
   \setexpandedfloatcaptionparameter\c!bottomoffset{\floatparameter\c!bottomoffset}%
   \setexpandedfloatcaptionparameter\c!freeregion  {\floatparameter\c!freeregion}%
   \resetfloatcaptionparameter      \c!reference
   \resetfloatcaptionparameter      \c!title
   \resetfloatcaptionparameter      \c!marking
   \resetfloatcaptionparameter      \c!list
   \resetfloatcaptionparameter      \c!bookmark
   \resetfloatcaptionparameter      \c!referencetext
   % pickup
   \ifparameter#settings\or
     \setupcurrentfloatcaption[#settings]%
   \fi
   \ifparameter#userdata\or
     \setupcurrentfloatuserdata[#userdata]%
     \def\m_strc_floats_saved_userdata{#userdata}%
   \else
     \lettonothing\m_strc_floats_saved_userdata
   \fi
   \edef\p_mode{\floatcaptionparameter\s!mode}%
   \ifempty\p_mode
     \let\strc_floats_stop_place\strc_floats_stop_place_yes
     \strc_floats_start_place_yes
   \orelse\ifmode{\p_mode}%
     \let\strc_floats_stop_place\strc_floats_stop_place_yes
     \strc_floats_start_place_yes
   \else
     \let\strc_floats_stop_place\strc_floats_stop_place_nop
     \strc_floats_start_place_nop
   \fi}

\def\strc_floats_start_place_yes
  {% check (see elsewhere
   \edef\floatlocationdefault{\floatparameter\c!default}%
   \edef\floatlocation{\floatcaptionparameter\c!location}%
   \ifempty\floatlocation
     \let\floatlocation\floatlocationdefault % beware of a clash between alignment locations
   \fi
   % inherit
   \setexpandedfloatparameter\c!topoffset   {\floatcaptionparameter\c!topoffset}%
   \setexpandedfloatparameter\c!bottomoffset{\floatcaptionparameter\c!bottomoffset}%
   \setexpandedfloatparameter\c!freeregion  {\floatcaptionparameter\c!freeregion}%
   % restore
   \letfloatcaptionparameter\c!location    \p_location
   \letfloatcaptionparameter\c!topoffset   \p_topoffset
   \letfloatcaptionparameter\c!bottomoffset\p_bottomoffset
   \letfloatcaptionparameter\c!freeregion  \p_freeregion
   %
   \strc_floats_analyze_location
   \strc_floats_analyze_caption
   \ifinset\v!split\floatlocation
     \expandafter\strc_floats_place_next_box_split
   \else
     \expandafter\strc_floats_place_next_box_normal
   \fi
   \bgroup
   \ignorespaces}

\def\strc_floats_stop_place_yes
  {\removeunwantedspaces
   \egroup}

\def\strc_floats_start_place_nop
  {\directsetup{\p_mode:\currentfloat:\v!before}%
   \bgroup
   \ignorespaces}

\def\strc_floats_stop_place_nop
  {\removeunwantedspaces
   \egroup
   \directsetup{\p_mode:\currentfloat:\v!after}%
   \strc_floats_end_group}

\permanent\protected\def\stopplacefloat
  {\strc_floats_stop_place}

% reserve

\protected\def\strc_floats_reserve
  {\flushnotes
   \page_otr_command_flush_side_floats % here !
   \strc_floats_begin_group
   \strc_floats_place}

\def\strc_floats_reserve_box#settings%
  {\begingroup
   \setupcurrentfloat[\c!frame=\v!on,#settings]%
   \inheritedfloatframed{}%
   \endgroup}

% text

\permanent\tolerant\protected\def\startfloattext[#tag]#spacer[#location]#spacer[#reference]%
  {\flushnotes      % Here indeed?
   \page_otr_command_flush_side_floats % Here indeed?
   \strc_floats_begin_text_group
   \strc_floats_place[#tag][\v!text,#location,\v!left][#reference]}

\protected\def\stopfloattext
  {\strc_floats_stop_text_indeed}

\ifdefined\startcontent \else \aliased\let\startcontent\relax \fi
\ifdefined\stopcontent  \else \aliased\let\stopcontent \relax \fi
\ifdefined\startentry   \else \aliased\let\startentry  \relax \fi
\ifdefined\stopentry    \else \aliased\let\stopentry   \relax \fi

\permanent\tolerant\protected\def\startplacefloattext[#tag]#spacer[#S#settings]#spacer[#S#userdata]%
  {\begingroup
   %
   \flushnotes % Here indeed?
   \page_otr_command_flush_side_floats % Here indeed?
   %
   \strc_floats_set_current_tag{#tag}%
   \strc_floats_reset_variables
   \resetfloatcaptionparameter\c!location
   \resetfloatcaptionparameter\c!reference
   \resetfloatcaptionparameter\c!title
   \resetfloatcaptionparameter\c!marking
   \resetfloatcaptionparameter\c!list
   \resetfloatcaptionparameter\c!bookmark
   \resetfloatcaptionparameter\c!referencetext
   % pickup
   \ifparameter#settings\or
     \setupcurrentfloatcaption[#settings]%
   \fi
   \xdef\askedfloatoptions{\v!text,\floatcaptionparameter\c!location,\v!left}%
   \edef\floatlocationdefault{\floatparameter\c!default}%
   \let\floatlocation\askedfloatoptions
   \strc_floats_analyze_location
   \strc_floats_analyze_caption
   \resetfloatcaptionparameter\c!location
   \ifparameter#userdata\or
     \setupcurrentfloatuserdata[#userdata]%
     \def\m_strc_floats_saved_userdata{#userdata}%
   \else
     \lettonothing\m_strc_floats_saved_userdata
   \fi
   \enforced\let\startcontent\strc_floats_text_content_start
   \enforced\let\stopcontent\strc_floats_text_content_stop
   \enforced\let\startentry\strc_floats_text_entry_start
   \enforced\let\stopentry \strc_floats_text_entry_stop}

\protected\def\stopplacefloattext
  {\strc_floats_stop_text_indeed
   \endgroup}

\protected\def\strc_floats_text_content_start
  {\setbox\floatbox\vbox\bgroup
   \ignorespaces}

\protected\def\strc_floats_text_content_stop
  {\removeunwantedspaces
   \egroup
   \strc_floats_begin_text_group
   \strc_floats_place_next_box_normal{\box\floatbox}}

\protected\def\strc_floats_text_entry_start
  {\ignorespaces}

\protected\def\strc_floats_text_entry_stop
  {\removeunwantedspaces}

% reserved text

\tolerant\protected\def\strc_floats_start_reserve_text[#tag]#spacer[#S#settings]#spacer[#location]#spacer[#reference]#:#caption%%
  {\flushnotes
   \page_otr_command_flush_side_floats
   \strc_floats_begin_text_group
   \strc_floats_place[#tag][\v!text,#location,\v!left][#reference]{#caption}{\strc_floats_reserve_box{#settings}}}

\protected\def\strc_floats_stop_reserve_text
  {\strc_floats_stop_text_indeed}

% special hack

\def\strc_floats_begin_group     {\begingroup}
\def\strc_floats_end_group       {\carryoverpar\endgroup} % hm
\def\strc_floats_end_split_group {\endgroup}
\def\strc_floats_begin_text_group{\begingroup\let\strc_floats_end_group\relax}
\def\strc_floats_end_text_group  {\endgroup}

% implementation

%setnewconstant\c_page_one_float_method  \zerocount % 0=raw 1=safe (.99) 2=tight (-1pt) / belongs in page-one
\setnewconstant\c_strc_floats_rotation   \zerocount % 0 90 180 270
\newconditional\c_strc_floats_par_float

\ifdefined\page_margin_strc_floats_before    \else \let\page_margin_strc_floats_before   \relax \fi
\ifdefined\page_margin_strc_floats_set_hsize \else \let\page_margin_strc_floats_set_hsize\relax \fi

\immutable\def\flushfloatslist
  {\v!left,\v!right,\v!inner,\v!outer,%
   \v!backspace,\v!cutspace,%
   \v!inleft,\v!inright,\v!inmargin,%
   \v!leftmargin,\v!rightmargin,\v!leftedge,\v!rightedge,%
   \v!innermargin,\v!outermargin,\v!inneredge,\v!outeredge,%
   \v!text,\v!opposite}% \v!page

% \protected\def\strc_floats_place_next_box_split
%   {\let\splitfloatfinalizer\strc_floats_end_split_group
%    \let\strc_floats_end_group\relax
%    \splitfloat{\strc_floats_place_next_box_normal}}

\protected\def\strc_floats_place_next_box_split
  {\let\splitfloatfinalizer\strc_floats_end_split_group
   \let\strc_floats_end_group\relax
  %\ifnumexpression \c_strc_floats_rotation=90 or \c_strc_floats_rotation=270 \relax
   \ifnumexpression (\c_strc_floats_rotation=90) or (\c_strc_floats_rotation=270) \relax
     \splitfloatfixedheight\conditionaltrue
     \def\splitfloatheight{\textwidth}%
   \fi
   \splitfloat{\strc_floats_place_next_box_normal}}

\protected\def\strc_floats_place_next_box_normal
  {\ifconditional\c_page_floats_some_waiting
     % this was \checkwaitingfloats spread all over
     \ifinset\v!always\floatlocation
       \showmessage\m!floatblocks5\empty
     \orelse\ifcommon\floatlocation\flushfloatslist
       \page_otr_command_flush_floats
     \fi
     % but which should be done before using box \floatbox
   \fi
   \page_margin_strc_floats_before % todo: each float handler gets a before
   \global\insidefloattrue
   \dostarttaggedchained\t!float\currentfloat\currentfloat\??float
   \page_margin_strc_floats_set_hsize % todo: each float handler gets a set_hsize
   \expand\everyinsidefloat
   \strc_floats_analyze_variables_one
   \dostarttaggednodetail\t!floatcontent
   \dowithnextboxcontent
     {\strc_floats_set_local_hsize
      \floatparameter\c!inner
      \postponenotes} % new
     {\page_postprocessors_linenumbers_box\nextbox % for aditya
      \dostoptagged
      \strc_floats_finish_placement}
     \vbox}

%D \starttyping
%D \definefloat
%D   [one] [figure]
%D   [default=right,
%D    rightmargindistance=-20cm,
%D    criterium=129pt,
%D    fallback=rightmargin]
%D
%D \definefloat
%D   [two] [figure]
%D   [default=right,
%D    rightmargindistance=-20cm,
%D    criterium=129pt,
%D    fallback=three]
%D
%D \definefloat
%D   [three] [figure]
%D   [default=rightmargin,
%D    rightmargindistance=0cm]
%D
%D \placefloat[one]{}{\blackrule[width=30pt]}  \samplefile{tufte}
%D \placefloat[one]{}{\blackrule[width=60pt]}  \samplefile{tufte}
%D \placefloat[one]{}{\blackrule[width=90pt]}  \samplefile{tufte}
%D \placefloat[one]{}{\blackrule[width=130pt]} \samplefile{tufte}
%D \placefloat[two]{}{\blackrule[width=130pt]} \samplefile{tufte}
%D \stoptyping

\def\strc_floats_finish_placement
  {\ifempty{\floatparameter\c!criterium}\else
     \ifdim\wd\nextbox>\floatparameter\c!criterium\relax
       \edef\forcedfloatmethod{\floatparameter\c!fallback}%
       \ifempty\forcedfloatmethod \else
         \doifelsecommandhandler\??float\forcedfloatmethod
           {\let\currentfloat\forcedfloatmethod
            \edef\floatlocationdefault{\floatparameter\c!default}%
            \let\floatlocation\floatlocationdefault
            \let\forcedfloatmethod\floatlocationdefault}
           \donothing
       \fi
       \ifempty\forcedfloatmethod
         \let\forcedfloatmethod\v!here
       \fi
     \fi
   \fi
   \strc_floats_check_extra_actions
   \strc_floats_analyze_variables_two
   \strc_floats_place_packaged_boxes
   \dotagregisterfloat\askedfloatoptions\askedfloatmethod
   \dostoptagged % tricky .... needs checking
   % we need to carry over the par because of side floats
   \global\d_page_sides_downshift \zeropoint
   \global\d_page_sides_extrashift\zeropoint
   \ifconditional\c_strc_floats_par_float
     \ifinset\v!reset\floatlocation
       \page_sides_forget_floats
     \fi
     \doinhibitblank
   \fi
   \strc_floats_end_group}

% nicer is a bunch of states and one loop that sets those states

\newdimension\d_strc_floats_top
\newdimension\d_strc_floats_bottom
\newdimension\d_strc_floats_overflow

% \def\strc_floats_calculate_skip#target#skip%
%   {\begingroup
%    \edef\askedfloatskip{\rootfloatparameter#skip}%
%    \ifempty\askedfloatskip
%      \global#target\zeropoint
%    \orelse\ifx\askedfloatskip\v!none
%      \global#target\zeropoint
%    \else
%      \setbox\scratchbox\vbox{\whitespace\blank[\askedfloatskip]}% todo: move whitespace inside blank
%      \global#target\ht\scratchbox
%    \fi
%    \endgroup}

\def\strc_floats_calculate_skip#target#skip%
  {\begingroup
   \edef\p_blank{\rootfloatparameter#skip}%
   \ifx\p_blank\v!nowhite
     \edef\p_blank{-\v!white}%
   \fi
   \prerollblank[\p_blank]%
   \global#target\prerolledblank
   \endgroup}

\def\strc_floats_analyze_variables_two
  {\ifinsidecolumns
     \global\c_strc_floats_par_float\conditionalfalse
   \orelse\ifcommon\floatlocation\flushfloatslist
     \global\c_strc_floats_par_float\conditionaltrue
   \else
     \global\c_strc_floats_par_float\conditionalfalse
   \fi
   % variable initializations
   \global\d_page_sides_shift       \zeropoint
   \global\d_page_sides_maximum     \zeropoint
   \global\c_page_sides_align       \zerocount
   \global\c_page_sides_tolerance   \zerocount
   \global\c_page_sides_skipmode    \zerocount
   \global\c_strc_floats_rotation   \zerocount
   \global\d_page_sides_margin      {\floatparameter\c!margin}%
   \global\d_page_sides_leftshift   {\floatparameter\c!leftmargindistance}%
   \global\d_page_sides_rightshift  {\floatparameter\c!rightmargindistance}%
   \global\d_page_sides_topoffset   {\floatparameter\c!topoffset}%
   \global\d_page_sides_bottomoffset{\floatparameter\c!bottomoffset}%
   \global\c_page_sides_method      \floatparameter\c!sidemethod
   \global\c_page_one_float_method  \floatparameter\c!textmethod
   \global\c_page_floats_n_of_top   \rootfloatparameter\c!ntop
   \global\c_page_floats_n_of_bottom\rootfloatparameter\c!nbottom
   \global\d_strc_floats_overflow   \zeropoint
   \global\c_page_sides_shape_down\conditionalfalse
   \ifconditional\c_strc_floats_par_float
     \global\d_strc_floats_top        \zeropoint
     \global\d_strc_floats_bottom     \zeropoint
     \strc_floats_calculate_skip\d_page_sides_topskip   \c!sidespacebefore
     \strc_floats_calculate_skip\d_page_sides_bottomskip\c!sidespaceafter
     \strc_floats_calculate_skip\d_page_sides_midskip   \c!sidespaceinbetween
     \strc_floats_calculate_skip\d_strc_floats_top      \c!spacebeforeside
     \strc_floats_calculate_skip\d_strc_floats_bottom   \c!spaceafterside
   \else
     \global\d_page_sides_topskip     \zeropoint
     \global\d_page_sides_bottomskip  \zeropoint
     \strc_floats_calculate_skip\d_strc_floats_top   \c!spacebefore
     \strc_floats_calculate_skip\d_strc_floats_bottom\c!spaceafter
   \fi
   % keyword handling
   \ifconditional\c_strc_floats_par_float
     \processaction
       [\floatparameter\c!sidealign]
       [\v!height=>\global\c_page_sides_align\plusone  ,%
          \v!line=>\global\c_page_sides_align\plustwo  ,% (***)
         \v!depth=>\global\c_page_sides_align\plusthree,%
          \v!grid=>\global\c_page_sides_align\plusfour ,%
      \v!halfline=>\global\c_page_sides_align\plusfive ]%
     \ifcase\c_page_sides_align\relax % todo: optie v!lokaal => \else
       \ifinset\v!height  \floatlocation\global\c_page_sides_align\plusone  \fi
       \ifinset\v!line    \floatlocation\global\c_page_sides_align\plustwo  \fi
       \ifinset\v!depth   \floatlocation\global\c_page_sides_align\plusthree\fi
       \ifinset\v!grid    \floatlocation\global\c_page_sides_align\plusfour \fi
       \ifinset\v!halfline\floatlocation\global\c_page_sides_align\plusfive \fi % meant for 'none'
     \fi
     \ifinset\v!high        \floatlocation\global\c_page_sides_skipmode \plusone  \fi
     \ifinset\v!low         \floatlocation\global\c_page_sides_skipmode \plustwo  \fi
     \ifinset\v!fit         \floatlocation\global\c_page_sides_skipmode \plusthree\fi
     \ifinset\v!tolerant    \floatlocation\global\c_page_sides_tolerance\plusone  \fi
     \ifinset\v!verytolerant\floatlocation\global\c_page_sides_tolerance\plustwo  \fi
   \else
     \processallactionsinset
       [\floatlocation]%
       [ 90=>\global\c_strc_floats_rotation\commalistelement\relax,%
        180=>\global\c_strc_floats_rotation\commalistelement\relax,%
        270=>\global\c_strc_floats_rotation\commalistelement\relax]%
   \fi
   \ifinset\v!paragraph\floatlocation
     \global\c_page_sides_force_shape\conditionaltrue
   \else
     \global\c_page_sides_force_shape\conditionalfalse
   \fi
   \ifinset\v!append\floatlocation
     \global\c_floats_append_to_stored\conditionaltrue
   \else
     \global\c_floats_append_to_stored\conditionalfalse
   \fi
   \ifinset\v!force\floatlocation
     \global\c_floats_force         \conditionaltrue
     \global\c_page_sides_shape_down\conditionaltrue  % might be changed later
   \else
     \global\c_floats_force         \conditionalfalse
     \global\c_page_sides_shape_down\conditionalfalse % might be changed later
   \fi
   \ifinset\v!keeptogether\floatlocation
     \global\c_page_sides_keep_together\conditionaltrue
   \else
     \global\c_page_sides_keep_together\conditionalfalse
   \fi
   \ifinset\v!nonumber\floatlocation
     \global\nofloatnumbertrue
   \orelse\ifcstok{\floatcaptionparameter\c!number}\v!yes
     \global\nofloatnumberfalse
   \else
     \global\nofloatnumbertrue
   \fi
   \ifinset\v!none\floatlocation
     \global\nofloatcaptiontrue
   \else
     \global\nofloatcaptionfalse
   \fi
   \ifcstok{\floatcaptionparameter\c!number}\v!none % new
     \global\nofloatcaptiontrue
   \fi
   \ifinset\v!effective\floatlocation
     \letfloatparameter       \c!leftmargin \effectiveleftskip
     \letfloatparameter       \c!rightmargin\effectiverightskip
     \letfloatcaptionparameter\c!leftmargin \effectiveleftskip
     \letfloatcaptionparameter\c!rightmargin\effectiverightskip
   \fi
   \ifemptyfloatcaption \ifnofloatnumber
     \global\nofloatcaptiontrue
   \fi \fi}

% documenteren in details

\def\strc_floats_analyze_variables_one
  {\ifcstok{\floatparameter\c!local}\v!yes % fout keyword
     \c_page_floats_center_box_global\conditionaltrue
   \else
     \c_page_floats_center_box_global\conditionalfalse
   \fi
   \ifconditional\c_page_floats_center_box_global
     \c_page_floats_center_box_local\conditionaltrue
   \orelse\ifinset\v!local\floatlocation
     \c_page_floats_center_box_local\conditionaltrue
   \else
     \c_page_floats_center_box_local\conditionalfalse
   \fi
   \ifcstok{\floatparameter\c!freeregion}\v!yes
     \c_strc_floats_mark_as_free\conditionaltrue
   \else
     \c_strc_floats_mark_as_free\conditionalfalse
   \fi
   \ifcommon{\v!always,\v!here,\v!force}\floatlocation
     % ! ! ! ! ! !
   \else
     \c_page_floats_center_box_global\conditionalfalse
     \c_page_floats_center_box_local\conditionalfalse
   \fi}

\permanent\def\naturalfloatheight{\the\naturalfloatwd}
\permanent\def\naturalfloatwidth {\the\naturalfloatht}
\permanent\def\naturalfloatdepth {\the\naturalfloatdp}

\permanent\def\floatcaptionheight{\the\floatcaptionwd}
\permanent\def\floatcaptionwidth {\the\floatcaptionht}
\permanent\def\floatcaptiondepth {\the\floatcaptiondp}

\newdimension\naturalfloatwd
\newdimension\naturalfloatht
\newdimension\naturalfloatdp

\newdimension\floatcaptionwd
\newdimension\floatcaptionht
\newdimension\floatcaptiondp

\def\strc_floats_set_natural_dimensions#box%
  {\global\naturalfloatwd\wd#box\relax
   \global\naturalfloatht\ht#box\relax
   \global\naturalfloatdp\dp#box\relax}

\def\strc_floats_set_caption_dimensions#box%
  {\global\floatcaptionwd\wd#box\relax
   \global\floatcaptionht\ht#box\relax
   \global\floatcaptiondp\dp#box\relax}

\permanent\def\doifelsemainfloatbody
  {\unless\ifinsidesplitfloat
     \expandafter\firstoftwoarguments
   \orelse\ifconditional\splitfloatfirstdone
     \expandafter\secondoftwoarguments
   \else
     \expandafter\firstoftwoarguments
   \fi}

\aliased\let\doifmainfloatbodyelse\doifelsemainfloatbody

% todo: optional user pars

\def\floatcaptionattribute
  {\iflocation
     \ifempty\currentfloatattribute
       % safeguard, can be samepage too
     \orelse\ifnofloatcaption
     \orelse\ifinsidesplitfloat
       \ifconditional\splitfloatfirstdone
       \else
         attr \destinationattribute \currentfloatattribute
       \fi
     \else
       attr \destinationattribute \currentfloatattribute
     \fi
   \fi}

% \def\floatcaptionattribute
%   {\iflocation
%      \ifempty\currentfloatattribute
%        % safeguard, can be samepage too
%      \orelse\ifnofloatcaption
%        % nothing
%      \orunless\ifinsidesplitfloat
%        attr \destinationattribute \currentfloatattribute
%      \orunless\ifconditional\splitfloatfirstdone
%        attr \destinationattribute \currentfloatattribute
%      \fi
%    \fi}

\newconditional\usesamefloatnumber

% \startplacefigure[location=here,reference=first, title=first, group=alpha,groupsuffix=.a]
%     \externalfigure[dummy][height=2cm]
% \stopplacefigure
% \startplacefigure[location=here,reference=second,title=second,group=alpha,groupsuffix=.b]
%     \externalfigure[dummy][height=2cm]
% \stopplacefigure
%
% uses:

\def\strc_floats_group_index
  {\numexpr\clf_listgroupindex{\currentfloat}{\currentfloatgroup}\relax}

%D A lightweight subnumber feature:
%D
%D \starttyping
%D \startplacefigure [location=none]
%D   \startsubfloatnumbering
%D     \startfloatcombination [nx=3]
%D       \startplacefigure [title=Left]   \externalfigure \stopplacefigure
%D       \startplacefigure [title=Middle] \externalfigure \stopplacefigure
%D       \startplacefigure [title=Right]  \externalfigure \stopplacefigure
%D     \stopfloatcombination
%D   \stopsubfloatnumbering
%D \stopplacefigure
%D \stoptyping

\glettonothing\currentsubfloatcounter

\permanent\protected\def\startsubfloatnumbering
  {\glet\currentsubfloatcounter\s!unknown}

\permanent\protected\def\stopsubfloatnumbering
  {\strc_counters_reset_sub\currentsubfloatcounter\plustwo
   \glettonothing\currentsubfloatcounter}

\defineconversionset[subfloats][number,characters]

\setupcaptions
 %[figure]
  [\c!numberconversionset=subfloats]

\def\strc_floats_place_packaged_boxes
  {\expandafter\strc_floats_place_packaged_boxes_indeed\expandafter{\m_strc_floats_saved_userdata}}

\def\strc_floats_place_packaged_boxes_indeed#userdata%
  {\bgroup
   \ifconditional\usesamefloatnumber
     \glet\currentfloatnumber\m_strc_floats_previous_number
     \glettonothing\currentfloatattribute
     \glet\currentfloatsynchronize\relax
   \else
     \edef\currentfloatcounter{\namedcounterparameter\currentfloat\s!name}%
     \edef\currentfloatgroup  {\floatcaptionparameter\c!group}%
     \ifnofloatnumber
     \orelse\ifnofloatcaption
     \orelse\ifempty\currentfloatgroup
       % independent
       \iftrialtypesetting\strc_counters_save\currentfloatcounter\fi
       \ifempty\currentsubfloatcounter
         \strc_counters_increment\currentfloatcounter
         \strc_counters_reset_sub\currentfloatcounter\plustwo
       \else
         \ifcase\strc_counters_raw_sub\currentfloatcounter\plustwo\relax
           \strc_counters_increment\currentfloatcounter
           \strc_counters_reset_sub\currentfloatcounter\plustwo
         \fi
         \strc_counters_increment_sub\currentfloatcounter\plustwo
         \glet\currentsubfloatcounter\currentfloatcounter
       \fi
     \orelse\ifcase\strc_floats_group_index
       % first in group
       \iftrialtypesetting\strc_counters_save\currentfloatcounter\fi
       \strc_counters_increment\currentfloatcounter
     \else
       % next in group
     \fi
     % *1* as an alternative we could set counter parameters here if needed
     \strc_counters_register_component
       \s!float
       \setupcurrentfloatcaption
       \floatcaptionparameter
       \detokenizedfloatcaptionparameter
       \relax
       \relax
       \relax
       [\s!name=\currentfloat,% was c!name
        \s!counter=\currentfloatcounter,%
        \s!hascaption=\ifnofloatcaption \v!no\else\v!yes\fi,%
        \s!hasnumber=\ifnofloatnumber   \v!no\else\v!yes\fi,%
        \s!hastitle=\ifemptyfloatcaption\v!no\else\v!yes\fi]%
       [#userdata]%
     \glet\m_strc_floats_previous_number\m_strc_counters_last_registered_index
     \glet\currentfloatnumber           \m_strc_counters_last_registered_index
     \glet\currentfloatattribute        \m_strc_counters_last_registered_attribute
     \glet\currentfloatsynchronize      \m_strc_counters_last_registered_synchronize
   \fi
   %
   \iftrialtypesetting\else\global\usesamefloatnumber\conditionalfalse\fi % one shot
   % check float box
   \strc_floats_set_natural_dimensions\nextbox
   \global\setbox\floatbox\vbox{\floatparameter\c!command{\box\nextbox}}% can be anything so no pack
   \strc_floats_set_natural_dimensions\floatbox
   \ifzeropt\htdp\floatbox
     \showmessage\m!floatblocks{11}\empty
     \global\setbox\floatbox\vpack
       {\dostarttaggednodetail\t!floatcontent
        \strc_floats_place_empty_box
        \dostoptagged}%
   \fi
   % deal with lack of caption
   \global\setbox\floatbox\vpack \floatcaptionattribute
     {\doifelsemainfloatbody\currentfloatsynchronize\donothing
      \unvbox\floatbox
      \ifnofloatcaption
        \vss
      \fi}% gets rid of the depth (unless tabulate)
   \iftrialtypesetting\strc_counters_restore\currentfloatcounter\fi
   \egroup
   % place the float
   \strc_floats_set_box
   \strc_floats_get_box
   \global\insidefloatfalse}

\newdimension\availablefloatwidth
\newdimension\availablefloatheight

\def\strc_floats_set_local_hsize
  {\ifconditional\c_page_floats_center_box_local
     % also available check here?
     \seteffectivehsize
     \hsize\localhsize
   \orelse\ifinset\v!margin\floatlocation % brr, really needed! see wm will be redone
     \hsize{\namedmarginblockparameter\empty\c!width}%
   \fi
   \availablefloatwidth \ifchkdimexpr\floatparameter\c!availablewidth \lastchkdimension\else\hsize\fi
   \availablefloatheight\ifchkdimexpr\floatparameter\c!availableheight\lastchkdimension\else\vsize\fi}

\ifdefined\everyinsidefloat \else \newevery \everyinsidefloat \relax \fi

\appendtoks
    \everyinsidefloat\emptytoks % in case it's called earlier
    \strc_float_load_data
\to \everyinsidefloat

\permanent\def\doifelserightpagefloat
  {\unless\ifdoublesided
     \expandafter\firstoftwoarguments
   \orelse\ifsinglesided
     \expandafter\firstoftwoarguments
   \orelse\ifodd\purenumber\strc_float_realpage\space
     \expandafter\firstoftwoarguments
   \else
     \expandafter\secondoftwoarguments
   \fi}

\permanent\def\doifelseoddpagefloat
  {\ifodd\purenumber\strc_float_realpage\space
     \expandafter\firstoftwoarguments
   \else
     \expandafter\secondoftwoarguments
   \fi}

\aliased\let\doifrightpagefloatelse\doifelserightpagefloat
\aliased\let\doifoddpagefloatelse  \doifelseoddpagefloat

\appendtoks
    \enforced\let\rightorleftpageaction\doifelserightpagefloat
\to \everyinsidefloat

% \let\movesidefloat\gobbleoneargument

% new : \place...[leftmargin,-2*line]; we need to catch fxtb:2*3
% watch out: line alone aligns on the line ! ! !

\permanent\protected\def\movesidefloat[#S#settings]% (-)n*line|x=,y=
  {\global\d_page_sides_downshift \zeropoint
   \global\d_page_sides_extrashift\zeropoint
   \ifhastok={#settings}%
     \begingroup
     \setupcurrentfloat[\c!x=\zeropoint,\c!y=\zeropoint,#settings]%
     \ifgridsnapping
       \getnoflines{\floatparameter\c!y}%
       \global\d_page_sides_downshift\noflines\lineheight
     \else
       \global\d_page_sides_downshift\floatparameter\c!y
     \fi
     \global\d_page_sides_extrashift\floatparameter\c!x
     \endgroup
   \else
     \movedownsidefloat[#settings]%
   \fi}

\installcorenamespace{floatmovement}

\defcsname\??floatmovement \v!line\endcsname{\strc_floats_move_down_line+}
\defcsname\??floatmovement+\v!line\endcsname{\strc_floats_move_down_line+}
\defcsname\??floatmovement-\v!line\endcsname{\strc_floats_move_down_line-}
\defcsname\??floatmovement \v!hang\endcsname{\strc_floats_move_down_hang\plusone}
\defcsname\??floatmovement+\v!hang\endcsname{\strc_floats_move_down_hang\plusone}
\defcsname\??floatmovement-\v!hang\endcsname{\strc_floats_move_down_hang\minusone}

\defcsname\??floatmovement-2*\v!line\endcsname{\strc_floats_move_down_line{-2}}
\defcsname\??floatmovement+2*\v!line\endcsname{\strc_floats_move_down_line{2}}
\defcsname\??floatmovement 2*\v!line\endcsname{\strc_floats_move_down_line{2}}

\permanent\protected\def\installfloatmovement#1#2{\defcsname\??floatmovement#1\endcsname{#2}}

\def\strc_floats_move_down#setting%
  {\begincsname\??floatmovement#setting\endcsname}

\def\strc_floats_move_down_line#sign%
  {\ifscratchconditionone \else
     \global\d_page_sides_downshift\zeropoint
     \scratchconditiononetrue
   \fi
   \global\advanceby\d_page_sides_downshift#sign\lineheight}

\def\strc_floats_move_down_hang#lines%
  {\ifscratchconditiontwo \else
     \global\c_page_sides_n_of_lines\zerocount
     \scratchconditiontwotrue
   \fi
   \global\advanceby\c_page_sides_n_of_lines#lines\relax}

\permanent\protected\def\movedownsidefloat[#S#settings]% already in core
  {\unless\ifhastok:{#settings}%
     \begingroup
     \scratchconditiononefalse
     \scratchconditiontwofalse
     \normalexpanded{\dorepeatwithcommand[#settings]}\strc_floats_move_down
     \endgroup
   \fi}

\permanent\protected\def\hangsidefloat[#number]%
  {\global\c_page_sides_n_of_lines#number\relax}

\mutable\lettonothing\extrafloatlocation

\def\strc_floats_set_extra_action#rightpagelocation#leftpagelocation%
  {\rightorleftpageaction
     {\let\extrafloatlocation#rightpagelocation}%
     {\let\extrafloatlocation#leftpagelocation}}

\installcorenamespace{extrafloataction}

\defcsname\??extrafloataction      \v!inner\endcsname#1{\strc_floats_set_extra_action\v!left       \v!right}
\defcsname\??extrafloataction      \v!outer\endcsname#1{\strc_floats_set_extra_action\v!right      \v!left}
\defcsname\??extrafloataction\v!innermargin\endcsname#1{\strc_floats_set_extra_action\v!leftmargin \v!rightmargin}
\defcsname\??extrafloataction\v!outermargin\endcsname#1{\strc_floats_set_extra_action\v!rightmargin\v!leftmargin}
\defcsname\??extrafloataction  \v!inneredge\endcsname#1{\strc_floats_set_extra_action\v!leftedge   \v!rightedge}
\defcsname\??extrafloataction  \v!outeredge\endcsname#1{\strc_floats_set_extra_action\v!rightedge  \v!leftedge}
\defcsname\??extrafloataction  \v!backspace\endcsname#1{\strc_floats_set_extra_action\v!backspace  \v!cutspace}
\defcsname\??extrafloataction   \v!cutspace\endcsname#1{\strc_floats_set_extra_action\v!cutspace   \v!backspace}
%defcsname\??extrafloataction     \v!margin\endcsname#1{\strc_floats_set_extra_action\v!cutspace   \v!backspace}
\defcsname\??extrafloataction       \v!left\endcsname#1{\strc_floats_set_extra_action\v!left       \v!left}
\defcsname\??extrafloataction      \v!right\endcsname#1{\strc_floats_set_extra_action\v!right      \v!right}
\defcsname\??extrafloataction       \v!line\endcsname#1{} % only -n*line is handled (see ***)
\defcsname\??extrafloataction    \s!unknown\endcsname#1{\movedownsidefloat[#1]}

\def\strc_floats_check_extra_actions % less tracingthis way ....
  {\ifinset\v!text\floatlocation\else % fuzzy, text overloads left, since then it's a directive
     \lettonothing\extrafloatlocation
     % \d_page_sides_downshift will be reset afterwards, and can
     % already be set at this point
     \processcommacommand[\floatlocation]\strc_floats_check_extra_actions_step
     \ifempty\extrafloatlocation\else
       \edef\floatlocation{\extrafloatlocation,\floatlocation}%
       \setfloatmethodvariables\floatlocation
     \fi
   \fi}

\def\strc_floats_check_extra_actions_step#step%
  {\csname\??extrafloataction
     \ifcsname\??extrafloataction#step\endcsname#step\else\s!unknown\fi
   \endcsname{#step}}

% pas op, maxbreedte niet instellen als plaats=links/rechts

\def\strc_floats_set_local_dimensions
  {\global\d_page_sides_shift  \zeropoint       % duplicate
   \global\d_page_sides_maximum\zeropoint\relax % duplicate
   \ifzeropt\d_page_sides_downshift\else
     \global\setbox\floatbox\vpack
       {\vskip\d_page_sides_downshift
        \nointerlineskip
        \box\floatbox}%
   \fi
  %\edef\p_minwidth{\floatparameter\c!minwidth}%
  %\ifempty\p_minwidth
  %  % nothing
  %\else
  %  \scratchwidth{\p_minwidth}%
  %  \ifdim\wd\floatbox<\scratchwidth
  %    \strc_floats_realign_floatbox_horizontal_two
  %  \fi
  %\fi
   \ifchkdimexpr\floatparameter\c!minwidth\or
     \ifdim\wd\floatbox<\lastchkdimension
       \strc_floats_realign_floatbox_horizontal_two
     \fi
   \fi
   % we can also support edges .. in that case no common but a fast loop
   \ifinset\v!hanging\floatlocation
     \ifcommon{\v!inleft,\v!leftmargin}\floatlocation
       \let\p_maxwidth\leftmarginwidth
     \orelse\ifcommon{\v!inright,\v!rightmargin}\floatlocation
       \let\p_maxwidth\rightmarginwidth
     \else
       \edef\p_maxwidth{\floatparameter\c!maxwidth}%
     \fi
   \else
     \edef\p_maxwidth{\floatparameter\c!maxwidth}%
   \fi
  %\ifempty\p_maxwidth
  %  % nothing
  %\else
  %  \scratchwidth{\p_maxwidth}%
  %  \ifdim\wd\floatbox>\scratchwidth
  %    \ifcommon{\v!inright,\v!rightmargin,\v!rightedge,\v!inleft,\v!leftmargin,\v!leftedge}\floatlocation
  %      \global\d_page_sides_maximum\scratchwidth
  %    \orelse\ifcommon{\v!right,\v!left}\floatlocation
  %      \strc_floats_realign_floatbox_horizontal_one
  %    \else
  %      \strc_floats_realign_floatbox_horizontal_two
  %    \fi
  %  \fi
  %\fi}
   \ifchkdimexpr\p_maxwidth\or
     \ifdim\wd\floatbox>\lastchkdimension
       \ifcommon{\v!inright,\v!rightmargin,\v!rightedge,\v!inleft,\v!leftmargin,\v!leftedge}\floatlocation
         \global\d_page_sides_maximum\lastchkdimension
       \orelse\ifcommon{\v!right,\v!left}\floatlocation
         \strc_floats_realign_floatbox_horizontal_one
       \else
         \strc_floats_realign_floatbox_horizontal_two
       \fi
     \fi
   \fi}

\def\strc_floats_realign_floatbox_horizontal_one
  {\global\setbox\floatbox\hpack to \scratchwidth
     {\ifinset\v!right\floatlocation\else\hss\fi
      \box\floatbox
      \ifinset\v!left\floatlocation\else\hss\fi}}

\def\strc_floats_realign_floatbox_horizontal_two % why is this
  {\global\setbox\floatbox\hpack to \scratchwidth
     {\ifcstok{\floatparameter\c!location}\v!left\else\hss\fi
      \box\floatbox
      \ifcstok{\floatparameter\c!location}\v!right\else\hss\fi}}

\permanent\protected\def\placefloats
  {\page_otr_command_flush_floats}

\permanent\protected\def\betweenfloatblanko % assumes that spaceafter is present
  {\blank[\rootfloatparameter\c!spacebefore]} % or v!back,....

% keep as old 1
%
% \protected\def\doplacefloatbox % used elsewhere
%   {%\forgetall % NO
%    \whitespace
%    \blank[\rootfloatparameter\c!spacebefore]
%    \page_otr_command_flush_float_box
%    \blank[\rootfloatparameter\c!spaceafter]}
%
% keep as old 2
%
% \protected\def\doplacefloatbox % used elsewhere
%   {%\forgetall % NO
%    \whitespace
%    \blank[\rootfloatparameter\c!spacebefore]
%    \nointerlineskip
%    \flushnotes % new per 2014-05-29 : todo: move them up in the mvl
%    \nointerlineskip
%    \page_otr_command_flush_float_box
%    \nointerlineskip
%    \blank[\rootfloatparameter\c!spaceafter]}

\def\strc_floats_apply_skip#1%
  {\edef\m_space{\rootfloatparameter#1}%
   \ifempty\m_space\orelse\ifx\m_space\v!none\else
      \directvspacing\m_space
   \fi}

\permanent\protected\def\doplacefloatbox % used elsewhere
  {%\forgetall % NO
   \whitespace
   \strc_floats_apply_skip\c!spacebefore
   \nointerlineskip
   \flushnotes % new per 2014-05-29 : todo: move them up in the mvl
   \nointerlineskip
   \page_otr_command_flush_float_box
 % \nointerlineskip % interferes with depth of caption
   \strc_floats_apply_skip\c!spaceafter}

% test case:
%
% \placefigure[page,none]{}{\blackrule[width=\textwidth,height=0.9\textheight,color=green]}
% \placefigure[page,none]{}{\blackrule[width=\textwidth,height=1.0\textheight,color=green]}
% \placefigure[page,none]{}{\blackrule[width=\textwidth,height=1.1\textheight,color=green]}

% the [#1] will go away

\def\page_one_place_float_text % this macro should be defined elsewhere
  {%\checkwaitingfloats\floatlocationmethod
   % todo: check if #1 is indeed \floatlocation or maybe more
   \global\floatwidth    \wd\floatbox
   \global\floatheight   \ht\floatbox % forget about the depth
   \global\floattextwidth{\hsize-\floatwidth-\rootfloatparameter\c!margin}%
   \edef\floatlocation{\floatlocationmethod}% to be sure .. why
   \ifinset\v!tall\floatlocationmethod
     \floattextheight{\pagegoal-\pagetotal-\bigskipamount}% ugly, this bigskip
     \ifdim\floattextheight>\textheight
       \floattextheight\textheight
     \fi
     \boxmaxdepth\zeropoint\relax            % toegevoegd
     \ifdim\floattextheight<\floatheight
       \floattextheight\floatheight
     \fi
     \setbox\floattext\vbox to \floattextheight
   \else
     \setbox\floattext\vbox
   \fi
   \bgroup
   \forgetall
   \setupblank
   \setupwhitespace % new, also needed for footnotes
   \blank[\v!disable]
   \hsize\floattextwidth
   \ignorespaces}

\def\strc_floats_stop_text_indeed % todo
  {\egroup
   \ifinset\v!tall\floatlocation\else
     \floattextheight\ifdim\ht\floattext<\floatheight\floatheight\else\ht\floattext\fi
   \fi
   \setbox\floatbox\vpack to \floattextheight
     {\hsize\floatwidth
      \ifinset\v!both\floatlocation
        \ifinset\v!low\floatlocation
          \vfill\box\floatbox
        \orelse\ifinset\v!middle\floatlocation
          \vfill\box\floatbox\vfill
        \else
          \box\floatbox\vfill
        \fi
      \else
        \box\floatbox\vfill
      \fi}%
    \setbox\floattext\vpack to \floattextheight
      {\hsize\floattextwidth
       \ifinset\v!low\floatlocation
         \vfill
         \box\floattext
         \ifinset\c!offset\floatlocation\whitespace\blank\fi
       \orelse\ifinset\v!middle\floatlocation
         \vfill
         \box\floattext
         \vfill
       \else
         \ifinset\v!offset\floatlocation\whitespace\blank\fi
         \box\floattext
         \vfill
       \fi}%
   \ifinset\v!right\floatlocation
     \setbox\floatbox\hpack to \hsize
       {\box\floattext
        \hfill
        \box\floatbox}%
   \else
     \setbox\floatbox\hpack to \hsize
       {\box\floatbox
        \hfill
        \box\floattext}%
   \fi
   \baselinecorrection
   \whitespace
   \blank[\rootfloatparameter\c!spacebefore]%
   \ifinset\v!tall\floatlocation\else
     \dp\floatbox\openstrutdepth% \strutdp % toegevoegd
   \fi
   \box\floatbox
   \dostoptagged
   \blank[\rootfloatparameter\c!spaceafter]%
   \strc_floats_end_text_group
   \page_floats_report_total}

\permanent\def\borderedfloatbox
  {\begingroup
   \setupcurrentfloat[\c!location=\v!normal,\c!width=\v!fit,\c!height=\v!fit]%
   \inheritedfloatframed{\box\floatbox}%
   \endgroup}

% minwidth=fit,width=max : no overshoot, as wide as graphic

% keep these as reference:
%
% \def\strc_floats_align_content_indeed
%   {\alignstrutmode\zerocount
%    \doifnotcommon\floatcaptionlocation{\v!outermargin,\v!innermargin,\v!leftmargin,\v!rightmargin}
%      {\shiftalignedline
%         {\floatparameter\c!leftmargin }{\floatparameter\c!rightmargin}%
%         {\floatparameter\c!innermargin}{\floatparameter\c!outermargin}}%
%    \alignedline{\floatparameter\c!location}\v!middle}
%
% \def\strc_floats_align_caption_indeed
%   {\alignstrutmode\zerocount
%    \shiftalignedline
%      {\floatcaptionparameter\c!leftmargin }{\floatcaptionparameter\c!rightmargin}%
%      {\floatcaptionparameter\c!innermargin}{\floatcaptionparameter\c!outermargin}%
%    \alignedline{\floatparameter\c!location}\v!middle}
%
% Test case:
%
% \setupfloats[location=left]
% \setupfloatcaption[width=max]
%
% \startfloatcombination
%     \placefigure{}{}
%     \placefigure{}{}
% \stopfloatcombination

%D In a floatcombination we ignore the margins .. if that is ever needed we need another
%D state (instead of local).

\def\strc_floats_align_indeed
  {\alignedline{\floatparameter\c!location}\v!middle}

\def\strc_floats_shift_indeed#1%
  {\shiftalignedline{#1\c!leftmargin}{#1\c!rightmargin}{#1\c!innermargin}{#1\c!outermargin}}

\def\strc_floats_align_content_indeed
  {\alignstrutmode\zerocount
   \ifx\forcedfloatmethod\v!local \else
     \ifcommon\floatcaptionlocation{\v!outermargin,\v!innermargin,\v!leftmargin,\v!rightmargin}\else
       \strc_floats_shift_indeed\floatparameter
     \fi
     \expandafter\strc_floats_align_indeed
   \fi}

\def\strc_floats_align_caption_indeed
  {\alignstrutmode\zerocount
   \ifx\forcedfloatmethod\v!local
     \expandafter\strc_floats_align_indeed_local
   \else
     \strc_floats_shift_indeed\floatcaptionparameter
     \expandafter\strc_floats_align_indeed
   \fi}

% \def\strc_floats_align_indeed_local#1%
%   {\begingroup
%    \hsize\wd\floatbox
%    \strc_floats_align_indeed{#1}%
%    \endgroup}

\let\strc_floats_align_indeed_local\firstofoneargument

\newdimension\d_strc_floats_content
\newdimension\d_strc_float_temp_height
\newdimension\d_strc_float_temp_width

\newconditional\c_floats_adapt_to_caption_width
\newconditional\c_floats_store_minimal_package

\newconditional\c_floats_append_to_stored
\newconditional\c_floats_force

\newdimension\d_strc_floats_caption_hsize
\newdimension\d_strc_floats_caption_min_width
\newdimension\d_strc_floats_caption_overshoot

% These are expandable, for diagnostic purposes only, but might eventually go away:

\permanent\def\captionhsize    {\the\d_strc_floats_caption_hsize}
\permanent\def\captionminwidth {\the\d_strc_floats_caption_min_width}
\permanent\def\captionovershoot{\the\d_strc_floats_caption_overshoot}

\let\strc_floats_align_content\relax
\let\strc_floats_align_caption\relax

\def\strc_floats_set_caption_criteria % can become parameter (but what name)
  {\d_strc_floats_caption_min_width15\bodyfontsize
   \d_strc_floats_caption_overshoot 2\emwidth}

\let\strc_floats_mark_pag_as_free\relax

\def\strc_floats_set_page_variant
  {\bgroup
   \strc_floats_set_local_hsize
   \ifcase\c_strc_floats_rotation\else
     % Swapping fails in overloadmode and is also wrong (as it then is persistent due
     % to global being inherited).
    %\swapdimens\hsize\vsize
     \scratchdimen\hsize
     \hsize\vsize
     \vsize\scratchdimen
   \fi
   \forgetall
   \postponenotes
   \dontcomplain
   \setbox\b_strc_floats_content\vpack{\borderedfloatbox}%
   \let\strc_floats_align_content\strc_floats_align_content_indeed
   \let\strc_floats_align_caption\strc_floats_align_caption_indeed
   \strc_floats_check_caption_content
   \d_strc_floats_content\wd\b_strc_floats_content
   \ifcase\floatparameter\c!method
     % nothing
   \or
     % automatic
     \ifnofloatcaption
       \strc_floats_prepare_no_caption
       \strc_floats_set_caption_dimensions\voidbox
      %\page_backgrounds_add_local_to_box\floatbox % was \doglobal but not needed
       \ifx\forcedfloatmethod\v!local
         % we need \ifinfloatcombination
         \strc_floats_build_box
       \fi
     \else
       % todo: installable maken, variant/method=auto vs macro
       \strc_floats_prepare_page_caption
      %\page_backgrounds_add_local_to_box\b_strc_floats_content
       \strc_floats_apply_caption_command
       \strc_floats_set_caption_dimensions\b_strc_floats_caption
      %\moveboxontogrid\b_strc_floats_caption{\floatcaptionparameter\c!grid}\d_strc_floats_caption_height
      %\page_backgrounds_add_local_to_box\b_strc_floats_caption
       \strc_floats_build_box
     \fi
   \or
     % semi automatic
   \or
     % manual
   \fi
   \ifconditional\c_floats_store_minimal_package
     % nothing
   \orelse\ifcase\c_strc_floats_rotation
     \ifinset\v!margin\floatlocation\else % brr, really needed! see wm
       \postcenterfloatbox\d_strc_floats_content
       \strc_floats_mark_pag_as_free
     \fi
     % mark as free not done here
   \else
     \global\setbox\floatbox\vpack
       {\rotate[\c!rotation=\the\c_strc_floats_rotation]{\box\floatbox}}%
     \strc_floats_mark_pag_as_free
   \fi
   \egroup}

\def\strc_floats_prepare_no_caption
  {\global\setbox\floatbox\vpack % pas op als wd groter dan hsize
     {\ifinsidecolumns\ifdim\wd\b_strc_floats_content>\hsize
        \let\strc_floats_align_content\relax
      \fi\fi
      \strc_floats_align_content{\copy\b_strc_floats_content}}}

\def\strc_floats_prepare_page_caption
  {\edef\p_strc_floats_caption_width   {\floatcaptionparameter\c!width}%
   \edef\p_strc_floats_caption_minwidth{\floatcaptionparameter\c!minwidth}%
   \edef\p_strc_floats_caption_align   {\floatcaptionparameter\c!align}%
   \dostarttaggednodetail\t!floatcaption
   \ifconditional\c_strc_floats_ornament_caption
      \strc_floats_prepare_ornament_caption
   \orelse\ifcommon{\v!top,\v!bottom}\floatcaptionlocation
     \strc_floats_prepare_page_caption_top_bottom
   \orelse\ifx\p_strc_floats_caption_width\v!fit
     \strc_floats_prepare_side_auto_caption
   \orelse\ifx\p_strc_floats_caption_width\v!max
     \strc_floats_prepare_side_auto_caption
   \else
     \strc_floats_prepare_side_width_caption
   \fi
   \dostoptagged}

\def\strc_floats_prepare_ornament_caption
  {\setbox\b_strc_floats_caption\null
   \setbox\b_strc_floats_content\vpack
     {\csname\??ornament\floatcaptionlocation\endcsname
        {\strc_floats_make_incomplete_caption}%
        {\box\b_strc_floats_content}}}

\def\strc_floats_prepare_page_caption_top_bottom
  {\ifx\p_strc_floats_caption_width\v!fit
     \strc_floats_prepare_page_caption_top_bottom_fit_max
   \orelse\ifx\p_strc_floats_caption_width\v!max
     \strc_floats_prepare_page_caption_top_bottom_fit_max
   \else
     \strc_floats_prepare_side_width_caption % new, special effects (see icare)
   \fi}

\def\strc_floats_prepare_page_caption_top_bottom_fit_max
  {\unless\ifx\p_strc_floats_caption_minwidth\v!fit
     \strc_floats_prepare_stack_caption_fixed
   \orelse\ifx\p_strc_floats_caption_width\v!max
     \strc_floats_prepare_stack_caption_max
   \orelse\ifdim\wd\b_strc_floats_caption>\wd\b_strc_floats_content % wider caption
     \ifx\p_strc_floats_caption_width\v!fit
       \strc_floats_prepare_stack_caption_auto
     \else
       \strc_floats_prepare_stack_caption_width
     \fi
   \else
     \strc_floats_prepare_stack_caption_min
   \fi}

\def\strc_floats_caption_set_align
  {\edef\m_align{\v!reset\ifempty\p_strc_floats_caption_align\else,\fi\p_strc_floats_caption_align}%
   \ifinset\v!tolerant    \floatcaptionlocation\edef\m_align{\m_align,\v!tolerant    }\fi
   \ifinset\v!verytolerant\floatcaptionlocation\edef\m_align{\m_align,\v!verytolerant}\fi
   \ifinset\v!stretch     \floatcaptionlocation\edef\m_align{\m_align,\v!stretch     }\fi
   \setupalign[\m_align]}

\def\strc_floats_prepare_side_auto_caption
  {\scratchdimen{\hsize-\wd\b_strc_floats_content-(\floatparameter\c!margin)}%
   \ifdim\wd\b_strc_floats_caption>\scratchdimen
     \ifdim\wd\b_strc_floats_caption<1.3\scratchdimen
       \scratchdimen0.8\scratchdimen
     \fi
   \fi
   \setbox\b_strc_floats_caption\vbox
     {\strc_floats_caption_set_align
      \hsize\scratchdimen
      \strc_floats_make_complete_caption}}

\def\strc_floats_prepare_side_width_caption
  {\setbox\b_strc_floats_caption\vbox
     {\strc_floats_caption_set_align
      \hsize{\floatcaptionparameter\c!width}%
      \strc_floats_make_complete_caption}}

\def\strc_floats_prepare_stack_caption_fixed
  {\setbox\b_strc_floats_caption\vbox
     {\strc_floats_caption_set_align
      \hsize{\floatcaptionparameter\c!minwidth}% special effects
      \strc_floats_make_complete_caption}}

\def\strc_floats_prepare_stack_caption_max
  {\setbox\b_strc_floats_caption\vbox
     {\strc_floats_caption_set_align
      \hsize\wd\b_strc_floats_content
      \strc_floats_make_complete_caption}}

\def\strc_floats_prepare_stack_caption_width
  {\setbox\b_strc_floats_caption\vbox
     {\strc_floats_caption_set_align
      \hsize{\floatcaptionparameter\c!width}%
      \strc_floats_make_complete_caption}}

\def\strc_floats_prepare_stack_caption_min
  {\setbox\b_strc_floats_caption\vbox
     {\strc_floats_caption_set_align
      \hsize\wd\b_strc_floats_content
      \ifempty\p_strc_floats_caption_align
        \raggedcenter % on purpose overloads align !
      \fi
      \strc_floats_make_complete_caption}}

\def\strc_floats_prepare_stack_caption_auto
%   {\ifempty\p_strc_floats_caption_align
%    \orelse\ifinset\v!middle\p_strc_floats_caption_align
%    \else
%      \d_strc_floats_caption_overshoot\zeropoint
%    \fi
  {\ifinset\v!middle\p_strc_floats_caption_align\else
     \d_strc_floats_caption_overshoot\zeropoint
   \fi
   \d_strc_floats_caption_hsize\wd\b_strc_floats_content
   \scratchwidth{\floatcaptionparameter\c!maxwidth}%
   \ifconditional\c_floats_adapt_to_caption_width
     \d_strc_floats_caption_min_width\zeropoint
     \d_strc_floats_caption_overshoot\zeropoint
   \fi
   \ifdim\d_strc_floats_caption_hsize>\scratchwidth
     % float is wider than \hsize
     \setbox\b_strc_floats_caption\vbox
       {\settrialtypesetting
        \strc_floats_caption_set_align
        \hsize\scratchwidth
        \notesenabledfalse
        \strc_floats_make_complete_caption}%
     \ifdim\ht\scratchbox>\lineheight % more lines
       \setbox\b_strc_floats_caption\vbox
         {\strc_floats_caption_set_align
          \hsize{\d_strc_floats_caption_hsize-\d_strc_floats_caption_overshoot}%
          \ifdim\hsize<\d_strc_floats_caption_min_width\relax
            \hsize\scratchwidth
          \fi
          \strc_floats_make_complete_caption}%
     \else
       \setbox\b_strc_floats_caption\vbox
         {\strc_floats_caption_set_align
          \hsize\scratchwidth
          \strc_floats_make_complete_caption}%
     \fi
   \else
     % float is smaller of equal to \hsize
     \ifdim\d_strc_floats_caption_hsize<\d_strc_floats_caption_min_width\relax
       \d_strc_floats_caption_hsize\d_strc_floats_caption_min_width % float smaller than min width
     % \ifconditional\c_floats_adapt_to_caption_width
     %   \setbox\b_strc_floats_content\hpack to \d_strc_floats_caption_hsize{\hss\box\b_strc_floats_content\hss}%
     % \fi
     \fi
     \setbox\scratchbox\vbox     % test with overshoot
       {\settrialtypesetting
        \scratchdimen{\d_strc_floats_caption_hsize+\d_strc_floats_caption_overshoot+3\emwidth}% 3em is an average word length
        \ifdim\scratchdimen<\hsize
          \hsize\scratchdimen
        \fi
        \notesenabledfalse
        \strc_floats_make_complete_caption}%
     \ifdim\ht\scratchbox>\lineheight
       % at least an average word longer than a line
       \setbox\b_strc_floats_caption\vbox
         {\strc_floats_caption_set_align
          \scratchdimen{\d_strc_floats_caption_hsize+\d_strc_floats_caption_overshoot}%
          \ifdim\scratchdimen<\hsize
            \hsize\scratchdimen
          \fi
          \strc_floats_make_complete_caption}%
     \orelse\ifempty\p_strc_floats_caption_align
       \setbox\b_strc_floats_caption\vbox
         {\strc_floats_caption_set_align
          \hsize\d_strc_floats_caption_hsize
          \raggedcenter % overloads
          \strc_floats_make_complete_caption}%
     \else
       \setbox\b_strc_floats_caption\vbox
         {\strc_floats_caption_set_align
          \hsize\d_strc_floats_caption_hsize
          \strc_floats_make_complete_caption}%
     \fi
   \fi}

\def\strc_floats_between_stack
  {\endgraf
   \nointerlineskip
   \floatcaptionparameter\c!inbetween
   \endgraf}

\def\strc_floats_build_box_default % done
  {\strc_floats_align_content{\box\b_strc_floats_content}}

\def\strc_floats_build_box_next_right#1%
  {\ifconditional\c_strc_floats_par_float \hpack \else \expandafter \strc_floats_align_content \fi % skip, no pack
     {\d_strc_float_temp_height\ht\b_strc_floats_content
      \box\b_strc_floats_content
      \ifinset\v!hang\floatcaptionlocation\else
        \dotfskip{\floatcaptionparameter\c!distance}%
      \fi
      \vbox to\d_strc_float_temp_height{#1}}}

\def\strc_floats_build_box_next_left#1%
  {\ifconditional\c_strc_floats_par_float \hpack \else \expandafter \strc_floats_align_content \fi % skip, no pack
     {\d_strc_float_temp_height\ht\b_strc_floats_content
      \vbox to\d_strc_float_temp_height{#1}%
      \ifinset\v!hang\floatcaptionlocation\else
        \dotfskip{\floatcaptionparameter\c!distance}%
      \fi
      \box\b_strc_floats_content}}

\def\strc_floats_build_box_next_outer
  {\doifelserightpagefloat\strc_floats_build_box_next_right\strc_floats_build_box_next_left}

\def\strc_floats_build_box_next_inner
  {\doifelserightpagefloat\strc_floats_build_box_next_left\strc_floats_build_box_next_right}

\def\strc_floats_build_box_next_right_hang#1%
  {\ifconditional\c_strc_floats_par_float \hpack \else \expandafter \strc_floats_align_content \fi
     {\d_strc_float_temp_height\ht\b_strc_floats_content
      \box\b_strc_floats_content
      \vbox to\d_strc_float_temp_height{#1}}}

\def\strc_floats_build_box_next_left_hang#1%
  {\ifconditional\c_strc_floats_par_float \hpack \else \expandafter \strc_floats_align_content \fi
     {\d_strc_float_temp_height\ht\b_strc_floats_content
      \vbox to\d_strc_float_temp_height{#1}%
      \box\b_strc_floats_content}}

\def\strc_floats_build_box_next_right_margin_indeed#1#2%
  {\ifconditional\c_strc_floats_par_float
     \hpack\bgroup
       \d_strc_float_temp_height\ht\b_strc_floats_content
       \box\b_strc_floats_content
       \hsmash{\hskip#1\vbox to\d_strc_float_temp_height{#2}}%
     \egroup
   \else
     \begingroup
     \d_strc_float_temp_height\ht\b_strc_floats_content
     \setbox\scratchboxone\vbox{#2}%
     \ifdim\htdp\scratchboxone>\htdp\b_strc_floats_content
       \global\d_strc_floats_overflow{\htdp\scratchboxone-\htdp\b_strc_floats_content}%
     \fi
     \ht\scratchboxone\d_strc_float_temp_height
     \everyrightofalignedline{\hsmash{\hskip#1\box\scratchboxone}}%
     \strc_floats_align_content{\box\b_strc_floats_content}%
     \endgroup
    \fi}

\def\strc_floats_build_box_next_left_margin_indeed#1#2%
  {\ifconditional\c_strc_floats_par_float
     \hpack\bgroup
       \d_strc_float_temp_height\ht\b_strc_floats_content
       \hsmash{\hskip-\dimexpr#1+\wd\b_strc_floats_caption\relax\vbox to\d_strc_float_temp_height{#2}}%
       \box\b_strc_floats_content
     \egroup
   \else
     \begingroup
     \d_strc_float_temp_height\ht\b_strc_floats_content
     \setbox\scratchboxone\vbox{#2}%
     \ifdim\htdp\scratchboxone>\htdp\b_strc_floats_content
       \global\d_strc_floats_overflow{\htdp\scratchboxone-\htdp\b_strc_floats_content}%
     \fi
     \ht\scratchboxone\d_strc_float_temp_height
     \everyleftofalignedline{\hsmash{\hskip-\dimexpr#1+\wd\scratchboxone\relax\box\scratchboxone}}%
     \strc_floats_align_content{\box\b_strc_floats_content}%
     \endgroup
   \fi}

\def\strc_floats_build_box_next_right_margin
  {\strc_floats_build_box_next_right_margin_indeed\rightmargindistance}

\def\strc_floats_build_box_next_left_margin
  {\strc_floats_build_box_next_left_margin_indeed \leftmargindistance}

\def\strc_floats_build_box_next_outer_margin
  {\doifelserightpagefloat
     {\strc_floats_build_box_next_right_margin_indeed\rightmargindistance}
     {\strc_floats_build_box_next_left_margin_indeed \rightmargindistance}}

\def\strc_floats_build_box_next_inner_margin
  {\doifelserightpagefloat
     {\strc_floats_build_box_next_left_margin_indeed \leftmargindistance}
     {\strc_floats_build_box_next_right_margin_indeed\leftmargindistance}}

\def\strc_floats_build_box_next % beware, we first check on left/rightmargin because there can be left/right also
  {\let\next\strc_floats_build_box_next_left
   \processallactionsinset[\floatcaptionlocation]
     [ \v!outermargin=>\let\next\strc_floats_build_box_next_outer_margin,
       \v!innermargin=>\let\next\strc_floats_build_box_next_inner_margin,
        \v!leftmargin=>\let\next\strc_floats_build_box_next_left_margin,
       \v!rightmargin=>\let\next\strc_floats_build_box_next_right_margin,
       \v!lefthanging=>\let\next\strc_floats_build_box_next_left_hang,
      \v!righthanging=>\let\next\strc_floats_build_box_next_right_hang,
             \v!outer=>\let\next\strc_floats_build_box_next_outer,
             \v!inner=>\let\next\strc_floats_build_box_next_inner,
              \v!left=>\let\next\strc_floats_build_box_next_left,
             \v!right=>\let\next\strc_floats_build_box_next_right]%
   \next}

\def\strc_floats_build_box_side
  {\c_page_sides_force_shape\conditionalfalse
   \ifconditional\c_strc_floats_par_float
     \let\next\strc_floats_build_box_high
   \else
     \let\next\strc_floats_build_box_middle
     \processallactionsinset[\floatcaptionlocation]
       [   \v!low=>\let\next\strc_floats_build_box_low,
        \v!middle=>\let\next\strc_floats_build_box_middle,
          \v!high=>\let\next\strc_floats_build_box_high]%
   \fi
   \next}

\def\strc_floats_flush_right_caption_hang
  {\hsmash{\rlap{\dotfskip{\floatcaptionparameter\c!distance}\box\b_strc_floats_caption}}}

\def\strc_floats_flush_left_caption_hang
  {\hsmash{\llap{\box\b_strc_floats_caption\dotfskip{\floatcaptionparameter\c!distance}}}}

\def\strc_floats_flush_caption_hang
  {\ifinset\v!righthanging\floatcaptionlocation
     \strc_floats_flush_right_caption_hang
   \orelse\ifinset\v!lefthanging\floatcaptionlocation
     \strc_floats_flush_left_caption_hang
   \orelse\ifinset\v!hang\floatcaptionlocation
     \ifinset\v!outer\floatcaptionlocation
       \doifelserightpagefloat
         {\strc_floats_flush_right_caption_hang}
         {\strc_floats_flush_left_caption_hang}%
     \orelse\ifinset\v!right\floatcaptiondirectives
       \strc_floats_flush_right_caption_hang
     \else
       \strc_floats_flush_left_caption_hang
     \fi
   \else
     \box\b_strc_floats_caption
   \fi} % is this ok

\def\strc_floats_build_box_high
  {\strc_floats_build_box_next{\strc_floats_between_stack\strc_floats_flush_caption_hang\vfill}}

\def\strc_floats_build_box_low
  {\strc_floats_build_box_next{\vfill\strc_floats_flush_caption_hang\strc_floats_between_stack}}

\def\strc_floats_build_box_middle
  {\strc_floats_build_box_next{\vfill\box\b_strc_floats_caption\vfill}}

% \definefloat
%   [lefty][lefties][figure]
% \setupfloat
%   [lefty]
%   [default=left,
%    rightmargindistance=-2cm,
%    leftmargindistance=-2cm]
% \setupcaption
%   [lefty]
%   [location={bottom,overlay}]
%
% \starttext
%     \placelefty{}{} \input tufte \input tufte
%     \placelefty{}{} \input tufte \input tufte
% \stoptext

\def\strc_floats_build_box_top_stack_normal_overlay
  {\vbox to \ht\b_strc_floats_content{\vss\strc_floats_build_box_top_stack_normal_content}}

\def\strc_floats_build_box_top_stack_normal_content
  {\d_strc_float_temp_width\wd\b_strc_floats_content
   \ifconditional\c_strc_floats_par_float
     \hpack{\strc_floats_locate_side_float{\box\b_strc_floats_caption}}%
     \strc_floats_between_stack
     \hpack{\hbox{\box\b_strc_floats_content}}%
   \else
     \page_otr_command_set_float_hsize
     \hpack{\strc_floats_locate_text_float{\box\b_strc_floats_caption}}
     \strc_floats_between_stack
     \hpack{\strc_floats_align_content{\box\b_strc_floats_content}}%
   \fi}

\def\strc_floats_build_box_bottom_stack_normal_overlay
  {\vbox to \ht\b_strc_floats_content{\strc_floats_build_box_bottom_stack_normal_content\vss}}

\def\strc_floats_build_box_bottom_stack_normal_content
  {\d_strc_float_temp_width\wd\b_strc_floats_content
   \ifconditional\c_strc_floats_par_float
     \hpack{\hpack{\box\b_strc_floats_content}}%
     \strc_floats_between_stack
     \hpack{\strc_floats_locate_side_float{\box\b_strc_floats_caption}}%
   \else
     \page_otr_command_set_float_hsize
     \hpack{\strc_floats_align_content{\box\b_strc_floats_content}}%
     \strc_floats_between_stack
     \hpack{\strc_floats_locate_text_float{\box\b_strc_floats_caption}}%
   \fi}

\def\strc_floats_build_box_top_stack_normal_tight
  {\hpack{\box\b_strc_floats_caption}%
   \strc_floats_between_stack
   \hpack{\box\b_strc_floats_content}}

\def\strc_floats_build_box_bottom_stack_normal_tight
  {\hpack{\box\b_strc_floats_content}%
   \strc_floats_between_stack
   \hpack{\box\b_strc_floats_caption}}

\def\strc_floats_build_box_top_stack_normal
  {\ifinset\v!overlay{\floatcaptionparameter\c!location}%
     \strc_floats_build_box_top_stack_normal_overlay
   \orelse\ifinset\v!tight{\floatlocation}%
     \strc_floats_build_box_top_stack_normal_tight
   \else
     \strc_floats_build_box_top_stack_normal_content
   \fi}

\def\strc_floats_build_box_bottom_stack_normal
  {\ifinset\v!overlay{\floatcaptionparameter\c!location}%
     \strc_floats_build_box_bottom_stack_normal_overlay
   \orelse\ifinset\v!tight{\floatlocation}%
     \strc_floats_build_box_bottom_stack_normal_tight
   \else
     \strc_floats_build_box_bottom_stack_normal_content
   \fi}

\def\strc_floats_build_box_top_stack_grid
  {\dp\b_strc_floats_caption\strutdepth
   \setbox\scratchbox\vbox
     {\d_strc_float_temp_width\wd\b_strc_floats_content
      \hsize\d_strc_float_temp_width
      \ifconditional\c_strc_floats_par_float
        \strc_floats_locate_side_float{\box\b_strc_floats_caption}%
        \vss\strc_floats_between_stack
        \hpack{\box\b_strc_floats_content}%
      \else
        \page_otr_command_set_float_hsize
        \strc_floats_locate_text_float{\box\b_strc_floats_caption}%
        \vss\strc_floats_between_stack
        \strc_floats_align_content{\box\b_strc_floats_content}%
      \fi}%
   \getnoflines{\htdp\scratchbox-10\scaledpoint}% get rid of inaccuracy
   \vpack to \noflines\lineheight{\unvbox\scratchbox}}

\def\strc_floats_build_box_bottom_stack_grid
  {\dp\b_strc_floats_caption\strutdepth
   \setbox\scratchbox\vbox
     {\d_strc_float_temp_width\wd\b_strc_floats_content
      \hsize\d_strc_float_temp_width
      \ifconditional\c_strc_floats_par_float
        \hpack{\box\b_strc_floats_content}%
        \vss\strc_floats_between_stack
        \strc_floats_locate_side_float{\box\b_strc_floats_caption}%
      \else
        \page_otr_command_set_float_hsize
        \strc_floats_align_content{\box\b_strc_floats_content}%
        \vss\strc_floats_between_stack
        \strc_floats_locate_text_float{\box\b_strc_floats_caption}%
      \fi}%
   \getnoflines{\htdp\scratchbox-10\scaledpoint}% get rid of inaccuracy
   \vpack to \noflines\lineheight{\unvbox\scratchbox}}

\def\strc_floats_build_box_top_stack_stretch
  {\dp\b_strc_floats_caption\strutdepth
   \setbox\scratchbox\vpack
     {\strc_floats_align_caption{\copy\b_strc_floats_caption}%
      \strc_floats_align_content{\copy\b_strc_floats_content}}%
   \getnoflines{\htdp\scratchbox-10\scaledpoint}% get rid of inaccuracy
   \vbox to \noflines\lineheight % pack ?
     {\d_strc_float_temp_width\wd\b_strc_floats_content
      \hsize\d_strc_float_temp_width
      \ifconditional\c_strc_floats_par_float
        \strc_floats_locate_side_float{\box\b_strc_floats_caption}%
        \vss\strc_floats_between_stack\vss
        \hpack{\box\b_strc_floats_content}%
      \else
        \page_otr_command_set_float_hsize
        \strc_floats_locate_text_float{\box\b_strc_floats_caption}%
        \vss\strc_floats_between_stack\vss
        \strc_floats_align_content{\box\b_strc_floats_content}%
      \fi}}

\def\strc_floats_build_box_bottom_stack_stretch
  {\dp\b_strc_floats_caption\strutdepth
   \setbox\scratchbox\vpack
     {\strc_floats_align_content{\copy\b_strc_floats_content}%
      \strc_floats_align_caption{\copy\b_strc_floats_caption}}%
   \getnoflines{\htdp\scratchbox-10\scaledpoint}% get rid of inaccuracy
   \vbox to \noflines\lineheight
     {\d_strc_float_temp_width\wd\b_strc_floats_content
      \hsize\d_strc_float_temp_width
      \ifconditional\c_strc_floats_par_float
        \hpack{\box\b_strc_floats_content}%
        \vss\strc_floats_between_stack\vss
        \strc_floats_locate_side_float{\box\b_strc_floats_caption}%
      \else
        \page_otr_command_set_float_hsize
        \strc_floats_align_content{\box\b_strc_floats_content}%
        \vss\strc_floats_between_stack\vss
        \strc_floats_locate_text_float{\box\b_strc_floats_caption}%
      \fi}}

\def\strc_floats_build_box_top
  {\let\next\strc_floats_build_box_top_stack_normal
   \processfirstactioninset[\floatcaptionparameter\c!location]
     [   \v!grid=>\let\next\strc_floats_build_box_top_stack_grid,
        \v!lines=>\let\next\strc_floats_build_box_top_stack_stretch]% was \v!grid but interfered
   \next}

\def\strc_floats_build_box_bottom
  {\let\next\strc_floats_build_box_bottom_stack_normal
   \processfirstactioninset[\floatcaptionparameter\c!location]
     [   \v!grid=>\let\next\strc_floats_build_box_bottom_stack_grid,
        \v!lines=>\let\next\strc_floats_build_box_bottom_stack_stretch]% was \v!grid but interfered
   \next}

\def\strc_floats_relocate_caption_right#1{\strc_floats_align_caption{\hbox to \d_strc_float_temp_width{\hss#1}}}
\def\strc_floats_relocate_caption_left #1{\strc_floats_align_caption{\hbox to \d_strc_float_temp_width{#1\hss}}}

\permanent\protected\def\installfloatboxbuilder#1#2{\defcsname\??floatbuilder#1\endcsname{#2}}

\def\strc_floats_build_box
  {\strc_floats_build_box_before
   \global\setbox\floatbox\vbox % pack ? probably not
     {\strc_floats_set_local_hsize
      \forgetall
      \ifconditional\c_floats_store_minimal_package
        \strc_floats_build_box_separate_make
      \orelse\ifconditional\c_strc_floats_ornament_caption
        \strc_floats_build_box_default
      \else
      % \let\floatcaptionarrangement\s!default
        \let\floatcaptionarrangement\v!bottom % for Alan
        \processcommacommand[\floatcaptionparameter\c!location]\strc_floats_build_box_step
        \ifcsname\??floatbuilder\floatcaptionarrangement\endcsname
          \lastnamedcs
        \else
          \strc_floats_build_box_default
        \fi
      \fi}%
   \strc_floats_build_box_after}

% \let\strc_floats_build_box_before\relax
% \let\strc_floats_build_box_after \relax

\def\strc_floats_build_box_before
  {\let\currentfloatframed\currentfloat
   \floatwidth\wd
     \ifdim\wd\b_strc_floats_content>\wd\b_strc_floats_caption
       \b_strc_floats_content\else\b_strc_floats_caption
     \fi}

\def\strc_floats_build_box_after
  {\doifelseframed\floatframedparameter\strc_floats_build_box_after_indeed\relax}

\def\strc_floats_build_box_after_indeed
  {\global\setbox\floatbox\hpack
     {\edef\p_width{\floatframedparameter\c!width}%
      \ifx\p_width\v!fit
        \letfloatframedparameter\c!width\floatwidth
      \orelse\ifx\p_width\v!broad
        \letfloatframedparameter\c!width\v!fit
      \else
        \letfloatframedparameter\c!width\p_width % expanded, not really needed
      \fi
      \letfloatframedparameter\c!strut\v!no
      \inheritedfloatframedframed
        {\box\floatbox}}}

% special purpose: used in floatcombinations
%
% todo : keep float content and caption separated in local

\newbox\b_strc_floats_separate_content
\newbox\b_strc_floats_separate_caption

\def\strc_floats_build_box_separate_set
  {\c_floats_adapt_to_caption_width\conditionaltrue
   \c_floats_store_minimal_package\conditionaltrue}

% \def\strc_floats_build_box_separate_make
%   {\offinterlineskip
%    \vpack to \onepoint{\box\b_strc_floats_content}\break
%    \vpack to \onepoint{\box\b_strc_floats_caption}}

%D Remark for \LMTX: we don't want to migrate inserts here so we unpack
%D (could be a flag). When migrated, the inserts end up in the vertical
%D list and we no longer have just a box (but inserts and lines again).

\def\strc_floats_build_box_separate_make
  {\savebox\??localfloatstack{\tointeger{\c_strc_localfloats_n+1}:a}{\box\b_strc_floats_content}%
   \savebox\??localfloatstack{\tointeger{\c_strc_localfloats_n+1}:b}{\box\b_strc_floats_caption}}

\protected\def\strc_floats_build_box_separate_split#1%
  {\global\setbox\b_strc_floats_separate_content\vpack{\foundbox\??localfloatstack{\number#1:a}}%
   \global\setbox\b_strc_floats_separate_caption\tpack{\foundbox\??localfloatstack{\number#1:b}}}

% \def\strc_floats_build_box_step#1%
%   {\doifdefined{\??floatbuilder#1}{\def\floatcaptionarrangement{#1}\quitcommalist}}

\def\strc_floats_build_box_step#1%
  {\ifcsname\??floatbuilder#1\endcsname
     \def\floatcaptionarrangement{#1}% \let\floatcaptionarrangement\commalistelement
     \quitcommalist
   \fi}

\def\strc_floats_locate_text_float
  {\let\next\strc_floats_align_caption
   \processallactionsinset[\floatcaptionparameter\c!location]
     [ \v!left=>\let\next\strc_floats_relocate_caption_left,
      \v!right=>\let\next\strc_floats_relocate_caption_right,
      \v!inner=>\doifelserightpagefloat{\let\next\strc_floats_relocate_caption_left }{\let\next\strc_floats_relocate_caption_right},
      \v!outer=>\doifelserightpagefloat{\let\next\strc_floats_relocate_caption_right}{\let\next\strc_floats_relocate_caption_left }]%
   \next}

\installfloatboxbuilder \v!none         \strc_floats_build_box_default
\installfloatboxbuilder \s!default      \strc_floats_build_box_default
\installfloatboxbuilder \v!high         \strc_floats_build_box_high
\installfloatboxbuilder \v!low          \strc_floats_build_box_low
\installfloatboxbuilder \v!middle       \strc_floats_build_box_middle

\installfloatboxbuilder \v!rightmargin  \strc_floats_build_box_side % added 2016-08-23
\installfloatboxbuilder \v!leftmargin   \strc_floats_build_box_side % added 2016-08-23
\installfloatboxbuilder \v!innermargin  \strc_floats_build_box_side % added 2016-08-23
\installfloatboxbuilder \v!outermargin  \strc_floats_build_box_side % added 2016-08-23

\installfloatboxbuilder \v!left         \strc_floats_build_box_side
\installfloatboxbuilder \v!right        \strc_floats_build_box_side
\installfloatboxbuilder \v!inner        \strc_floats_build_box_side % added 2016-08-23
\installfloatboxbuilder \v!outer        \strc_floats_build_box_side % added 2016-08-23

\installfloatboxbuilder \v!lefthanging  \strc_floats_build_box_side % added 2016-08-23
\installfloatboxbuilder \v!righthanging \strc_floats_build_box_side % added 2016-08-23
\installfloatboxbuilder \v!hang         \strc_floats_build_box_side % added 2016-08-23

\installfloatboxbuilder \v!top          \strc_floats_build_box_top
\installfloatboxbuilder \v!bottom       \strc_floats_build_box_bottom

% \setuplayout[grid=yes] \showgrid \setupcaptions[style=smallbodyfont,location=grid,inbetween=]
%
% \starttext
%     test \placefigure{}                 {\externalfigure[cow.pdf][frame=on,grid=yes]}   test \page
%     test \placefigure{\input zapf\relax}{\externalfigure[cow.pdf][frame=on,grid=yes]}   test \page
%     test \placefigure{}                 {\externalfigure[cow.pdf][frame=on,grid=depth]} test \page
%     test \placefigure{\input zapf\relax}{\externalfigure[cow.pdf][frame=on,grid=depth]} test \page
% \stoptext

% This might move to page-flt:

\newif\ifpostponecolumnfloats \postponecolumnfloatsfalse % don't change

\setnewconstant\postcenterfloatmethod\plusone

\permanent\def\postcenterfloatbox#1%
  {\scratchdimen
     \ifcase\postcenterfloatmethod
       #1% \wd\floatbox
     \orelse\ifinsidecolumns
       \ifpostponecolumnfloats\makeupwidth\else#1\fi
     \orelse\ifdim#1>\hsize
       \hsize
     \else
       \wd\floatbox
     \fi
   \global\setbox\floatbox\hbox to \scratchdimen
   % {\hfill\box\floatbox\hfill}} % geen \hss, gaat mis in kolommen !
   % {\hss  \box\floatbox\hss  }} % wel \hss, anders mis in colset
     {\ifconditional\c_page_floats_center_box_global
        \donetrue
      \orelse\ifconditional\c_page_floats_center_box_local
        \donetrue
      \else
        \donefalse
      \fi
      \ifdim\scratchdimen>\effectivehsize
        \donefalse
      \fi
      \hss\ifdone\hskip\effectiveleftskip\fi
      \box\floatbox
      \ifdone\hskip\effectiverightskip\fi\hss}}

\def\strc_floats_set_paragraph_variant
  {\bgroup
   \forgetall
   \postponenotes
   \dontcomplain
   \setbox\b_strc_floats_content\vbox{\borderedfloatbox}% \vpack >?
  %\page_backgrounds_add_local_to_box\b_strc_floats_content
   \ifnofloatcaption
     \global\setbox\floatbox\vpack{\box\b_strc_floats_content}%
   \else
     \strc_floats_check_caption_content
     \strc_floats_prepare_side_caption
     \strc_floats_apply_caption_command
    %\moveboxontogrid\b_strc_floats_caption{\floatcaptionparameter\c!grid}\d_strc_floats_caption_height
    %\page_backgrounds_add_local_to_box\b_strc_floats_caption
     \strc_floats_build_side_box
   \fi
   \egroup}

\def\strc_floats_prepare_side_caption
  {\dostarttaggednodetail\t!floatcaption
   \edef\p_strc_floats_caption_width{\floatcaptionparameter\c!width}%
   \edef\p_strc_floats_caption_align{\floatcaptionparameter\c!align}%
   \ifx\p_strc_floats_caption_width\v!max
     \strc_floats_prepare_side_caption_max
   \orelse\ifx\p_strc_floats_caption_width\v!fit
     \strc_floats_prepare_side_caption_fit
   \else
     \strc_floats_prepare_side_caption_width
   \fi
   \dostoptagged}

% these could be \??floatpreparesidecaption

% \setupfloat[figure][location=left]
% \setupcaption[figure][width=max]
%
% \placefigure{my figure caption my figure caption}{\framed[width=4cm,height=1cm]{}} \input tufte
% \placefigure{my figure caption}                  {\framed[width=4cm,height=1cm]{}} \input tufte

\def\strc_floats_prepare_side_caption_max
  {\setbox\b_strc_floats_caption\vbox
     {\strc_floats_caption_set_align
      \hsize\wd\b_strc_floats_content
      \strc_floats_make_complete_caption}}

\def\strc_floats_prepare_side_caption_fit % or center when smaller
  {\ifdim\wd\b_strc_floats_caption>\wd\b_strc_floats_content\relax
     \setbox\b_strc_floats_caption\vbox
       {\forgetall % needed?
        \strc_floats_caption_set_align
        \hsize\wd\b_strc_floats_content
        \strc_floats_make_complete_caption}%
   \else
     % maybe we should listen to the align option here (now side floats need the max option
     \setbox\b_strc_floats_caption\hpack to \wd\b_strc_floats_content
       {\hss\hbox{\strc_floats_make_complete_caption}\hss}%
   \fi}

\def\strc_floats_prepare_side_caption_width
  {\setbox\b_strc_floats_caption\vbox
     {\strc_floats_caption_set_align
      \hsize{\p_strc_floats_caption_width}% \wd\b_strc_floats_content
      \strc_floats_make_complete_caption}}

% % maybe (but then also prepare_page that way):
%
% \installcorenamespace{floatpreparesidecaption}
%
% \def\strc_floats_prepare_side_caption
%   {\dostarttaggednodetail\t!floatcaption
%    \edef\p_strc_floats_caption_width{\floatcaptionparameter\c!width}%
%    \edef\p_strc_floats_caption_align{\floatcaptionparameter\c!align}%
%    \expandnamespacemacro\??floatpreparesidecaption\p_strc_floats_caption_width\s!unknown
%    \dostoptagged}
%
% \defcsname\??floatpreparesidecaption\v!max\endcsname
%   {\setbox\b_strc_floats_caption\vbox
%      {\strc_floats_caption_set_align
%       \hsize\wd\b_strc_floats_content
%       \strc_floats_make_complete_caption}}
%
% \defcsname\??floatpreparesidecaption\v!fit\endcsname
%   {\ifdim\wd\b_strc_floats_caption>\wd\b_strc_floats_content\relax
%      \setbox\b_strc_floats_caption\vbox
%        {\forgetall % needed?
%         \hsize\wd\b_strc_floats_content
%         \strc_floats_make_complete_caption}%
%    \else
%      \setbox\b_strc_floats_caption\hbox to \wd\b_strc_floats_content
%        {\hss\hbox{\strc_floats_make_complete_caption}\hss}%
%    \fi}
%
% \defcsname\??floatpreparesidecaption\s!unknown\endcsname
%   {\setbox\b_strc_floats_caption\vbox
%      {\strc_floats_caption_set_align
%       \hsize\p_strc_floats_caption_width % \wd\b_strc_floats_content
%       \strc_floats_make_complete_caption}}

\def\strc_floats_locate_side_float#1%
  {\begingroup
   \alignstrutmode\zerocount
   \hsize\d_strc_float_temp_width \forgetall
   \alignedline{\floatparameter\c!location}\v!middle{#1}%
   \endgroup}

\def\strc_floats_build_side_box
  {\let\strc_floats_align_content\relax
   \let\strc_floats_align_caption\relax
   \strc_floats_build_box}

\setupcaptions
  [\c!topdistance=\zeropoint,
   \c!bottomdistance=\zeropoint]

\setupfloats % cheat as we want to set this per float
  [\c!topdistance=\floatcaptionparameter\c!topdistance,
   \c!bottomdistance=\floatcaptionparameter\c!bottomdistance]

\def\strc_floats_open_up
  {\setbox\floatbox\vpack\bgroup
     \offinterlineskip
     \vkern\scratchtopoffset
     \box\floatbox
     \vkern\scratchbottomoffset
   \egroup}

\def\strc_floats_set_open_up#1#2%
  {\ifchkdimension\floatparameter\c!topdistance\or
     \scratchtopoffset\lastchkdimension
   \orelse\ifchknumber\lastnamedcs\or
     \scratchtopoffset\lastnamedcs\lineheight
   \else
     \scratchtopoffset\zerocount
   \fi
   \ifchkdimension\floatparameter\c!bottomdistance\or
     \scratchbottomoffset\lastchkdimension
   \orelse\ifchknumber\lastnamedcs\or
     \scratchbottomoffset\lastnamedcs\lineheight
   \else
     \scratchbottomoffset\zerocount
   \fi
   \unless\ifzeropt\scratchtopoffset
     #1%
   \orunless\ifzeropt\scratchbottomoffset
     #1%
   \else
     #2%
   \fi}

\def\strc_floats_set_box % todo : \global\setbox, currently messy
  {\ifvisible
     \par
     \edef\floatcaptiondirectives{\floatparameter\c!location,\floatcaptionparameter\c!location}%
     \strc_floats_set_caption_criteria
     \ifconditional\c_strc_floats_par_float
       \strc_floats_set_paragraph_variant
     \else
       \strc_floats_set_page_variant
     \fi
     \strc_floats_set_local_dimensions
     \global\advanceby\totalnoffloats\plusone
     \ifconditional\c_floats_store_minimal_package \else
       \setbox\floatbox\hpack{\strc_float_save_data\box\floatbox}% still needed? we will do renumbering differently
     \fi
     \global\floatheight\htdp\floatbox
     \global\floatwidth\wd\floatbox
     \ifconditional\c_floats_store_minimal_package \else
       \ifinset\v!margin\floatlocation\else % gaat namelijk nog fout
         \setbox\floatbox\vpack
           {\parindent\zeropoint
            \box\floatbox}%
       \fi
     \fi
     \strc_floats_set_open_up\strc_floats_open_up\relax
     \wd\floatbox\floatwidth
     \ifdim{\floatheight+\lineheight}<\textheight \else
       \global\floatheight{\textheight-\lineheight}%
       \ht\floatbox\floatheight
       \dp\floatbox\zeropoint
       \showmessage\m!floatblocks{10}{\the\totalnoffloats}%
     \fi
   \fi}

% \def\dooutput{\sidefloatoutput} % redefinition of \dooutput

\definefloat
  [\v!figure]
  [\v!figures]

\definefloat
  [\v!table]
  [\v!tables]

\setupfloat
  [\v!table]
  [\c!frame=\v!off]

\definefloat
  [\v!intermezzo]
  [\v!intermezzi]

\definefloat
  [\v!graphic]
  [\v!graphics]

% float strategy, replaces some of the above macros

\installcorenamespace{floatmethods}

\mutable\lettonothing\floatmethod        % set by lua
\mutable\lettonothing\floatlabel         % set by lua
\mutable\lettonothing\floatcolumn        % set by lua
\mutable\lettonothing\floatrow           % set by lua
\mutable\lettonothing\floatspecification
\mutable\lettonothing\forcedfloatmethod  % set by lua and floatcombinations

\permanent\protected\def\setfloatmethodvariables#1% \floatmethod \floatlabel \floatrow \floatcolumn
  {\clf_analysefloatmethod{#1}} % move definition to lua end

%D \starttyping
%D \starttext
%D
%D test \placefigure[somewhere:alpha][whatever]{alpha}{}
%D test \placefigure[somewhere:beta] [whatever]{beta}{}
%D test \placefigure[somewhere:gamma][whatever]{gamma}{}
%D test \placefigure[somewhere:delta][whatever]{delta}{}
%D test \placefigure{}{}
%D
%D in \in{figure}[whatever] bla bla
%D
%D \placenamedfloat[figure][*l*]
%D
%D \placenamedfloat[figure][gamma]
%D \placenamedfloat[figure][beta]
%D
%D \stoptext
%D \stoptyping

\newconditional\c_page_floats_ignore_method

\permanent\protected\def\somesomewherefloat[#1]%
  {\page_floats_save_somewhere_float\s!somewhere{#1}}

\def\strc_floats_get_box
  {\ifvisible
     \ifconditional\c_page_floats_ignore_method
        \let\floatmethod\s!box
     \fi
     \ifcsname\??floatmethods\currentoutputroutine:\floatmethod\endcsname \else
       \let\floatmethod\floatlocationdefault
       \ifcsname\??floatmethods\currentoutputroutine:\floatmethod\endcsname \else
         \let\floatmethod\v!here
       \fi
     \fi
     \ifempty\forcedfloatmethod \else
       \let\floatmethod\forcedfloatmethod
     \fi
     \let\askedfloatmethod\floatmethod
     \ifexporting \ifx\askedfloatmethod\v!here \else
       \showmessage\m!floatblocks{15}{\askedfloatmethod,\v!here}%
       \let\floatlocation\v!here
     \fi \fi
     % [] will go
     \edef\floatlocationmethod{\floatmethod,\floatlocation}%
     \csname\??floatmethods\currentoutputroutine:\floatmethod\endcsname
   \fi}

\installcorenamespace{floatsettings}

\permanent\protected\def\installfloatmethod#1#2#3% routine keyword handler
  {\defcsname\??floatmethods#1:#2\endcsname{#3}}

\permanent\protected\def\handlefloatmethod#1%
  {\csname\??floatmethods\currentoutputroutine:#1\endcsname}

% \protected\def\installfloatmethod#1#2#3% routine keyword handler
%   {\ifcsname\??floatsettings#1:#2\endcsname \else
%      \expandafter\newtoks\csname\??floatsettings#1:#2\endcsname
%    \fi
%    \defcsname\??floatmethods#1:#2\endcsname{#3}}
%
% \protected\def\startfloatmethodsettings#1#2 #3\stopfloatmethodsettings
%   {\csname\??floatsettings#1:#2\endcsname\expandafter{\the\csname\??floatsettings#1:#2\endcsname#3}}
%
% \let\stopfloatmethodsettings\relax
%
% \protected\def\applyfloatmethodsettings#1#2{\the\??floatsettings#1:#2\endcsname}

\definesystemconstant{tblr}
\definesystemconstant{lrtb}
\definesystemconstant{tbrl}
\definesystemconstant{rltb}
\definesystemconstant{btlr}
\definesystemconstant{lrbt}
\definesystemconstant{btrl}
\definesystemconstant{rlbt}
\definesystemconstant{fxtb}
\definesystemconstant{fxbt}
\definesystemconstant{fixd}

% can move to page-one:

\installfloatmethod \s!singlecolumn \v!here        \page_one_place_float_here
\installfloatmethod \s!singlecolumn \v!force       \page_one_place_float_force
\installfloatmethod \s!singlecolumn \v!left        \page_one_place_float_left
\installfloatmethod \s!singlecolumn \v!right       \page_one_place_float_right
\installfloatmethod \s!singlecolumn \v!text        \page_one_place_float_text
\installfloatmethod \s!singlecolumn \v!top         \page_one_place_float_top
\installfloatmethod \s!singlecolumn \v!bottom      \page_one_place_float_bottom
\installfloatmethod \s!singlecolumn \v!auto        \page_one_place_float_auto
\installfloatmethod \s!singlecolumn \v!margin      \page_one_place_float_margin
\installfloatmethod \s!singlecolumn \v!opposite    \page_one_place_float_face
\installfloatmethod \s!singlecolumn \v!page        \page_one_place_float_page
\installfloatmethod \s!singlecolumn \v!leftpage    \page_one_place_float_leftpage
\installfloatmethod \s!singlecolumn \v!rightpage   \page_one_place_float_rightpage
\installfloatmethod \s!singlecolumn \v!inmargin    \page_one_place_float_inmargin
\installfloatmethod \s!singlecolumn \v!inleft      \page_one_place_float_leftmargin
\installfloatmethod \s!singlecolumn \v!inright     \page_one_place_float_rightmargin
\installfloatmethod \s!singlecolumn \v!leftmargin  \page_one_place_float_leftmargin
\installfloatmethod \s!singlecolumn \v!rightmargin \page_one_place_float_rightmargin
\installfloatmethod \s!singlecolumn \v!leftedge    \page_one_place_float_leftedge
\installfloatmethod \s!singlecolumn \v!rightedge   \page_one_place_float_rightedge
\installfloatmethod \s!singlecolumn \v!somewhere   \page_one_place_float_somewhere
\installfloatmethod \s!singlecolumn \v!backspace   \page_one_place_float_backspace
\installfloatmethod \s!singlecolumn \v!cutspace    \page_one_place_float_cutspace
\installfloatmethod \s!singlecolumn \s!tblr        \page_one_place_float_top
\installfloatmethod \s!singlecolumn \s!lrtb        \page_one_place_float_top
\installfloatmethod \s!singlecolumn \s!tbrl        \page_one_place_float_top
\installfloatmethod \s!singlecolumn \s!fxtb        \page_one_place_float_top
\installfloatmethod \s!singlecolumn \s!rltb        \page_one_place_float_top
\installfloatmethod \s!singlecolumn \s!btlr        \page_one_place_float_bottom
\installfloatmethod \s!singlecolumn \s!lrbt        \page_one_place_float_bottom
\installfloatmethod \s!singlecolumn \s!btrl        \page_one_place_float_bottom
\installfloatmethod \s!singlecolumn \s!rlbt        \page_one_place_float_bottom
\installfloatmethod \s!singlecolumn \s!fxbt        \page_one_place_float_bottom
\installfloatmethod \s!singlecolumn \s!fixd        \page_one_place_float_force

%D Local floats:

\installcorenamespace{localfloats}
\installcorenamespace{localfloatstack}

\installsetuponlycommandhandler \??localfloats {localfloats}

\setuplocalfloats
  [%\c!before=\blank,
   %\c!after=\blank,
   \c!inbetween=\blank]

\initializeboxstack\??localfloatstack

%newcount  \c_strc_localfloats_n  \aliased\let \noflocalfloats\c_strc_localfloats_n
\newinteger\c_strc_localfloats_n  \aliasinteger\noflocalfloats\c_strc_localfloats_n

\permanent\protected\def\resetlocalfloats
  {\global\c_strc_localfloats_n\zerocount
   \initializeboxstack\??localfloatstack}

\permanent\protected\def\somelocalfloat
  {\global\advanceby\c_strc_localfloats_n\plusone
   \savebox\??localfloatstack{\the\c_strc_localfloats_n}{\box\floatbox}}

\permanent\protected\def\getlocalfloats
  {\dorecurse\c_strc_localfloats_n
     {\ifnum\recurselevel=\plusone % 1\relax
        \directlocalfloatsparameter\c!before
      \else
        \directlocalfloatsparameter\c!inbetween
      \fi
      \dontleavehmode\hpack{\foundbox\??localfloatstack\recurselevel}% \restorebox...
      \ifnum\recurselevel=\c_strc_localfloats_n\relax
        \directlocalfloatsparameter\c!after
      \fi}}

\permanent\protected\def\flushlocalfloats
  {\getlocalfloats
   \resetlocalfloats}

% \protected\def\getlocalfloat#1%
%   {\normalexpanded{\foundbox{\??localfloatstack}{\number#1}}}% \vbox{\restorebox...}

\permanent\protected\def\getlocalfloat#1%
  {\foundbox\??localfloatstack{\number#1}} % \vbox{\restorebox...}

\permanent\protected\def\forcelocalfloats
  {\let\forcedfloatmethod\v!local}

\installfloatmethod \s!singlecolumn \v!local \somelocalfloat
\installfloatmethod \s!multicolumn  \v!local \somelocalfloat
\installfloatmethod \s!mixedcolumn  \v!local \somelocalfloat
\installfloatmethod \s!columnset    \v!local \somelocalfloat

%D Defined at the \LUA\ end:
%D
%D \starttyping
%D \reorderfloats[figure] % can be a list
%D \stoptyping

\protect \endinput