%D \module
%D   [       file=strc-tag,
%D        version=2010.07.16,
%D          title=\CONTEXT\ Structure Macros,
%D       subtitle=Tags,
%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.

% labels: no language needed
% key/values and other names might change (and probably will)

\writestatus{loading}{ConTeXt Structure Macros / Tags}

\registerctxluafile{strc-tag}{autosuffix}

\unprotect

%D Eventually these labels will either move to the modules where they're used, or
%D they will en dup in mult-tag.

\definetagconstant{document}
\definetagconstant{documentpart}

\definetagconstant{division}
\definetagconstant{paragraph}
\definetagconstant{subparagraph}
\definetagconstant{p}
\definetagconstant{highlight}
\definetagconstant{ornament}
\definetagconstant{break}
\definetagconstant{placeholder}

\definetagconstant{construct}
\definetagconstant{constructleft}
\definetagconstant{constructright}
\definetagconstant{constructcontent}

% \definetagconstant{sectionblock}

\definetagconstant{section}
\definetagconstant{sectioncaption}
\definetagconstant{sectiontitle}
\definetagconstant{sectionnumber}
\definetagconstant{sectioncontent}

\definetagconstant{itemgroup}
\definetagconstant{item}
\definetagconstant{itemtag}
\definetagconstant{itemcontent}
\definetagconstant{itemhead}
\definetagconstant{itembody}

\definetagconstant{items}
\definetagconstant{itemtexts}
\definetagconstant{itemtext}
\definetagconstant{itemsymbols}
\definetagconstant{itemsymbol}

\definetagconstant{description}
\definetagconstant{descriptiontag}
\definetagconstant{descriptioncontent}
\definetagconstant{descriptionsymbol}

\aliastagconstant {construction}       {description}
\aliastagconstant {constructiontag}    {descriptiontag}
\aliastagconstant {constructioncontent}{descriptioncontent}
\aliastagconstant {constructionsymbol} {descriptionsymbol}

\definetagconstant{verbatimblock}
\definetagconstant{verbatimlines}
\definetagconstant{verbatimline}
\definetagconstant{verbatim}

\definetagconstant{lines}
\definetagconstant{line}
\definetagconstant{linenumber}

\definetagconstant{sorting}
\definetagconstant{synonym}

\definetagconstant{register}
\definetagconstant{registerlocation}
\definetagconstant{registersection}
\definetagconstant{registertag}
\definetagconstant{registerentries}
\definetagconstant{registerentry}
\definetagconstant{registercontent}
\definetagconstant{registersee}
\definetagconstant{registerpages}
\definetagconstant{registerpage}
\definetagconstant{registerpagerange}
\definetagconstant{registerfrompage}
\definetagconstant{registertopage}
\definetagconstant{registerseparator}

\definetagconstant{table}
\definetagconstant{tablerow}
\definetagconstant{tablecell}
\definetagconstant{tableheadcell}
\definetagconstant{tablehead}
\definetagconstant{tablebody}
\definetagconstant{tablefoot}

\definetagconstant{tabulate}
\definetagconstant{tabulaterow}
\definetagconstant{tabulatecell}
\definetagconstant{tabulateheadcell}
\definetagconstant{tabulatehead}
\definetagconstant{tabulatebody}
\definetagconstant{tabulatefoot}

\definetagconstant{math}
\definetagconstant{mtable}
\definetagconstant{mtr}
\definetagconstant{mtd}

\definetagconstant{maction}

\definetagconstant{mstack}

\definetagconstant{mstacker}
\definetagconstant{mstackertop}
\definetagconstant{mstackermid}
\definetagconstant{mstackerbot}

\definetagconstant{mextensible}

\definetagconstant{mfunction}
\definetagconstant{mfunctionstack}

\definetagconstant{mdelimited}
\definetagconstant{mdelimitedstack}

\definetagconstant{mfraction}
\definetagconstant{mfractionstack}

\definetagconstant{munit}
\definetagconstant{mdigits}

\aliastagconstant {mtablerow} {mtr}
\aliastagconstant {mtablecell}{mtd}

\definetagconstant{munderover}
\definetagconstant{munder}
\definetagconstant{mover}
\definetagconstant{mtext}

\definetagconstant{mrow}

\definetagconstant{list}
\definetagconstant{listitem}
\definetagconstant{listtag}
\definetagconstant{listcontent}
\definetagconstant{listdata}
\definetagconstant{listpage}
\definetagconstant{listtext}

\definetagconstant{delimitedblock}
\definetagconstant{delimited}
\definetagconstant{delimitedsymbol}
\definetagconstant{delimitedcontent}

%aliastagconstant {delimitedblock}{delimited} % no longer

\definetagconstant{subsentence}
\definetagconstant{subsentencecontent}
\definetagconstant{subsentencesymbol}

\definetagconstant{float}
\definetagconstant{floatcaption}
\definetagconstant{floatlabel}
\definetagconstant{floattext}
\definetagconstant{floatnumber}
\definetagconstant{floatcontent}
\definetagconstant{subfloat}

\definetagconstant{image}

\definetagconstant{mpgraphic}

\definetagconstant{formulaset}
\definetagconstant{formula}
\definetagconstant{formulacaption}
\definetagconstant{formulalabel}
\definetagconstant{formulanumber}
\definetagconstant{formulacontent}
\definetagconstant{subformula}

\definetagconstant{link}
\definetagconstant{reference}

\definetagconstant{nativation}
\definetagconstant{nativationbutton}
\definetagconstant{nativationmenu}
\definetagconstant{nativationmenuitem}
\definetagconstant{nativationaction}

\definetagconstant{margintext}
\definetagconstant{margintextblock}
\definetagconstant{marginanchor}

\definetagconstant{linetext}

% we might opt for verbose variants so this is experimental:

\definetagconstant{label}
\definetagconstant{number}

\definetagconstant{ignore}
\definetagconstant{private}

\definetagconstant{mid}
\definetagconstant{sub}
\definetagconstant{sup}
\definetagconstant{subsup}

\definetagconstant{unit}
\definetagconstant{quantity}
%definetagconstant{number}

\definetagconstant{combination}
\definetagconstant{combinationpair}
\definetagconstant{combinationcontent}
\definetagconstant{combinationcaption}

\definetagconstant{publications}
\definetagconstant{publication}
\definetagconstant{pubfld}

\definetagconstant{citation}
\definetagconstant{cite}

\definetagconstant{narrower}

\definetagconstant{block}

\definetagconstant{userdata}

\definetagconstant{textdisplay}

\definetagconstant{verse}
\definetagconstant{versetag}
\definetagconstant{verseseparator}
\definetagconstant{versecontent}

\definetagconstant{navigation}
\definetagconstant{navigationbutton}
\definetagconstant{navigationmenu}
\definetagconstant{navigationmenuitem}
\definetagconstant{navigationaction}
\definetagconstant{navigationpage}

% \setuptaglabeltext
%   [en]
%   [\t!document=document]

% the real code

\definesystemattribute[tagged][public,pickup] % pickup added
\definesystemattribute[image] [public]

% \setelementbackendtag [#1][#2] % define at the lua end
% \setelementnature     [#1][#2] % define at the lua end

\permanent\protected\def\ignoretagsinexport[#1]{\clf_ignoretagsinexport{#1}} % todo: public implementor

\installcorenamespace{tagging}

\installsetuponlycommandhandler \??tagging {tagging}

% It makes no sense to have labels ... maybe some day as a last 'replace' in the export
% which might be more efficient then ... okay, we now cannot overload but who cares.

% \strc_tags_start_userdata              % defined at the lua end
% \strc_tags_stop                        % defined at the lua end
% \strc_tags_set_aspect                  % defined at the lua end
% \strc_tags_get_element_tag             % defined at the lua end
% \strc_tags_set_element_user_properties % defined at the lua end

\permanent\protected\def\strc_tags_element_start_yes
  {\iftrialtypesetting
     \expandafter\gobbletwooptionals
   \else
     \expandafter\strc_tags_start_userdata
   \fi}

\permanent\protected\def\strc_tags_element_stop_yes
  {\iftrialtypesetting
     % nothing
   \else
     \expandafter\strc_tags_stop
   \fi}

\protected\def\strc_tags_enable_elements
  {\enforced\let\startelement    \strc_tags_element_start_yes
   \enforced\let\stopelement     \strc_tags_element_stop_yes
   \enforced\let\dosettagproperty\strc_tags_set_aspect}

\protected\def\strc_tags_disable_elements
  {\enforced\let\startelement    \gobbletwooptionals
   \enforced\let\stopelement     \relax
   \enforced\let\dosettagproperty\gobbletwoarguments}

% beware: making these unexpanded spoils tables (noalign problem)

\def\strc_tags_enabled_start_no_detail
  {\iftrialtypesetting
     \expandafter\gobbleoneargument
   \else
     \expandafter\strc_tags_start
   \fi}

\def\strc_tags_enabled_start_detail
  {\iftrialtypesetting
     \expandafter\gobbletwoarguments
   \else
     \expandafter\strc_tags_start_detail
   \fi}

\def\strc_tags_enabled_start_chained
  {\iftrialtypesetting
     \expandafter\gobblefourarguments
   \else
     \expandafter\strc_tags_start_chained_indeed
   \fi}

\def\strc_tags_enabled_start_ignore
  {\iftrialtypesetting
     \expandafter\gobbleoneargument
   \else
     \expandafter\strc_tags_start_ignore
   \fi}

\def\strc_tags_enabled_stop
  {\iftrialtypesetting
     % do nothing
   \else
     \expandafter\strc_tags_stop
  \fi}

% #2 : parent #3: instance

\def\strc_tags_start_chained_indeed#1#2#3#4{\strc_tags_start_chained{#1}{#2}{\getcurrentparentchain#4{#3}}}

\newconditional\c_strc_tags_enabled
\newconditional\c_strc_tags_global

\permanent\protected\def\taggingpause % see pack-obj
  {\c_strc_tags_global\conditionalfalse}

\lettonothing\dotaggedplaceholder

\permanent\chardef\strc_tags_placeholder_char\zerocount % "FFFC

\protected\def\strc_tags_enable_indeed
  {\enforced\let\dotaggedplaceholder  \strc_tags_placeholder_char
   \enforced\let\dostarttagged        \strc_tags_enabled_start_detail
   \enforced\let\dostarttaggednodetail\strc_tags_enabled_start_no_detail
   \enforced\let\dostarttaggedchained \strc_tags_enabled_start_chained
   \enforced\let\dostoptagged         \strc_tags_enabled_stop
   \enforced\let\dostartignoretagging \strc_tags_enabled_start_ignore
   \enforced\let\dostopignoretagging  \strc_tags_stop
   \enforced\let\dotagdocumentpush    \strc_tags_document_push % defined at the lua end
   \enforced\let\dotagdocumentpop     \strc_tags_document_pop  % defined at the lua end
   \enforced\let\dotagdocumentignore  \strc_tags_document_ignore}

\protected\def\strc_tags_enable
  {% once enable one is toast
   \global\c_strc_tags_enabled\conditionaltrue
   % and gets:
   \strc_tags_enable_indeed}

\protected\def\strc_tags_disable
  {\ifconditional\c_strc_tags_enabled
     % so now all are artifacts
     \enforced\let\dotaggedplaceholder  \strc_tags_placeholder_char
     \enforced\let\dostarttagged        \gobbletwoarguments
     \enforced\let\dostarttaggednodetail\gobbleoneargument
     \enforced\let\dostarttaggedchained \gobblefourarguments
     \enforced\let\dostoptagged         \donothing
   \else
     % initial
     \enforced\lettonothing\dotaggedplaceholder
     \enforced\let\dostarttagged        \gobbletwoarguments
     \enforced\let\dostarttaggednodetail\gobbleoneargument
     \enforced\let\dostarttaggedchained \gobblefourarguments
     \enforced\let\dostoptagged         \donothing
     \enforced\let\dostartignoretagging \gobbleoneargument
     \enforced\let\dostopignoretagging  \donothing
     \enforced\let\dotagdocumentpush    \donothing
     \enforced\let\dotagdocumentpop     \donothing
     \enforced\let\dotagdocumentignore  \donothing
   \fi}

% this
%
% \appendtoks
%     \strc_tags_disable_elements
%     \strc_tags_disable
% \to \everybeforepagebody
%
% has become

\protected\def\strc_tags_document_ignore
  {\c_attr_tagged\plusone}

\prependtoks
    \dotagdocumentignore
\to \everybeforepagebody

% \def\strc_tags_horrible_start
%   {\begingroup
%    \ifconditional\c_strc_tags_enabled
%      \dotagdocumentpush
%    \fi}

% \def\strc_tags_horrible_stop
%   {\ifconditional\c_strc_tags_enabled
%       \dotagdocumentpop
%    \fi
%    \endgroup}

% for luigi (beware: fully expandable):

\protected\def\strc_tags_setup_element_user_properties
  {\iftrialtypesetting
     \expandafter\gobbletwooptionals
   \else
     \expandafter\strc_tags_set_element_user_properties
   \fi}

\protected\def\strc_tags_enable_properties
  {\enforced\let\getelementtag             \strc_tags_get_element_tag
   \enforced\let\setupelementuserproperties\strc_tags_set_element_user_properties}

\protected\def\strc_tags_disable_properties
  {\enforced\let\getelementtag             \donothing
   \enforced\let\setupelementuserproperties\gobbletwooptionals}

\strc_tags_disable

%D The triggers:

\newtoks\everyenableelements
\newtoks\everydisableelements

\appendtoks
    \strc_tags_enable_elements
    \strc_tags_enable_properties
    \ifcstok{\taggingparameter\c!method}\v!auto
      \strc_tags_enable
    \else
      \strc_tags_disable
    \fi
\to \everyenableelements

\appendtoks
    \strc_tags_disable_elements
    \strc_tags_disable_properties
    \strc_tags_disable
\to \everydisableelements

%D Tagging is kind of tricky because quite a bit happens when we ship out a page and
%D therefore we can't just enable and disable at will. In some manuals we only need
%D part of the tagging mechanism so there we can turn it on and off.

\appendtoks
   \ifexporting
     % already set up
   \orelse\ifcstok{\taggingparameter\c!state}\v!start
     \c_strc_tags_global\conditionaltrue
     \setsystemmode\s!tagging
     \expand\everyenableelements
   \orelse\iflastnamedcs\v!on
     \setsystemmode\s!tagging
     \ifconditional\c_strc_tags_global \else
       \expand\everyenableelements
     \fi
   \orelse\iflastnamedcs\v!off
     \resetsystemmode\s!tagging
     \ifconditional\c_strc_tags_global \else
       \expand\everydisableelements
     \fi
   \else
     \c_strc_tags_global\conditionalfalse
     \resetsystemmode\s!tagging
     \expand\everydisableelements
   \fi
\to \everysetuptagging

\permanent\protected\def\forgettagging
  {\c_attr_tagged\attributeunsetvalue}

\setuptagging
  [\c!state=\v!stop,
   \c!method=\v!auto]

% We now have a proper key instead of a directive:

\appendtoks
    \ifempty{\taggingparameter\c!preset}\else
        \clf_settaggingpresets
          preset {\lastnamedcs}%
          level  {\taggingparameter\c!level}%
        \relax
    \fi
    \ifempty{\taggingparameter\c!comment}\else
        \clf_settaggingcomment{\lastnamedcs}%
    \fi
    \ifempty{\taggingparameter\c!option}\else
        \clf_settaggingoption{\lastnamedcs}%
    \fi
\to \everysetuptagging

% Cf suggestion by Wolfgang we now have named paragraphs. Watch out, the content
% is grouped but only when we have an instance.
%
% \defineparagraph[red] [color=red]
% \defineparagraph[bold][style=bold]
%
% \startparagraph       \input ward \stopparagraph
% \startparagraph[red]  \input ward \stopparagraph
% \startparagraph[bold] \input ward \stopparagraph

\installcorenamespace               {paragraph}
\installcommandhandler \??paragraph {paragraph} \??paragraph

\setupparagraph % someday maybe also strut (beg/end) and align
  [\c!color=,
   \c!style=]

\ifdefined\dotagparagraph \else \aliased\let\dotagparagraph\gobbleoneargument \fi

\permanent\tolerant\protected\def\startparagraph[#S#1]#*[#S#2]%
  {\endgraf % we end before the group
   \begingroup
   \ifarguments
     \lettonothing\currentparagraph
   \or
     \ifhastok={#1}%
       \lettonothing\currentparagraph
       \setupcurrentparagraph[#1]
     \else
       \cdef\currentparagraph{#1}%
     \fi
   \or
     \cdef\currentparagraph{#1}%
     \setupcurrentparagraph[#2]%
   \fi
   \useparagraphstyleandcolor\c!style\c!color
   \usealignparameter\paragraphparameter
   \usesetupsparameter\paragraphparameter
   \dostarttagged\t!paragraph\currentparagraph
   \dotagparagraph{\paragraphparameter\c!align}}

\permanent\protected\def\stopparagraph
  {\dostoptagged
   \endgraf % we end inside the group
   \endgroup}

\aliased\let\startpar\startparagraph
\aliased\let\stoppar \stopparagraph

\def\strc_tags_document_start_indeed
  {\glet\strc_tags_document_start_indeed\relax
   \dostarttaggednodetail\t!document
   \dostarttaggednodetail\t!documentpart
   } % ua2 demands at least one level more

\def\strc_tags_document_stop_indeed
  {\glet\strc_tags_document_stop_indeed\relax
   \ifconditional\c_strc_tags_enabled
     \clf_checknesting
   \fi
   \dostoptagged
   \dostoptagged}

\appendtoks
    \strc_tags_document_start_indeed % here because otherwise products don't get a root (starttext before env)
\to \everyenableelements

% \appendtoks
%     \strc_tags_document_start_indeed
% \to \everystarttext

\appendtoks
    \strc_tags_document_stop_indeed
\to \everystoptext

% \doifelseinelement{structure:section}            {yes} {no}
% \doifelseinelement{structure:chapter}            {yes} {no}
% \doifelseinelement{division:*-structure:chapter} {yes} {no}

\aliased\let\doifinelementelse\doifelseinelement % define at the lua end

\permanent\protected\def\taggedlabeltexts#1#2#3% experimental: label, numberdetail, numbercontent
  {\begingroup
   \dostarttagged\t!label{#1}%
   \labeltexts{#1}%
     {\dostoptagged
      \dostarttagged\t!number{#2}%
      #3%
      \dostoptagged
      \dostarttagged\t!label{#1}}%
   \dostoptagged
   \endgroup}

\permanent\protected\def\namedtaggedlabeltexts#1#2#3#4#5% experimental: labeltag label numbertag numberdetail numbercontent
  {\begingroup
   \dostarttagged{#1}{#2}%
   \labeltexts{#2}%
     {\dostoptagged
      \dostarttagged{#3}{#4}%
      #5%
      \dostoptagged
      \dostarttagged{#1}{#2}}%
   \dostoptagged
   \endgroup}

%D Metadata is added after the following structure element so here we get some as
%D child of the document root and some as child of the chapter element.
%D
%D \settaggedmetadata[title=Hello World!,author=Hans Hagen]
%D
%D \starttyping
%D \starttext
%D   \startelement[ignore]
%D     \input tufte
%D   \stopelement
%D   \par \input ward \par
%D   \settaggedmetadata[whatever=Again and Again]
%D   \startchapter[title=test]
%D     \input ward
%D   \stopchapter
%D \stoptext
%D \stoptyping

% \settaggedmetadata[#1] % define at the lua end

%D An overload:

\pushoverloadmode

\aliased\let\strc_tagged_saved_bpar\bpar
\aliased\let\strc_tagged_saved_epar\epar

\enforced\permanent\protected\def\bpar{\dostarttaggednodetail\t!paragraph\strc_tagged_saved_bpar}
\enforced\permanent\protected\def\epar{\strc_tagged_saved_epar\dostoptagged}

\popoverloadmode

% \permanent\def\untagged{attr \taggedattribute\attributeunsetvalue}

%D Horrible (maybe enable more here):

\def\strc_tags_horrible_start
  {\ifconditional\c_strc_tags_enabled
     \strc_tags_enable_indeed
     \dostarttaggednodetail\t!document
     \dostarttaggednodetail\t!documentpart
   \fi}

\def\strc_tags_horrible_stop
  {\ifconditional\c_strc_tags_enabled
     \dostoptagged
     \dostoptagged
   \fi}

%D A byproduct of some tests:
%D
%D \starttyping
%D \startquotation
%D     \startsubparagraph test 1\stopsubparagraph
%D     \startsubparagraph test 2\stopsubparagraph
%D     \startsubparagraph test 3\stopsubparagraph
%D \stopquotation
%D \stoptyping

\newboundary\subparagraphboundary

\permanent\protected\def\startsubparagraph
  {\removeunwantedspaces
   \ifnum\lastboundary=\subparagraphboundary
     \unboundary
     \par
   \fi
   \dostarttagged\t!subparagraph\empty
   \ignorespaces}

\permanent\protected\def\stopsubparagraph
  {\removeunwantedspaces
   \dostoptagged
   \boundary\subparagraphboundary
   \ignorespaces}

\permanent\protected\def\subparagraph{\stopsubparagraph\startsubparagraph}

%D New:

\newinteger\tagparcounter

\installglobalmacrostack\tagparcounter

% we don't want a zero one as it is also a trigger

\permanent\protected\lettonothing\dotagsetparcounter
\permanent\protected\lettonothing\doresetparcounter

% Fuzzy:

% \appendtoks
%     \doresetparcounter
% \to \everyflushatnextpar

% \prependtoks
%     \dotagsetparcounter
% \to \everypar

% \prependtoks
%     \dotagsetparcounter
% \to \neverypar

% \appendtoks
%     \dotagsetparcounter
% \to \everytabulatepar % tricky, maybe this should be neverypar

% \permanent\protected\def\strc_tags_parcounter_set
%   {\advanceby\tagparcounter\plusone
%    \c_attr_taggedpar\tagparcounter}

% \permanent\protected\def\strc_tags_parcounter_reset
%   {\c_attr_taggedpar\attributeunsetvalue}

% \appendtoks
%     \strc_tags_parcounter_check
%     \enforced\let\dotagsetparcounter\strc_tags_parcounter_set
%     \enforced\let\doresetparcounter \strc_tags_parcounter_reset
% \to \everyenableelements

% \permanent\protected\def\strc_tags_parcounter_push
%   {\push_macro_tagparcounter
%    \global\advanceby\tagparcounter\plusone
%   %\parattribute\c_attr_taggedpar\tagparcounter
%    \global\c_attr_taggedpar\tagparcounter}
%
% \permanent\protected\def\strc_tags_parcounter_pop
%   {\pop_macro_tagparcounter
%    \global\c_attr_taggedpar\tagparcounter}

% safeguard

% \permanent\protected\def\strc_tags_parcounter_check
%   {\ifcase\tagparcounter
%      \global\tagparcounter\plusone
%      \c_attr_taggedpar\plusone
%    \fi}

% We need to fool the scanner as well as be transparent for grouping
% kind of a mess ... check with combinations:

% \noaligned\permanent\protected\def\strc_tags_parcounter_check
%   {\beginlocalcontrol
%    \clf_strc_tags_parcounter_check
%    \endlocalcontrol}

\noaligned\permanent\protected\def\strc_tags_parcounter_push
  {\beginlocalcontrol
   \clf_strc_tags_parcounter_push
   \endlocalcontrol}

\noaligned\permanent\protected\def\strc_tags_parcounter_pop
  {\beginlocalcontrol
   \clf_strc_tags_parcounter_pop
   \endlocalcontrol}

\permanent\protected\def\strc_tags_parcounter_reset
  {\c_attr_taggedpar\attributeunsetvalue}

\immutable\everyparbegin\emptytoks
\immutable\everyparend  \emptytoks

% \appendtoks
%     \enforced\everyparbegin\emptytoks
%     \enforced\everyparend  \emptytoks
% \to \everyforgetall

\appendtoks
    \enforced\everyparbegin{\strc_tags_parcounter_push}%
    \enforced\everyparend  {\strc_tags_parcounter_pop }%
\to \everyenableelements

\protect
