%D \module
%D   [       file=strc-mar,
%D        version=1997.03.31,
%D          title=\CONTEXT\ Structure Macros,
%D       subtitle=Markings,
%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 Structure Macros / Markings}

\unprotect

\prependtoks \getallmarks \to \everybeforepagebody
\prependtoks \setallmarks \to \everyafterpagebody  % currently \relax

% voor 'interne' doeleinden zijn beschikbaar:
%
%   \fetchmark[naam][plaats]

\def\mainmarking#1%
  {\ifcsname\??mk#1\c!coupling\endcsname
     \csname\??mk#1\c!coupling\endcsname
   \fi}

\def\fastresetmarker#1%
  {\ifcsname\??mk#1\c!coupling\endcsname
     \@EA\resetmark\csname\??mk\csname\??mk#1\c!coupling\endcsname\endcsname
   \fi}

\def\fastresetmarkerlist[#1]%
  {\expanded{\rawprocesscommalist[#1]}\fastresetmarker}

\def\doresetmarking[#1]%
  {\processcommalist[#1]\fastresetmarker}

\def\resetmarking
  {\dosingleargument\doresetmarking}

\def\dosetupmarking[#1][#2]%
  {\def\docommand##1{\getparameters[\??mk##1][#2]}%
   \processcommalist[#1]\docommand}

\def\setupmarking
  {\dodoubleargument\dosetupmarking}

% betere protectie

\letvalue{\??mk\??mk\v!previous}\gettopmark
\letvalue{\??mk\??mk\v!first   }\getfirstmark
\letvalue{\??mk\??mk\v!last    }\getbotmark
\letvalue{\??mk\??mk\v!current }\getcurrentmark

% todo: make it work in balancing
%
% \definemarking[vers][]
% \setupheadertexts
%   [\doiftext{\getmarking[vers][first]}
%      {\doiftextelse{\getmarking[vers][column:last]}
%         {\getmarking[vers][first] -- \getmarking[vers][column:last]}
%         {\getmarking[vers][first]}}]
% \starttext
%   \startcolumns[n=2,balance=no]
%     \dorecurse{10}{\expanded{\marking[vers]{\recurselevel}} \recurselevel:\dorecurse{4}{\input ward } \endgraf}
%   \stopcolumns
% \stoptext

\letvalue{\??mk\??mk\v!column:\v!first}\getsplitfirstmark
\letvalue{\??mk\??mk\v!column:\v!last }\getsplitbottommark

\ifx\decouplemarking\undefined \def\decouplemarking[#1]{} \fi

\let\alldefinedmarks\empty

\def\dododefinemarking[#1][#2]%
  {\getparameters[\??mk#1]
     [\c!expansion=\v!no, % saves a macro
      \c!separator={\space\emdash\space},
      \c!limittext=\@@kolimittext,
          \c!state=\v!start]%
   \decouplemarking[#1]%  % no coupling with sections
   \setevalue{\??mk#1\c!coupling}{#2}%
   \doglobal\addtocommalist{#2}\alldefinedmarks
   \expandafter\newmark\csname\??mk#2\endcsname
   \showmessage\m!systems{13}{#1,[#2]}}

\def\dodefinemarking[#1][#2]%
  {\doifelsenothing{#2}
     {\dododefinemarking[#1][#1]}
     {\dododefinemarking[#1][#2]}}

\def\definemarking
  {\dodoubleempty\dodefinemarking}

\def\definerawmarking[#1]% global ! ! ! !
  {\getgparameters[\??mk#1]
     [\c!expansion=\v!no,  % saves a macro
      \c!separator={ --- }, % watch the spaces
      \c!limittext=,
        \c!state=\v!start]%
   \setxvalue{\??mk#1\c!coupling}{#1}%
   \expandafter\newmark\csname\??mk#1\endcsname
   \showmessage\m!systems{13}{#1}}

\let\nomarking\empty

\def\fetchmark[#1][#2]% % expandable / never use \unexpanded
  {\ifcsname\??mk::#1\endcsname % saved mark
     \csname\??mk::\??mk::#2\@EA\@EA\@EA\endcsname
     \csname\??mk::#1\endcsname
   \else\ifcsname\??mk#1\c!coupling\endcsname % real mark
     \csname\??mk\??mk#2\@EA\endcsname
     \csname\??mk\csname\??mk#1\c!coupling\endcsname\endcsname
   \fi\fi}

\letvalue{\??mk::\??mk::\v!previous}\firstoffourarguments
\letvalue{\??mk::\??mk::\v!first   }\secondoffourarguments
\letvalue{\??mk::\??mk::\v!last    }\thirdoffourarguments
\letvalue{\??mk::\??mk::\v!current }\fourthoffourarguments

% this version can be used when a page is built up in steps without
% feedback of the otr'd list to the mvl (i.e.\ a page made of pages,
% as in column sets where content is buffered)

% reset at begin
% preset before page
% bubble in column
% refresh at end

\def\refreshsavedmark[#1][#2]% mark tag (packing saves many hash entries)
  {\setxvalue{\??mk::#1:#2}%
     {{\@EA\ifx\csname\??mk::#1:pp\endcsname\relax
         % empty
       \else
         \csname\??mk::#1:pp\endcsname
       \fi}%
      {\@EA\ifx\csname\??mk::#1:ff\endcsname\relax
         \fetchmark[#1][\v!first]%
       \else
         \csname\??mk::#1:ff\endcsname
       \fi}%
      {\fetchmark[#1][\v!last]}%
      {\fetchmark[#1][\v!current]}}%
    \setxvalue{\??mk::#1:pp}{\fetchmark[#1][\v!first]}%
    \letgvalue{\??mk::#1:ff}\relax
    }

\def\bubblesavedmark[#1][#2]% no packing (not now, maybe make a six-pack later)
  {\@EA\ifx\csname\??mk::#1:ff\endcsname\relax
     \setxvalue{\??mk::#1:ff}{\fetchmark[#1][\v!first]}%
   \fi}

\def\resetsavedmark[#1][#2]% mark tag
  {\doifelsenothing{\fetchmark[#1][\v!previous]}
     {\letgvalue{\??mk::#1:pp}\relax}
     {\setxvalue{\??mk::#1:pp}{\fetchmark[#1][\v!previous]}}%
   \doifelsenothing{\fetchmark[#1][\v!first]}
     {\letgvalue{\??mk::#1:ff}\relax}
     {\setxvalue{\??mk::#1:ff}{\fetchmark[#1][\v!first]}}%
   \letgvalue{\??mk::#1:#2}\emptysavedmark}

\def\presetsavedmark[#1][#2]% mark tag
  {\letgvalue{\??mk::#1:#2}\emptysavedmark}

\def\emptysavedmark{{}{}{}{}}

% new (can be used in column sets)
%
% \getsavedmarking[M][previous]
% \getsavedmarking[M][first]
% \getsavedmarking[M][last]

\def\getsavedmarking
  {\dodoubleargument\dogetsavedmarking}

\def\dogetsavedmarking[#1][#2]%
  {\doifelse{#2}\v!previous
     {\getmarking[#1][1][\v!previous]}
     {\doifelse{#2}\v!first
        {\getmarking[#1][1][\v!first]}
        {\getmarking[#1][\v!last]}}}

% fetching

\def\fetchtwomarks[#1]%
  {\dofetchtwomarks[#1][#1]}

\def\fetchallmarks[#1]%
  {\dofetchallmarks[#1][#1]}

\def\dofetchtwomarks[#1][#2]% class class:tag
  {\doifsomething{\fetchmark[#2][\v!first]}
     {\fetchmark[#2][\v!first]%
      \doifsomething{\fetchmark[#2][\v!last]}
        {\doifnot{\fetchmark[#2][\v!first]}{\fetchmark[#2][\v!last]}
            {\getvalue{\??mk#1\c!separator}\fetchmark[#2][\v!last]}}}}

\def\dofetchallmarks[#1][#2]%
  {\doifsomething{\fetchmark[#2][\v!first]}
     {\doifsomething{\fetchmark[#2][\v!previous]}
        {\doifnot{\fetchmark[#2][\v!previous]}{\fetchmark[#2][\v!first]}
           {\fetchmark[#2][\v!previous]\getvalue{\??mk#1\c!separator}}}}%
      \fetchtwomarks[#1][#2]}

% \newtoks \everymarking

% \def\Interesting{\doifmodeelse{*\v!marking}{Interesting}{Boring}}
% \setupheadertexts[chapter]
% \starttext
%     \chapter{This Is \Interesting}
% \stoptext

\def\dogetmarking[#1][#2][#3]%
  {\doifvalue{\??mk#1\c!state}\v!start
     {\bgroup
      \setsystemmode\v!marking
      \the\everymarking
     %\def\nomarking##1{\unknown\ }%
      \def\nomarking{\splitsequence{\getvalue{\??mk#1\c!limittext}}}%
      \setfullsectionnumber{\??mk#1}%
      \ifthirdargument
        \processaction % slow
          [#3]
          [   \v!both=>{\dofetchtwomarks[#1][#1:#2]},
               \v!all=>{\dofetchallmarks[#1][#1:#2]},
           \s!default=>{\fetchmark          [#1:#2][\v!first]},
           \s!unknown=>{\fetchmark          [#1:#2][#3]}]%
      \else
        \processaction % slow
          [#2]
          [   \v!both=>{\dofetchtwomarks[#1][#1]},
               \v!all=>{\dofetchallmarks[#1][#1]},
           \s!default=>{\fetchmark          [#1][\v!first]},
           \s!unknown=>{\fetchmark          [#1][#2]}]%
      \fi
      \egroup}}

\def\nogetmarking[#1][#2][#3]%
  {}

\unexpanded\def\getmarking
  {\dotripleargument\dogetmarking}

\let\setsomemark\setmark

\def\domarking[#1]#2%
  {\ifcsname\??mk#1\c!coupling\endcsname
     \bgroup
     \doifelsevalue{\??mk#1\c!expansion}\v!yes
       \expandmarkstrue\expandmarksfalse
     \@EA\setsomemark\csname\??mk\csname\??mk#1\c!coupling\endcsname\endcsname{#2}%
     \egroup
   \fi}

\def\marking
  {\dosingleargument\domarking}

%D Used in placing text lines.

\def\doifelsemarking#1%
  {\ifundefined{\??mk#1\c!coupling}%
     \expandafter\secondoftwoarguments
   \else
     \expandafter\firstoftwoarguments
   \fi}

%D And then \unknown\ we had a chaptertitle packaged in a
%D makeup environment. And we don't want to loose marks there!

\newbox\collectedmarks

\def\flushmarks % use with care to avoid empty pages
  {\ifvoid\collectedmarks\else\unhbox\collectedmarks\fi}

\def\postponemarks
  {\let\setsomemark\postponemark}

\def\postponemark#1#2%
  {%\writestatus{marks}{postponing \string#1 => #2}%
   \global\setbox\collectedmarks\hbox
     {\unhbox\collectedmarks\setmark{#1}{#2}}}

\protect \endinput

% Pseudo marks: (for Hraban)
%
% \def\RegisterPageMark#1#2%
%   {\iftrialtypesetting \else
%      \doglobal\increment\NameCounter
%      \textreference[#1:t:\NameCounter]{#2}%
%      \doifreferencefoundelse{#1:t:\NameCounter}
%        {\doifundefined{#1:f:\currentrealreference}%
%           {\setxvalue{#1:f:\currentrealreference}%
%              {\noexpand\in[#1:t:\NameCounter]}}%
%         \setxvalue{#1:l:\currentrealreference}%
%           {\noexpand\in[#1:t:\NameCounter]}}%
%        {}%
%    \fi}
%
% \def\GetFirstOnPage#1{\getvalue{#1:f:\realfolio}}
% \def\GetLastOnPage #1{\getvalue{#1:l:\realfolio}}
%
% \setupheadertexts[\GetFirstOnPage{Name}][\GetLastOnPage{Name}]
%
% \starttext
%
% \def\Name#1{\RegisterPageMark{Name}{#1}#1}
% \def\TestLine#1{\NC test \NC \Name {test: #1} \NC \NR}
%
% \starttabulate
% \dorecurse{100}{\expanded{\TestLine{\recurselevel}}}
% \stoptabulate
%
% \stoptext