%D \module
%D   [       file=core-syn,
%D        version=1997.03.31,
%D          title=\CONTEXT\ Core Macros,
%D       subtitle=Synonyms and Sorts,
%D         author=Hans Hagen,
%D           date=\currentdate,
%D      copyright={PRAGMA / Hans Hagen \& Ton Otten}]
%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 / Synonyms and Sorts}

\unprotect

% \checkdefined kan hierheen

%  Formaat tex-utility-input-file <jobname.tui>:
%
%    synonym entry {tag} {pure} {text} {synonym}
%
%  Deze file wordt met het programma TeXUtil omgezet in een
%  in te lezen TeXFile met de commando's:
%
%    \synonymentry {tag} {pure} {text} {synonym}

\newif\ifsynonymmeaning

% todo: \def\synonymparameter#1{\csname\??sm\currentsynonym#1\endcsname}

\def\dosetupsynonyms[#1][#2]%
  {\getparameters[\??sm#1][#2]}

\def\setupsynonyms
  {\dodoubleargument\dosetupsynonyms}

\def\doresetsynonym#1%
  {\letvalue{#1\s!entry}\gobblethreearguments}

\def\dohandlesynonymentry#1#2#3#4%
  {\bgroup
   \global\utilitydonetrue
   \syndef
     {\doattributes{\??sm#1}\c!textstyle\c!textcolor{#3}}
     \ConvertToConstant\doifelse{#4}{}{\unknown}{#4}\par
   \egroup}

\def\synonymentry#1%
  {\executeifdefined{#1\s!entry}\gobblethreearguments}

\def\dosetsynonym#1%
  {\doifdefinedelse{\??sm#1\c!command}
     {\setvalue{#1\s!entry}{\getvalue{\??sm#1\c!command}}} % 3 argumenten
     {\setvalue{#1\s!entry}{\dohandlesynonymentry{#1}}}}

\def\synonymparameter#1{\csname\??sm\currentsynonym#1\endcsname}

\def\doplacelistofsynonyms#1#2%
  {\whitespace
   \begingroup
   \def\currentsynonym{#1}%
   \definedescription  % nog eens een class van maken, net als framed
     [syndef]
%      [\c!location=\getvalue{\??sm#1\c!location}, % todo \synonymparameter
%       \c!width=\getvalue{\??sm#1\c!width},
%       \c!distance=\getvalue{\??sm#1\c!distance},
%       \c!sample=\getvalue{\??sm#1\c!sample},
%       \c!hang=\getvalue{\??sm#1\c!hang},
%       \c!align=\getvalue{\??sm#1\c!align},
%       \c!before=\getvalue{\??sm#1\c!before},
%       \c!inbetween=\getvalue{\??sm#1\c!inbetween},
%       \c!after=\getvalue{\??sm#1\c!after},
%       \c!indentnext=\getvalue{\??sm#1\c!indentnext},
     [\c!location=\synonymparameter\c!location,
      \c!width=\synonymparameter\c!width,
      \c!distance=\synonymparameter\c!distance,
      \c!sample=\synonymparameter\c!sample,
      \c!hang=\synonymparameter\c!hang,
      \c!align=\synonymparameter\c!align,
      \c!before=\synonymparameter\c!before,
      \c!inbetween=\synonymparameter\c!inbetween,
      \c!after=\synonymparameter\c!after,
      \c!indentnext=\synonymparameter\c!indentnext,
      \c!headstyle=,
      \c!style=]%
   \setupwhitespace[\v!none]%
   \doutilities{#1}\jobname{#2}\relax\par
   \endgroup
   \ifutilitydone\else\nowhitespace\fi}

\def\docompletelistofsynonyms#1#2% expansion needed to avoid v! (due to french active !)
  {\expanded{\systemsuppliedchapter[#1]{\noexpand\headtext{#2}}}%
   \doplacelistofsynonyms{#1}{#2}%
   \page[\v!yes]}

\def\processsynonym#1#2#3%
  {\begingroup  % anders in mathmode lege \hbox, zie eenheden
   \ifsynonymmeaning
     \synonymmeaningfalse
     \doattributes{\??sm#1}\c!synonymstyle\c!synonymcolor{#3}%
   \else
     \explicithmode
     \doattributes{\??sm#1}\c!textstyle\c!textcolor{#2}%
   \fi
   \endgroup}

\def\getsynonymmeaning#1#2#3%
  {\bgroup
   \doifundefined{#2#3}
     {\setgvalue{#2#3}{{\tt[#3]}}%
      \showmessage\m!systems{18}{#1,#3}}%
   \synonymmeaningtrue
   \getvalue{#2#3}%
   \egroup}

\def\dowritesynonym#1#2#3#4%
  {\begingroup  % anders in mathmode lege \hbox
   \convertexpanded{\getvalue{\??sm#1\c!expansion}}{#3}\asciisynonym
   \convertexpanded{\getvalue{\??sm#1\c!expansion}}{#4}\asciimeaning
   \immediatewriteutility{s e {#1} {#2} {\asciisynonym} {\asciimeaning}}%
   \endgroup}

% \def\preexecutesynonym#1#2#3#4%
%   {\ifdoinpututilities \else
%      \dowritesynonym{#1}{#2}{#3}{#4}%
%      \unexpanded\setgvalue{#2}{\processsynonym{#1}{#3}{#4}}%
%    \fi}
%
% \def\executesynonym#1#2#3#4%
%   {\preexecutesynonym{#1}{#2}{#3}{#4}%
%    \processsynonym{#1}{#3}{#4}}

\def\reprocesssynonym#1#2#3%
  {\processsynonym{#1}{#2}{#3}%
   \getvalue{\??sm#1\c!next}} % not formally documented

\def\preexecutesynonym#1#2#3#4%
  {\ifdoinpututilities \else
     \dowritesynonym{#1}{#2}{#3}{#4}%
     \unexpanded\setgvalue{#2}{\reprocesssynonym{#1}{#3}{#4}}%
   \fi}

\def\executesynonym#1#2#3#4%
  {\preexecutesynonym{#1}{#2}{#3}{#4}%
   \processsynonym{#1}{#3}{#4}%
   \getvalue{\??sm#1\c!next}} % not formally documented

\def\expandsynonym#1#2#3#4%
  {{\synonymmeaningtrue
    \processsynonym{#1}{#3}{#4}}}

\def\dodoloadsynonym#1#2#3#4%
  {\setgvalue{#2}{\executesynonym{#1}{#2}{#3}{#4}}}

\def\doloadsynonym#1%
  {\setvalue{#1\s!entry}##1##2##3%
     {\doifelsenothing{##1}
        {\dodoloadsynonym{#1}{##2}{##2}{##3}}
        {\dodoloadsynonym{#1}{##1}{##2}{##3}}%
      \global\utilitydonetrue}}

\def\doloadsynonyms#1#2%
  {\bgroup
   \let\dosetsynonym\doloadsynonym
   \showmessage\m!systems{19}{#2}%
   \doutilities{#1}\jobname\empty\relax\relax
   \egroup
   \setvalue{\s!check#1}##1{}}

\def\dodocomplexsynonym[#1][#2]#3#4%
  {\doifsomething{#2}
     {\getvalue{\s!check#1}{#2}%
      \doglobal\appendtoks\setvalue{#2}{#2}\to\simplifiedcommands
      \doifelsevalue{\??sm#1\c!conversion}\v!yes
        {\unexpanded\setgvalue{#2}{\expandsynonym{#1}{#2}{#3}{#4}}}
        {\doifelsevalue{\??sm#1\c!state}\v!start
           {\doifelsevalue{\??sm#1\c!criterium}\v!all
              {\preexecutesynonym{#1}{#2}{#3}{#4}}
              {\unexpanded\setgvalue{#2}{\executesynonym{#1}{#2}{#3}{#4}}}}
           {\unexpanded\setgvalue{#2}{\processsynonym{#1}{#3}{#4}}}}}}

\def\docomplexsynonym[#1][#2][#3]#4#5%
  {\ifthirdargument
     \dodocomplexsynonym[#2][#1#3]{#4}{#5}%
   \else
     \dodocomplexsynonym[#2][#1#4]{#4}{#5}%
   \fi}

\def\doregistersynonymlanguage#1%
  {\savesortlanguage{\getvalue{\??sm#1\s!language}}%
   \immediatewriteutility{s l {#1} {\getvalue{\??sm#1\s!language}}}}

\def\dodefinesynonyms[#1][#2][#3][#4]%
  {\iffourthargument
     \unexpanded\def#4##1{\getsynonymmeaning{#1}{\??sm:#1:}{##1}}%
     \ifthirdargument
       \unexpanded\def#3##1{\getvalue{\??sm:#1:##1}}%
     \fi
     \setvalue{#1}{\dotripleempty\docomplexsynonym[\??sm:#1:][#1]}%
   \else
     \ifthirdargument
       \unexpanded\def#3##1{\getsynonymmeaning{#1}{}{##1}}%
     \fi
     \setvalue{#1}{\dotripleempty\docomplexsynonym[][#1]}%
   \fi
   \dosetupsynonyms
     [#1]%
     [\c!synonymstyle=,\c!textstyle=,
      \c!state=\v!start,\c!criterium=,
      \c!location=\v!left,\c!width=5em,\c!distance=0pt,
      \c!sample=,\c!hang=,\c!align=,
      \c!before=,\c!inbetween=,\c!after=,
      \c!indentnext=\v!no,
      \c!expansion=,
      \s!language=\currentmainlanguage]%
   \doglobal\appendtoksonce
     \doregistersynonymlanguage{#1}%
   \to \everysavesortkeys
   \presetheadtext[#2=\Word{#2}]% changes the \if...argument
   \addutilityreset{#1}%
   \setvalue{\e!setup #2\e!endsetup}{\dodoubleargument\getparameters[\??sm#1]}% to be obsolete
   \setvalue{\s!set              #1}{\dosetsynonym{#1}}%
   \setvalue{\s!reset            #1}{\doresetsynonym{#1}}%
   \setvalue{\s!check         #1}##1{\checkdefined{synonym}{#1}{##1}}%
   \setvalue{\e!load             #2}{\doloadsynonyms{#1}{#2}}%
   \setvalue{\e!place\e!listof   #2}{\doplacelistofsynonyms{#1}{#2}}%
   \setvalue{\e!complete\e!listof#2}{\docompletelistofsynonyms{#1}{#2}}}

\def\definesynonyms
  {\doquadrupleempty\dodefinesynonyms}

%  Formaat tex-utility-input-file <jobname.tui>:
%
%    synonym entry {tag} {pure} {text} {}
%
%  Deze file wordt met het programma TeXUtil omgezet in een
%  in te lezen TeXFile met de commando's:
%
%    \synonymentry {tag} {pure} {text} {}

\def\dosetupsorting[#1][#2]%
  {\getparameters[\??so#1][#2]}

\def\setupsorting
  {\dodoubleargument\dosetupsorting}

\def\doresetsort#1%
  {\letvalue{#1\s!entry}\gobblethreearguments}

\def\dosetsort#1%
  {\setvalue{#1\s!entry}##1##2##3%
     {\def\dowritesort####1####2####3{}%
      \global\utilitydonetrue
      \bgroup
      \doifdefinedelse{\??so#1\c!command}
        {\getvalue{\??so#1\c!command}{##2}}  % 1 argument
        {\getvalue{\??so#1\c!before}%
         \doattributes{\??so#1}\c!style\c!color{##2}%
         \getvalue{\??so#1\c!after}}%
      \egroup}}

\def\doplacelistofsorts#1% NOG EEN RUWE VERSIE MAKEN
  {\whitespace           % ZONDER WITRUIMTE ETC ETC
   \begingroup
   \setupwhitespace[\v!none]%
   \doutilities{#1}\jobname{#1}\relax\par
   \endgroup
   \ifutilitydone\else\nowhitespace\fi}

% to be tested
%
% \def\doplacelistofsorts#1% NOG EEN RUWE VERSIE MAKEN
%   {\startpacked
%    \doutilities{#1}\jobname{#1}\relax\par
%    \stoppacked}

\def\docompletelistofsorts#1#2%
  {\expanded{\systemsuppliedchapter[#1]{\noexpand\headtext{#2}}}%
   \doplacelistofsorts{#1}%
   \page[\v!yes]}

% todo:
%
% \def\placelistofsorts[#1]%
%   {\doplacelistofsorts{#1}}

\def\processsort#1#2#3%
  {\explicithmode
   \begingroup % was \bgroup
   \doattributes{\??so#1}\c!style\c!color{#2}%
   \endgroup}  % was \egroup

\def\dowritesort#1#2#3%
  {\bgroup
   \convertexpanded{\getvalue{\??so#1\c!expansion}}{#3}\asciisynonym
   \immediatewriteutility{s e {#1} {#2} {\asciisynonym} {}}%
   \egroup}

\def\synonymentry#1%
  {\executeifdefined{#1\s!entry}\gobblethreearguments}

% \def\preexecutesort#1#2#3%
%   {\ifdoinpututilities \else
%      \dowritesort{#1}{#2}{#3}%
%      \unexpanded\setgvalue{#2}{\processsort{#1}{#3}{#2}}%
%    \fi}
%
% \def\executesort#1#2#3%
%   {\begingroup
%    \let\executesort\thirdofthreearguments % Trick needed for nested logo's.
%    \preexecutesort{#1}{#2}{#3}%
%    \processsort{#1}{#3}{#2}%
%    \endgroup}

\def\reprocesssort#1#2#3%
  {\processsort{#1}{#2}{#3}%
   \getvalue{\??so#1\c!next}}

\def\preexecutesort#1#2#3%
  {\ifdoinpututilities \else
     \dowritesort{#1}{#2}{#3}%
     \unexpanded\setgvalue{#2}{\reprocesssort{#1}{#3}{#2}}%
   \fi}

\def\executesort#1#2#3%
  {\begingroup
   \let\executesort\thirdofthreearguments % Trick needed for nested logo's.
   \preexecutesort{#1}{#2}{#3}%
   \processsort{#1}{#3}{#2}%
   \endgroup
   \getvalue{\??so#1\c!next}} % not formally documented

\def\doloadsort#1%
  {\setvalue{#1\s!entry}##1##2##3%
     {\setgvalue{##1}{##2}%
      \global\utilitydonetrue}}

\def\doloadsort#1#2%
  {\bgroup
   \let\dosetsort\doloadsort
   \showmessage\m!systems{20}{#2}%
   \doutilities{#1}\jobname\empty\relax\relax
   \egroup
   \setvalue{\s!check#1}##1{}}

\def\dodocomplexsort[#1][#2]#3%
  {\doifsomething{#2}
     {\getvalue{\s!check#1}{#2}%
      \doglobal\appendtoks\setvalue{#2}{#2}\to\simplifiedcommands
      \doifelsevalue{\??so#1\c!state}\v!start
        {\doifelsevalue{\??so#1\c!criterium}\v!all
           {\preexecutesort{#1}{#2}{#3}}
           {\unexpanded\setgvalue{#2}{\executesort{#1}{#2}{#3}}}}
        {\unexpanded\setgvalue{#2}{\processsort{#1}{#3}{#2}}}}}

\def\docomplexsort[#1][#2][#3]#4%
  {\ifthirdargument
     \dodocomplexsort[#2][#1#3]{#4}%
   \else
     \dowritesort{#2}{#4}{#4}%
   \fi}

% if #3=\relax or \v!none, then no command but still protected

\def\doregistersortinglanguage#1%
  {\savesortlanguage{\getvalue{\??so#1\s!language}}%
   \immediatewriteutility{s l {#1} {\getvalue{\??so#1\s!language}}}}

\def\dodefinesorting[#1][#2][#3]%
  {\getparameters[\??so#1]
     [%\c!command=, % we test for defined !
      \c!state=\v!start,
      \c!criterium=,
      \c!style=,
      \c!before=,
      \c!after=\endgraf,
      \c!expansion=,
      \s!language=\currentmainlanguage]%
   \doglobal\appendtoksonce
     \doregistersortinglanguage{#1}%
   \to \everysavesortkeys
   \ifthirdargument
     \ConvertConstantAfter\doifnot{#3}\v!none
       {\ifx#3\relax \else
          \def#3##1{\getvalue{\??so:#1:##1}}
        \fi}%
     \setvalue{#1}{\dotripleempty\docomplexsort[\??so:#1:][#1]}%
   \else
     \setvalue{#1}{\dotripleempty\docomplexsort[][#1]}%
   \fi
   \addutilityreset{#1}%
   \presetheadtext[#2=\Word{#2}]% after \ifthirdargument -)
   \setvalue{\e!setup#2\e!endsetup}[##1]{\getparameters[\??so#1][##1]}% to be obsolete
   \setvalue{\s!set#1}{\dosetsort{#1}}%
   \setvalue{\s!reset#1}{\doresetsort{#1}}%
   \setvalue{\e!load#2}{\doloadsort{#1}{#2}}%
   \setvalue{\s!check#1}##1{\checkdefined{sort}{#1}{##1}}%
   \setvalue{\e!place\e!listof#2}{\doplacelistofsorts{#1}}%
   \setvalue{\e!complete\e!listof#2}{\docompletelistofsorts{#1}{#2}}}

\def\definesorting
  {\dotripleempty\dodefinesorting}

%D Here we define a support macro that can sort simple comma
%D separated lists. It's a multi-list variant of a prototype
%D written by Taco.

\def\processlistofsorts[#1]%
  {\doutilities{#1}\jobname{#1}\donothing\donothing}

\newcounter\nofsortedalphalists

\def\sortalphacommacommand#1%
  {\begingroup
   \doglobal\increment\nofsortedalphalists
   \edef\currentsortedalphalist{alpha:\nofsortedalphalists}%
   \definesorting[\currentsortedalphalist][\currentsortedalphalist]%
   \processcommacommand[#1]{\getvalue\currentsortedalphalist}%
   \global\let\sortedcommalist\empty
   \def\makesortedlist##1{\doglobal\appendtocommalist{##1}\sortedcommalist}%
   \setupsorting[\currentsortedalphalist][\c!criterium=\v!all,\c!command=\makesortedlist]%
   \processlistofsorts[\currentsortedalphalist]%
   \endgroup
   \dodoglobal\let#1\sortedcommalist}

% \starttext
%     \def\whatever{a,b,q,d,r,f}       \sortalphacommacommand\whatever \whatever \endgraf
%     \def\whatever{ax,bx,qx,dx,rx,fx} \sortalphacommacommand\whatever \whatever \endgraf
% \stoptext

\definesynonyms
  [\v!abbreviation]
  [\v!abbreviations]
  [\infull]

\setupsynonyms
  [\v!abbreviation]
  [\c!textstyle=\v!capital,
   \c!synonymstyle=,
   \c!textcolor=,
   \c!synonymcolor=,
   \c!location=\v!left,
   \c!width=5em,
   \c!state=\v!start]

\definesorting
  [\v!logo]
  [\v!logos]
% no [\logogram]

\definesynonyms
  [\v!unit]
  [\v!units]
  [\unitmeaning]

\setupsynonyms
  [\v!unit]
  [\c!textstyle=\dimension]

\protect \endinput
