%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}{}

\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}               % Div

\definetagconstant{division}               % Div
\definetagconstant{paragraph}              % P
\definetagconstant{p}                      % P
\definetagconstant{construct}              % Span
\definetagconstant{highlight}              % Span

\definetagconstant{section}                % Sect
\definetagconstant{sectioncaption}         % Div
\definetagconstant{sectiontitle}           % H
\definetagconstant{sectionnumber}          % H
\definetagconstant{sectioncontent}         % Div

\definetagconstant{itemgroup}              % L
\definetagconstant{item}                   % Li
\definetagconstant{itemtag}                % Lbl
\definetagconstant{itemcontent}            % LBody
\definetagconstant{itemhead}               % Div
\definetagconstant{itembody}               % Div

\definetagconstant{description}            % Li
\definetagconstant{descriptiontag}         % Lbl
\definetagconstant{descriptioncontent}     % LBody
\definetagconstant{descriptionsymbol}      % Span

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

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

\definetagconstant{lines}                  % Code
\definetagconstant{line}                   % Code
\definetagconstant{linenumber}             % Span

\definetagconstant{sorting}                % Span
\definetagconstant{synonym}                % Span

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

\definetagconstant{table}                  % Table
\definetagconstant{tablerow}               % TR
\definetagconstant{tablecell}              % TD
\definetagconstant{tableheadcell}          % TH
\definetagconstant{tablehead}              % THEAD
\definetagconstant{tablebody}              % TBODY
\definetagconstant{tablefoot}              % TFOOT

\definetagconstant{tabulate}               % Table
\definetagconstant{tabulaterow}            % TR
\definetagconstant{tabulatecell}           % TD
\definetagconstant{tabulateheadcell}       % TH
\definetagconstant{tabulatehead}           % THEAD
\definetagconstant{tabulatebody}           % TBODY
\definetagconstant{tabulatefoot}           % TFOOT

\definetagconstant{math}                   % math
\definetagconstant{mtable}                 % Table
\definetagconstant{mtr}                    % TR
\definetagconstant{mtd}                    % TD
\definetagconstant{maction}                %
\definetagconstant{mstacker}
\definetagconstant{mstackertop}
\definetagconstant{mstackermid}
\definetagconstant{mstackerbot}

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

\definetagconstant{munderover}             % special cases
\definetagconstant{munder}                 % special cases
\definetagconstant{mover}                  % special cases

\definetagconstant{list}                   % TOC
\definetagconstant{listitem}               % TOCI
\definetagconstant{listtag}                % Lbl
\definetagconstant{listcontent}            % P
\definetagconstant{listdata}               % P
\definetagconstant{listpage}               % Reference
\definetagconstant{listtext}               % Span

\definetagconstant{delimited}              % BlockQuote
%definetagconstant{delimited}              % Quote
\definetagconstant{delimitedsymbol}        % Span
\definetagconstant{delimitedcontent}       % Span

\aliastagconstant{delimitedblock}{delimited}

\definetagconstant{subsentence}            % Span
\definetagconstant{subsentencecontent}     % Span
\definetagconstant{subsentencesymbol}      % Span

\definetagconstant{float}                  % Div
\definetagconstant{floatcaption}           % Caption
\definetagconstant{floatlabel}             % Span
\definetagconstant{floattext}              % Span
\definetagconstant{floatnumber}            % Span
\definetagconstant{floatcontent}           % P

\definetagconstant{image}                  % P

\definetagconstant{mpgraphic}              % P

\definetagconstant{formulaset}             % Div
\definetagconstant{formula}                % Div
\definetagconstant{formulacaption}         % Span
\definetagconstant{formulalabel}           % Span
\definetagconstant{formulanumber}          % P
\definetagconstant{formulacontent}         % P
\definetagconstant{subformula}             % Div

\definetagconstant{link}                   % Link
\definetagconstant{reference}              % Span

\definetagconstant{margintext}             % Span
\definetagconstant{margintextblock}        % Div
\definetagconstant{marginanchor}           % Span

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

\definetagconstant{label}                  % Span
\definetagconstant{number}                 % Span

\definetagconstant{ignore}                 % Span
\definetagconstant{private}                % Span

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

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

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

\definetagconstant{publications}           % Span
\definetagconstant{publication}            % Span
\definetagconstant{pubfld}                 % Span

\definetagconstant{block}                  % Div
\definetagconstant{userdata}               % Div

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

% the real code

\definesystemattribute[tagged][public]
\definesystemattribute[image] [public]

\unexpanded\def\setelementbackendtag{\dodoubleargument\strc_tags_set_backend}
\unexpanded\def\setelementnature    {\dodoubleargument\strc_tags_set_nature}

\def\strc_tags_set_backend[#1][#2]{\clf_settagproperty_b{#1}{#2}} % todo: ignore when no export
\def\strc_tags_set_nature [#1][#2]{\clf_settagproperty_n{#1}{#2}} % todo: ignore when no export

\unexpanded\def\strc_tags_set_aspect_nop#1#2{}
\unexpanded\def\strc_tags_set_aspect_yes#1#2{\clf_settagaspect{#1}{#2}} % todo: ignore when no export / also \let

\unexpanded\def\ignoretagsinexport[#1]%
  {\clf_ignoretagsinexport{#1}}

\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

\unexpanded\def\strc_tags_element_start_yes{\dodoubleempty\strc_tags_element_start_yes_indeed}
\unexpanded\def\strc_tags_element_start_nop{\dodoubleempty\strc_tags_element_start_nop_indeed}

\unexpanded\def\strc_tags_element_start_yes_indeed
  {\iftrialtypesetting
     \expandafter\strc_tags_element_start_yes_indeed_nop
   \else
     \expandafter\strc_tags_element_start_yes_indeed_yes
   \fi}

\unexpanded\def\strc_tags_element_start_yes_indeed_nop[#1][#2]%
  {}

\unexpanded\def\strc_tags_element_start_yes_indeed_yes[#1][#2]%
  {\clf_starttag_u{#1}{#2}}

\unexpanded\def\strc_tags_element_stop_yes
  {\iftrialtypesetting
     \expandafter\strc_tags_element_stop_yes_indeed_nop
   \else
     \expandafter\strc_tags_element_stop_yes_indeed_yes
   \fi}

\unexpanded\def\strc_tags_element_stop_nop
  {}

\unexpanded\def\strc_tags_element_stop_yes_indeed_nop
  {}

\unexpanded\def\strc_tags_element_stop_yes_indeed_yes
  {\clf_stoptag}

\let\strc_tags_element_start_nop_indeed\strc_tags_element_start_yes_indeed_nop
\let\strc_tags_element_stop_nop_indeed \strc_tags_element_stop_yes_indeed_nop

\def\strc_tags_report_hyphen#1%
  {\writestatus\m!languages{setting #1 to U+00AD}}

\unexpanded\def\strc_tags_patch_hyphen
  {% for the moment here
   \ifnum\languageparameter\s!lefthyphenchar>\zerocount
     \setuplanguage[\s!default][\s!lefthyphenchar="AD]%
     \strc_tags_report_hyphen\s!lefthyphenchar
   \fi
   \ifnum\languageparameter\s!righthyphenchar>\zerocount
     \setuplanguage[\s!default][\s!righthyphenchar="AD]%
     \strc_tags_report_hyphen\s!righthyphenchar
   \fi
   \let\strc_tags_report_hyphen\gobbleoneargument}

\unexpanded\def\strc_tags_enable_elements
  {\strc_tags_patch_hyphen
   \let\startelement\strc_tags_element_start_yes
   \let\stopelement \strc_tags_element_stop_yes
   \let\dosettagproperty\strc_tags_set_aspect_yes}

\unexpanded\def\strc_tags_disable_elements
  {\let\startelement\strc_tags_element_start_nop
   \let\stopelement \strc_tags_element_stop_nop
   \let\dosettagproperty\strc_tags_set_aspect_nop}

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

\def\strc_tags_enabled_start_no_detail
  {\iftrialtypesetting
     \expandafter\strc_tags_start_nop_no_detail
   \else
     \expandafter\strc_tags_start_yes_no_detail
   \fi}

\def\strc_tags_enabled_start_detail
  {\iftrialtypesetting
     \expandafter\strc_tags_start_nop_detail
   \else
     \expandafter\strc_tags_start_yes_detail
   \fi}

\def\strc_tags_enabled_start_chained
  {\iftrialtypesetting
     \expandafter\strc_tags_start_nop_chained
   \else
     \expandafter\strc_tags_start_yes_chained
   \fi}

\def\strc_tags_enabled_stop
  {\iftrialtypesetting
     \expandafter\strc_tags_stop_nop
   \else
     \expandafter\strc_tags_stop_yes
  \fi}

\def\strc_tags_start_yes_no_detail    #1{\clf_starttag{#1}}
\def\strc_tags_start_yes_detail     #1#2{\clf_starttag_d{#1}{#2}}
\def\strc_tags_start_yes_chained  #1#2#3{\clf_starttag_c{#1}{#2}{\getcurrentparentchain#3{#2}}}
\def\strc_tags_stop_yes                 {\clf_stoptag}

\let\strc_tags_start_nop_no_detail\gobbleoneargument
\let\strc_tags_start_nop_detail   \gobbletwoarguments
\let\strc_tags_start_nop_chained  \gobblethreearguments
\let\strc_tags_stop_nop           \donothing

\def\strc_tags_start_yes_ignore{\clf_starttag{\t!ignore}}
\let\strc_tags_stop_yes_ignore \strc_tags_stop_yes
\let\strc_tags_start_nop_ignore\donothing
\let\strc_tags_stop_nop_ignore \donothing

% more efficient:

% \dostarttagged         % {tag} {detail}
% \dostarttaggedchained  % {tag} {detail} \??hash
% \dostarttaggednodetail % {tag}

\newconditional\c_strc_tags_enabled

\let\dotaggedplaceholder\empty

\chardef\strc_tags_placeholder_char\zerocount % "FFFC

\unexpanded\def\strc_tags_enable_indeed
  {\let\dotaggedplaceholder  \strc_tags_placeholder_char
   \let\dostarttagged        \strc_tags_enabled_start_detail
   \let\dostarttaggednodetail\strc_tags_enabled_start_no_detail
   \let\dostarttaggedchained \strc_tags_enabled_start_chained
   \let\dostoptagged         \strc_tags_enabled_stop
   \let\dostartignoretagging \strc_tags_start_yes_ignore
   \let\dostopignoretagging  \strc_tags_stop_yes_ignore}

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

\unexpanded\def\strc_tags_disable
  {\ifconditional\c_strc_tags_enabled
     % so now all are artifacts
     \let\dotaggedplaceholder  \strc_tags_placeholder_char
     \let\dostarttagged        \strc_tags_start_nop_detail
     \let\dostarttaggednodetail\strc_tags_start_nop_no_detail
     \let\dostarttaggedchained \strc_tags_start_nop_chained
     \let\dostoptagged         \strc_tags_stop_nop_ignore
   \else
     % initial
     \let\dotaggedplaceholder  \empty
     \let\dostarttagged        \strc_tags_start_nop_detail
     \let\dostarttaggednodetail\strc_tags_start_nop_no_detail
     \let\dostarttaggedchained \strc_tags_start_nop_chained
     \let\dostoptagged         \strc_tags_stop_nop_ignore
     \let\dostartignoretagging \strc_tags_start_nop_ignore
     \let\dostopignoretagging  \strc_tags_stop_nop_ignore
   \fi}

% for luigi (beware: fully expandable):

\def\strc_tags_get_element_tag_yes{\clf_getelementtag}
\let\strc_tags_get_element_tag_nop\donothing

\unexpanded\def\strc_tags_setup_element_user_properties_yes
  {\dodoubleempty\strc_tags_setup_element_user_properties_indeed}

\unexpanded\def\strc_tags_setup_element_user_properties_nop
  {\dodoubleempty\strc_tags_setup_element_user_properties_indeed_nop}

\def\strc_tags_setup_element_user_properties_indeed
  {\iftrialtypesetting
     \expandafter\strc_tags_setup_element_user_properties_indeed_nop
   \else
     \expandafter\strc_tags_setup_element_user_properties_indeed_yes
   \fi}

\def\strc_tags_setup_element_user_properties_indeed_nop[#1][#2]{}
\def\strc_tags_setup_element_user_properties_indeed_yes[#1][#2]{\clf_setelementuserproperties{#1}{#2}}

\unexpanded\def\strc_tags_enable_properties
  {\let\getelementtag             \strc_tags_get_element_tag_yes
   \let\setupelementuserproperties\strc_tags_setup_element_user_properties_yes}

\unexpanded\def\strc_tags_disable_properties
  {\let\getelementtag             \strc_tags_get_element_tag_nop
   \let\setupelementuserproperties\strc_tags_setup_element_user_properties_nop}

%D The triggers:

\newtoks\everyenableelements
\newtoks\everydisableelements

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

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

\appendtoks
   \doifelse{\taggingparameter\c!state}\v!start{\the\everyenableelements}{\the\everydisableelements}%
\to \everysetuptagging

\unexpanded\def\forgettagging
  {\c_attr_tagged\attributeunsetvalue}

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

% \unexpanded\def\startparagraph
%   {\dostarttagged\t!paragraph\empty}
%
% \unexpanded\def\stopparagraph
%   {% \removeunwantedspaces % yes or no
%    \dostoptagged
%    \par}

% 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=]

\unexpanded\def\startparagraph
  {\dodoubleempty\paragraph_start}

\def\paragraph_start
  {\endgraf % we end before the group
   \begingroup
   \iffirstargument
     \ifsecondargument
       \doubleexpandafter\paragraph_start_two
     \else
       \doubleexpandafter\paragraph_start_one
     \fi
   \else
     \expandafter\paragraph_start_zero
   \fi}

\def\paragraph_start_two[#1][#2]%
  {\edef\currentparagraph{#1}%
   \setupcurrentparagraph[#2]%
   \paragraph_start_indeed}

\def\paragraph_start_one[#1][#2]%
  {\doifelseassignment{#1}
     {\let\currentparagraph\empty
      \setupcurrentparagraph[#1]}
     {\edef\currentparagraph{#1}}%
   \paragraph_start_indeed}

\def\paragraph_start_zero[#1][#2]%
  {\let\currentparagraph\empty
   \paragraph_start_indeed}

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

\def\paragraph_start_indeed
  {\useparagraphstyleandcolor\c!style\c!color
   \usealignparameter\paragraphparameter
   \usesetupsparameter\paragraphparameter
   \dostarttagged\t!paragraph\currentparagraph
   \dotagparagraph{\paragraphparameter\c!align}}

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

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

\def\strc_tags_document_start_indeed
  {\glet\strc_tags_document_start_indeed\relax
   \dostarttagged\t!document\empty}

\def\strc_tags_document_stop_indeed
  {\glet\strc_tags_document_stop_indeed\relax
   \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

\appendtoks
    \strc_tags_disable_elements
    \strc_tags_disable
\to \everybeforepagebody

%D This will only work well with sane use.

% \appendtoks
%     {%
%         \doglobal\appendtoks
%             \strc_tags_start_yes_ignore
%         \to \everybeforepagebody
%         \doglobal\appendtoks
%             \strc_tags_stop_yes_ignore
%         \to \everyafterpagebody
%     }%
% \to \everyenableelements

% This doesn't work well either, so instead we handle the ornaments in the
% tagging in a different way (see attr -> false code).

% \appendtoks
%     \dostartignoretagging
% \to \everybeforepagebody
%
% \appendtoks
%     \dostopignoretagging
% \to \everyafterpagebody

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

\unexpanded\def\doifelseinelement#1%
  {\clf_doifelseinelement{#1}}

\let\doifinelementelse\doifelseinelement

\unexpanded\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}

\unexpanded\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
%D here we get some as child of the document root and some as child
%D 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

\unexpanded\def\settaggedmetadata[#1]%
  {\clf_settaggedmetadata{#1}}

%D An overload:

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

\unexpanded\def\bpar{\dostarttagged\t!paragraph\empty\strc_tagged_saved_bpar}
\unexpanded\def\epar{\strc_tagged_saved_epar\dostoptagged}

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

\protect
