%D \module
%D   [       file=page-ins,
%D        version=2002.04.16, % was core-ins
%D          title=\CONTEXT\ Insertion Macros,
%D       subtitle=Insertions,
%D         author=Hans Hagen,
%D           date=\currentdate,
%D      copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
%C
%C This module is part of the \CONTEXT\ macro||package and is
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.

\writestatus{loading}{ConTeXt Core Macros / Insertions}

%D Insertions are special data collections that are associated to \TEX's internal
%D page builder. When multiple footnote classes were introduced, I decided to
%D isolate some of the functionality in a module.

\registerctxluafile{page-ins}{autosuffix}

\unprotect

%D Because we need to deal with inserts at the \LUA\ end as well, we provide a
%D proper installer.

\installcorenamespace{insertion}
\installcorenamespace{insertionnumber}

\installcommandhandler \??insertion {insertion} \??insertion

\setupinsertion
  [%c!n=\plusone,
   %c!distance=\zeropoint,
   %c!maxheight=\maxdimen,
   %c!factor=\plusthousand,
   \c!location=\v!page]

\newconstant\insertionmigrationmode

\def\page_inserts_check_anchoring
  {\edef\p_anchoring{\namedinsertionparameter\empty\c!anchoring}%
   \insertionmigrationmode\ifx\p_anchoring\v!auto\plusone\else\zerocount\fi
   \clf_setinsertmigration{\p_anchoring}}

\appendtoks
    \ifempty\currentinsertionparent
        \page_inserts_check_anchoring
    \fi
\to \everysetupinsertion

\setupinsertion
  [\c!anchoring=\v!auto]

\appendtoks
    \page_inserts_check_anchoring
\to \everystarttext % or \everyjob

\newinteger\currentinsertionnumber % This is a count and not a macro !

\newtoks\t_page_inserts_list

\mutable\let\doprocessinsert\gobbleoneargument % probably kind of obsolete now

%D Maybe some day we will move settings here.

\permanent\protected\def\setcurrentinsertion#1%
  {\cdef\currentinsertion{#1}%
   \currentinsertionnumber\csname\??insertionnumber\currentinsertion\endcsname}

\permanent\def\namedinsertionnumber#1{\csname\??insertionnumber#1\endcsname}

\protected\def\page_inserts_synchronize_registers
  {\currentinsertionnumber\csname\??insertionnumber\currentinsertion\endcsname}

\appendtoks
    \ifempty\currentinsertionparent \else
        \page_inserts_synchronize_registers
    \fi
\to \everysetupinsertion

\protected\def\page_inserts_process#1% beware, this adapts currentinsertion !
  {\cdef\currentinsertion{#1}%
   \currentinsertionnumber\csname\??insertionnumber\currentinsertion\endcsname
   \doprocessinsert\currentinsertionnumber} % old method

\permanent\protected\def\processinsertions
  {\expand\t_page_inserts_list}

% \permanent\protected\def\synchronizeinsertions
%   {\let\doprocessinsert\page_inserts_synchronize
%    \processinsertions}
%
% \protected\def\page_inserts_synchronize#1% yes or no
%   {\ifvoid#1\else
%      \page_inserts_inject#1{\unvbox#1}%
%    \fi}

\permanent\protected\def\doifelseinsertion#1%
  {\ifcsname\??insertionnumber#1\endcsname
        \expandafter\firstoftwoarguments
   \else
     \expandafter\secondoftwoarguments
   \fi}

\aliased\let\doifinsertionelse\doifelseinsertion

% \protected\def\startinsertion[#1]%
%   {\page_inserts_inject\csname\??insertionnumber#1\endcsname\bgroup}
%
% \protected\def\stopinsertion
%   {\egroup}

% For the moment we use the regular insertion allocator so that users can still
% define their own insertions (not that they will play nicely with all context
% mechanisms then). We can use the dimensions at the \LUA\ end so we don't need to
% pass pass them explicitly. Actually, when we see an insertion node at that end,
% we already know the number.

% Per January 2025 we use the primitives directly becuase we won't switch back
% to the old mechanism.

\insertmode\plustwo \pushoverloadmode \newinteger\insertmode \popoverloadmode

% \ifnum\insertmode=\plustwo

%   \protected\def\page_inserts_inject        {\insert}

%   \protected\def\page_inserts_set_limit     {\insertlimit}
%   \protected\def\page_inserts_set_distance  {\insertdistance}
%   \protected\def\page_inserts_set_multiplier{\insertmultiplier}
%   \protected\def\page_inserts_set_penalty   {\insertpenalty}
%   \protected\def\page_inserts_set_maxdepth  {\insertmaxdepth}
%   \protected\def\page_inserts_set_lineheight{\insertlineheight}
%   \protected\def\page_inserts_set_linedepth {\insertlinedepth}

%   \protected\def\page_inserts_get_limit     {\insertlimit}
%   \protected\def\page_inserts_get_distance  {\insertdistance}
%   \protected\def\page_inserts_get_multiplier{\insertmultiplier}
%   \protected\def\page_inserts_get_penalty   {\insertpenalty}
%   \protected\def\page_inserts_get_maxdepth  {\insertmaxdepth}

%   \protected\def\page_inserts_get_boxed     {\insertbox}
%   \protected\def\page_inserts_get_copied    {\insertcopy}
%   \protected\def\page_inserts_get_unboxed   {\insertunbox}
%   \protected\def\page_inserts_get_uncopied  {\insertuncopy}

%   \protected\def\page_inserts_get_height    {\insertheight}
%   \protected\def\page_inserts_get_depth     {\insertdepth}
%   \protected\def\page_inserts_get_width     {\insertwidth}

% \else
%
%     \protected\def\page_inserts_inject        {\insert}
%
%     \protected\def\page_inserts_set_limit     {\global\dimen}
%     \protected\def\page_inserts_set_distance  {\global\skip }
%     \protected\def\page_inserts_set_multiplier{\global\count}
%
%     \protected\def\page_inserts_get_limit     {\dimen}
%     \protected\def\page_inserts_get_distance  {\skip }
%     \protected\def\page_inserts_get_multiplier{\count}
%
%     \protected\def\page_inserts_get_boxed     {\box}
%     \protected\def\page_inserts_get_copied    {\copy}
%     \protected\def\page_inserts_get_unboxed   {\unvbox}
%     \protected\def\page_inserts_get_uncopied  {\unvcopy}
%
%     \protected\def\page_inserts_get_height    {\ht}
%     \protected\def\page_inserts_get_depth     {\dp}
%     \protected\def\page_inserts_get_width     {\wd}
%
% \fi

\newinteger\c_page_inserts_last_allocated

\appendtoks
    \ifempty\currentinsertionparent
        \ifcsname\??insertionnumber\currentinsertion\endcsname
          % bad news
        \else
          %expandafter\newinsert\csname\??insertionnumber\currentinsertion\endcsname
          \global\advanceby\c_page_inserts_last_allocated\plusone
          \global\expandafter\integerdef\csname\??insertionnumber\currentinsertion\endcsname\c_page_inserts_last_allocated
          \page_inserts_synchronize_registers
          \clf_defineinsertion
            {\currentinsertion}%
            {%
                number \currentinsertionnumber
            }%
          \relax
%           \t_page_inserts_list\expandafter\expandafter\expandafter
%             {\expandafter\the\expandafter\t_page_inserts_list
%              \expandafter\page_inserts_process\csname\??insertionnumber\currentinsertion\endcsname}%
          \xtoksapp\t_page_inserts_list{\page_inserts_process{\currentinsertion}}%
          \insertmultiplier\currentinsertionnumber\plusthousand
          \insertdistance  \currentinsertionnumber\zeropoint
          \insertlimit     \currentinsertionnumber\maxdimen
       \fi
    \else
      \letcsname\??insertionnumber\currentinsertion\expandafter\endcsname
         \csname\??insertionnumber\currentinsertionparent\endcsname
    \fi
\to \everydefineinsertion

\appendtoks
    \ifempty\currentinsertionparent \else
        \clf_setupinsertion
          {\currentinsertion}
          {%
            location {\insertionparameter\c!location}%
          }%
        \relax
    \fi
\to \everysetupinsertion

\protected\def\page_inserts_set_location#1#2% fast one
  {\clf_setinsertionlocation{#1}{#2}}

%D Auxiliary macros:

\def\page_insert_insertion_height#1%
  {\dimexpr\expandafter\page_insert_insertion_height_indeed\csname\??insertionnumber#1\endcsname\relax}

% \def\page_insert_insertion_height_indeed#1%
%   {\ifvoid#1\zeropoint\else1\page_inserts_get_distance#1+\ht#1\fi}

\def\page_insert_insertion_height_indeed#1%
  {\ifzeropt\insertheight#1\zeropoint\else\dimexpr\insertdistance#1\relax+\insertheight#1\fi}

%D Tricky stuff:
%D
%D \starttyping
%D \page_inserts_detach\floatbox      % \detachinsertions\floatbox
%D \page_otr_command_flush_float_box
%D \page_inserts_attach               % \attachinsertions\attachinsert
%D \stoptyping

\permanent\protected\def\attachinsert#1%
  {\dontleavehmode#1\par}

\def\page_inserts_detach#1%
  {\detachinsertions#1\relax}

\def\page_inserts_attach_indeed
  {\dorecurse
     {\nofdetachedinsertions\currentnoteinsertionnumber}
     {\attachinsertion\currentnoteinsertionnumber\attachinsert}}

\def\page_inserts_attach
  {\strc_notes_process\page_inserts_attach_indeed}

%D Tracing:
%D
%D \starttyping
%D \enabletrackers[inserts.split]
%D
%D \definenote[foonote]
%D \definenote[fonote]
%D
%D \starttext
%D     \setupnote[footnote][height=4cm]
%D     \setupnote[foonote] [height=4cm]
%D     \setupnote[fonote]  [height=4cm]
%D     \dorecurse{40}{
%D         Test #1.
%D         \footnote{footnote #1}
%D         \footnote{footnote #1}
%D         \ifodd#1\relax
%D             \foonote{foonote #1}
%D             \foonote{foonote #1}
%D             \fonote{fonote #1}
%D         \fi
%D         \par
%D     }
%D     \page[note] \page % needed otherwise empty page
%D
%D     \setupnote[footnote][height=\maxdimen]
%D     \setupnote[foonote] [height=\maxdimen]
%D     \setupnote[fonote]  [height=\maxdimen]
%D     tufte    \footnote{\dorecurse{10}{\samplefile{tufte}}}
%D     ward     \foonote {\dorecurse{10}{\samplefile{ward}}}
%D     zelensky \fonote  {\dorecurse{10}{\samplefile{zelensky}}}
%D     \page[note] \page % needed otherwise empty page
%D \stoptext
%D \stoptyping

\permanent\protected\def\insertchecksplitfirst#1{\setbox\scratchbox\hpack{\llap{\tttf\darkred#1 <<<\quad}}\ht\scratchbox\zeropoint\dp\scratchbox\zeropoint} % artifact
\permanent\protected\def\insertchecksplitlast #1{\setbox\scratchbox\hpack{\rlap{\tttf\darkred\quad>>> #1}}\ht\scratchbox\zeropoint\dp\scratchbox\zeropoint} % artifact

\protect \endinput
