%D \module
%D   [       file=colo-ini,
%D        version=1997.04.01,
%D          title=\CONTEXT\ Color Macros,
%D       subtitle=Initialization,
%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 Color Macros / initialization}

%D To do: stroke versus fill color
%D 1000 100 10 -> constants

%D Possible optimization: store level in mark instead of name

\unprotect

%D Color support is not present in \TEX. Colorful output can
%D however be accomplished by using specials. This also means
%D that this support depends on the \DVI\ driver used. At the
%D moment this module was written, still no decent standard on
%D color specials has been agreed upon. We therefore decided to
%D implement a mechanism that is as independant as possible of
%D drivers.
%D
%D Color support shares with fonts that is must be implemented
%D in a way that permits processing of individual \DVI\ pages.
%D Furthermore it should honour grouping. The first condition
%D forces us to use a scheme that keeps track of colors at
%D page boundaries. This can be done by means of \TEX's
%D marking mechanism (\type{\mark}).
%D
%D When building pages, \TEX\ periodically looks at the
%D accumulated typeset contents and breaks the page when
%D suitable. At that moment, control is transfered to the
%D output routine. This routine takes care of building the
%D pagebody and for instance adds headers and footers. The page
%D can be broken in the middle of some colored text, but
%D headers and footers are often in black upon white or
%D background. If colors are applied there, they definitely
%D are used local, which means that they don't cross page
%D borders.
%D
%D Boxes are handled as a whole, which means that when we
%D apply colors inside a box, those colors don't cross page
%D boundaries, unless of course boxes are split or unboxed.
%D Especially in interactive texts, colors are often used in
%D such a local way: in boxes (buttons and navigational tools)
%D or in the pagebody (backgrounds).
%D
%D So we can distinguish local colors, that don't cross
%D pages from global colors, of which we can end many pages
%D later. The color macros will treat both types in a different
%D way, thus gaining some speed.
%D
%D This module also deals with gray scales. Because similar
%D colors can end up in the same gray scale when printed in
%D black and white, we also implement a palet system that deals
%D with these matters. Because of fundamental differences
%D between color and gray scale printing, in \CONTEXT\ we also
%D differ between these. For historic reasons |<|we first
%D implemented gray scales using patterns of tiny periods|>|
%D and therefore called them {\em rasters}. So don't be
%D surprised if this term shows up.

\startmessages  dutch  library: colors
  title: kleur
      1: systeem -- is globaal actief
      2: systeem -- is lokaal actief
      3: -- is niet gedefinieerd --
      4: systeem -- wordt geladen
      5: onbekend systeem --
      6: palet -- is beschikbaar
      7: palet -- is niet beschikbaar
      8: specificatie -- bij -- wordt zwart
      9: -- kleurruimte wordt niet ondersteund
     10: -- kleurruimte wordt ondersteund
     11: kleur wordt vertaald in grijs
     12: -- is geregistreerd
\stopmessages

\startmessages  english  library: colors
  title: color
      1: system -- is global activated
      2: system -- is local activated
      3: -- is not defined --
      4: system -- is loaded
      5: unknown system --
      6: palette -- is available
      7: palette -- is not available
      8: specification -- at color -- becomes black
      9: -- color space is not supported
     10: -- color space is supported
     11: color is converted to gray
     12: -- is registered
\stopmessages

\startmessages  german  library: colors
  title: farbe
      1: system -- ist global aktiviert
      2: system -- ist lokal aktiviert
      3: -- ist undefiniert --
      4: system -- ist geladen
      5: unbekanntes System --
      6: palette -- ist verfuegbar
      7: palette -- ist nicht verfuegbar
      8: Spezifikation -- bei Farbe -- wird schwarz
      9: -- Farbraum wird nicht unterstuetzt
     10: -- Farbraum wird unterstuetzt
     11: Farbe wird in Grau umgewandelt
     12: -- is registered
\stopmessages

\startmessages  czech  library: colors
  title: barva
      1: system -- je globalne aktivovana
      2: system -- je lokalne activovana
      3: -- neni definovana --
      4: system -- je nacten
      5: neznamy system --
      6: palette -- je k dispozici
      7: palette -- neni k dispozici
      8: specifikace -- v barve -- bude cerna
      9: -- prostor barev neni podporovan
     10: -- prostor barev je podporovan
     11: barva je prevedena na sed
     12: -- is registered
\stopmessages

\startmessages  italian  library: colors
  title: colore
      1: sistema -- attivato globalmente
      2: sistema -- attivato localmente
      3: -- non definito --
      4: sistema -- caricato
      5: sistema -- sconosciuto
      6: tavolozza -- resa disponibile
      7: tavolozza -- non disponibile
      8: specifica -- del colore -- convertita in nero
      9: spazio dei colori -- non supportato
     10: spazio dei colori -- supportato
     11: il colore ø convertito in grigio
     12: -- is registered
\stopmessages

\startmessages  norwegian  library: colors
  title: farge
      1: system -- er aktivert globalt
      2: system -- er aktivert lokalt
      3: -- er udefinert --
      4: system -- er lest inn
      5: ukjent system --
      6: palett -- er tilgjengelig
      7: palett -- er ikke tilgjengelig
      8: spesifikasjon -- for farge -- gir kun svart
      9: -- fargerom er ikke støttet
     10: -- fargerom er støttet
     11: fargen vil bli vist som grø
     12: -- is registered
\stopmessages

\startmessages  romanian  library: colors
  title: culori
      1: sistem -- este activata global
      2: sistem -- este activata local
      3: -- nu este definita --
      4: sistem -- este incarcata
      5: sistem -- necunoscuta
      6: paleta -- este disponibila
      7: palette -- nu este disponibila
      8: specificatia -- la culoarea -- devine neagra
      9: spatiul de culoare -- nu este suportat
     10: spatiul de culoare -- este suportat
     11: culoarea este convertita la gri
     12: -- is registered
\stopmessages

\startmessages  french  library: colors
  title: couleurs
      1: le système -- est globalement activé
      2: le système -- est localement activé
      3: -- n'est pas défini --
      4: le système -- est chargé
      5: système -- inconnu
      6: la palette -- est disponible
      7: le palette -- n'est pas disponible
      8: la spécification -- de la couleur -- devient noire
      9: l'espace de couleur -- n'est pas supporté
     10: -- l'espace de couleur est supporté
     11: la couleur est convertie en niveau de gris
     12: -- est enregistré
\stopmessages

%D We use a couple of local registers. That way we don't have
%D to group when converting colors. By the way, this is not
%D really faster. We can sqeeze half a second runtime for 50K
%D switches on a 1G machine, but the macros will become rather
%D ugly then. To mention one such improvement: no colon
%D after the key character (.25 sec).

\newdimen\colordimen
\newcount\colorcount

%D \macros
%D   {definecolor}
%D
%D We will enable users to specify colors in \cap{RGB} and
%D \cap{CMYK} color spaces or gray scales using
%D
%D \showsetup{definecolor}
%D
%D For example:
%D
%D \starttyping
%D \definecolor [SomeKindOfRed] [r=.8,g=.05,b=.05]
%D \stoptyping
%D
%D Such color specifications are saved in a macro in the
%D following way:
%D
%D \starttyping
%D \setvalue{\??cr name}{R:r:g:b}
%D \setvalue{\??cr name}{C:c:m:y:k}
%D \setvalue{\??cr name}{S:s}
%D \stoptyping
%D
%D Gray scales are specified with the \type{s} parameter,
%D where the \type {s} is derived from {\em screen}.
%D
%D Starting with \PDF\ 1.4 (2001) \CONTEXT\ supports
%D transparent colors. The transparency factor is represented
%D by a \type {t} and the transparency method by an \type {a}
%D (alternative). Later we will implement more control
%D (probably by symbolic methods. So, currently the data is
%D stored as follows:
%D
%D \starttyping
%D \setvalue{\??cr name}{R:r:g:b:a:t}
%D \setvalue{\??cr name}{C:c:m:y:k:a:t}
%D \setvalue{\??cr name}{S:s:a:t}
%D \stoptyping

% beware: comparisons asked/current on name, not value

\newif\iffreezecolors  \freezecolorsfalse

\let\colorlist       \empty
\let\currentspotcolor\empty

\def\@@cl@@z{0}
\def\@@cl@@o{1}

% \def\@@resetcolorparameters
%   {\let\@@cl@@r\@@cl@@z\let\@@cl@@g\@@cl@@z\let\@@cl@@b\@@cl@@z
%    \let\@@cl@@c\@@cl@@z\let\@@cl@@m\@@cl@@z\let\@@cl@@y\@@cl@@z\let\@@cl@@k\@@cl@@z
%    \let\@@cl@@s\@@cl@@z\let\@@cl@@p\@@cl@@o
%    \let\@@cl@@t\@@cl@@z\let\@@cl@@a\@@cl@@z
%    \let\@@cl@@h\empty  \let\@@cl@@n\empty}

% r g b   : rbg
% c m y k : cmyk
% s       : gray
% p n d f : spot
% h       : hexadecimal
% t a     : transparency
% e       : equivalent (spotcolors)

\def\@@resetcolorparameters
  {\let\@@cl@@r\@@cl@@z \let\@@cl@@g\@@cl@@z \let\@@cl@@b\@@cl@@z
   \let\@@cl@@c\@@cl@@z \let\@@cl@@m\@@cl@@z \let\@@cl@@y\@@cl@@z \let\@@cl@@k\@@cl@@z
   \let\@@cl@@s\@@cl@@z
   \let\@@cl@@p\@@cl@@o \let\@@cl@@n\empty \let\@@cl@@d\empty \let\@@cl@@f\@@cl@@o
   \let\@@cl@@h\empty
   \let\@@cl@@e\empty
   \let\@@cl@@t\@@cl@@z \let\@@cl@@a\@@cl@@z}

\@@resetcolorparameters

\def\@@cl@@A{\@@cl@@a} % a hook for symbolic conversion, see below

%D Handling a few nested \type{\cs}'s is no problem (\type
%D {\@EA\@EAEAEA\@EA}) but we need a full expansion, so I
%D tried one of the fully expandable primitives using a sort
%D of delimited thing. I tried \type {\number} first, but this
%D does not work, but \type {\romannumeral} does. Actually,
%D \type{\romannumeral0} returns nothing, so it's a perfect
%D candidate for this kind of hackery. This reminds me that I
%D have to look into David Kastrup's Euro\TeX\ 2002 article
%D because he is using \type {\romannumeral} for loops
%D (repetitive \quote {m} stuff).

% \def\x{\y}\def\y{\z}\def\z{0:1:1:1}
%
% \def\bla #1:#2:#3\end{}
%
% \@EA\bla\romannumeral\x\end

\def\colorXpattern{0S:\@@cl@@z:\@@cl@@z:\@@cl@@z}
\def\colorZpattern{0S:\@@cl@@z:\@@cl@@A:\@@cl@@t}
\def\colorSpattern{0S:\@@cl@@s:\@@cl@@A:\@@cl@@t}
\def\colorCpattern{0C:\@@cl@@c:\@@cl@@m:\@@cl@@y:\@@cl@@k:\@@cl@@A:\@@cl@@t}
\def\colorRpattern{0R:\@@cl@@r:\@@cl@@g:\@@cl@@b:\@@cl@@A:\@@cl@@t}

%def\colorPpattern{0P:\@@cl@@n:\@@cl@@p:\@@cl@@A:\@@cl@@t}

\def\colorPpattern{0P:\@@cl@@n:\@@cl@@f:\@@cl@@d:\@@cl@@p:\@@cl@@A:\@@cl@@t}

%D The extra 0 catches empty colors specs (needed for the
%D \type {\MPcolor} and \type {\PDFcolor} conversion (\type
%D {\@@cr} equals \type {\relax}!).

\def\handlecolorwith#1{\@EA#1\romannumeral0}

%D Next comes the main definition macro.

\def\definecolor      {\dodoubleargument\dodefinecolor}
\def\defineglobalcolor{\dodoubleargument\dodefineglobalcolor}
\def\definenamedcolor {\dodoubleargument\dodefinenamedcolor}

\def\dodefinecolor      {\dododefinecolor\relax   \setvalue \setevalue1}
\def\dodefineglobalcolor{\dododefinecolor\doglobal\setgvalue\setxvalue1}
\def\dodefinenamedcolor {\dododefinecolor\doglobal\setvalue \setevalue0}

\def\dododefinecolor#1#2#3#4[#5][#6]% #2==set(g)value #3==set[e|x]value
  {#1\addtocommalist{#5}\colorlist % optional
   \doifassignmentelse{#6}
     {\@@resetcolorparameters
      \getparameters[\??cl @@][#6]%
      \ifx\@@cl@@h\empty
        \doifelse{\@@cl@@r\@@cl@@g\@@cl@@b}{\@@cl@@z\@@cl@@z\@@cl@@z}
          {\doifelse{\@@cl@@c\@@cl@@m\@@cl@@y\@@cl@@k}{\@@cl@@z\@@cl@@z\@@cl@@z\@@cl@@z}
             {\doifelse\@@cl@@s\@@cl@@z
                {\showmessage\m!colors8{{[#6]},#5}%
                 #3{\??cr#5}{\colorZpattern}}
                {#3{\??cr#5}{\colorSpattern}}}
             {#3{\??cr#5}{\colorCpattern}}}
          {#3{\??cr#5}{\colorRpattern}}%
      \else
        \setxvalue{\??cr#5}{\colorHpattern}%
      \fi
      % new: e=external spot color name
      \ifx\@@cl@@e\empty \else
        \doregisterspotcolorname{#5}\@@cl@@e
      \fi}
     {\doifelsenothing\currentpalet
         \donefalse
        {\doifdefinedelse{\??cr\currentpalet#6}\donetrue\donefalse}%
      \ifdone
        \doifnot{#5}{#6}
           {#2{\??cr#5}{\paletcolorspec{#6}}}%
      \else
        \doifdefinedelse{\??cr#6}
           {\doifelse{#5}{#6}
              {% this way we can freeze \definecolor[somecolor][somecolor]
               % and still prevent cyclic definitions
               \iffreezecolors#3{\??cr#5}{\csname\??cr#6\endcsname}\fi}
              {\iffreezecolors\@EA#3\else\@EA#2\fi
                 {\??cr#5}{\csname\??cr#6\endcsname}}}
           {\showmessage\m!colors3{#5 (def)}}%
       \fi}%
   \ifcase#4\or
     \unexpanded#2{#5}{\switchtocolor[#5]}% \unexpanded toegevoegd
   \fi}

\def\paletcolorspec#1%
% {\executeifdefined{\??cr\currentpalet#1}{\executeifdefined{\??cr#1}\empty}}
  {\csname\??cr\currentpalet#1\endcsname}

%D Hex color support is not enabled by default. You need to say \type
%D {\setupcolor [hex]} to get this working.

\ifx\colorHpattern\undefined \let\colorHpattern\colorZpattern \fi

%D New and experimental.

\let\allspotcolors    \empty
\let\usedspotcolors   \empty
\let\usedcolorchannels\empty

\def\definespotcolor % [name] [color] [p=,t=,a=]
  {\dotripleempty\dodefinespotcolor}

\def\dodefinespotcolor[#1][#2][#3]% todo: always global
  {\doifnot{#1}{#2}
     {\@@resetcolorparameters
      \edef\@@cl@@n{#2}%
      \getparameters[\??cl @@][#3]%
      \doifnothing\@@cl@@p{\let\@@cl@@p\!!plusone}%
      \ifx\@@cl@@e\empty \else
        \doregisterspotcolorname{#2}\@@cl@@e
      \fi
      \doglobal\addtocommalist{#2}\allspotcolors
      \setxvalue{\??cr#1}{\colorPpattern}% was \setevalue
      \setgvalue{#1}{\switchtocolor[#1]}}} % was \setvalue

\def\registerusedspotcolors
  {\ifx\allspotcolors\empty \else
     \bgroup
     \let\usedspotcolors\empty
     \def\docommand##1%
       {\doifdefined{\??cs##1}{\addtocommalist{##1}\usedspotcolors}}%
     \processcommacommand[\allspotcolors]\docommand
     \savecurrentvalue\usedspotcolors\usedspotcolors
     \egroup
   \fi}

\def\registerusedcolorchannels
  {\bgroup
   \doifdefinedelse{\??cs c}
     {\def\usedcolorchannels{c,m,y,k}}%
     {\let\usedcolorchannels\empty}%
   \doifdefined{\??cs r}
     {\addtocommalist{r,g,b}\usedcolorchannels}%
   \doifdefined{\??cs s}
     {\ExpandBothAfter\doifnotinset{k}\usedcolorchannels
        {\addtocommalist{s}\usedcolorchannels}}%
   \savecurrentvalue\usedcolorchannels\usedcolorchannels
   \egroup}

\prependtoks
  \registerusedspotcolors
  \registerusedcolorchannels
\to \everylastshipout

\def\registerusedspotcolor#1%
  {\global\@EA\chardef\csname\??cs#1\endcsname\zerocount}

%D On top of spotcolors, we define multitone colors. You'd better know
%D what you're doing because invalid definitions will lead to invalid
%D documents (i.e.\ resources).

% \definecolor [darkblue]   [c=.5,m=.5]
% \definecolor [darkyellow] [y=.5]
%
% \definemultitonecolor [whatever] [darkblue=.5,darkyellow=.5] [c=.25,m=.25,y=.25] [a=1,t=.5]
% \definemultitonecolor [another]  [darkblue=.5,darkyellow=.5] [c=.25,m=.25,y=.25]

\def\definemultitonecolor
  {\doquadrupleempty\dodefinemultitonecolor}

\def\dodefinemultitonecolor[#1][#2][#3][#4]%
  {\let\@@cl@@cl@@D\empty % n's
   \let\@@cl@@cl@@P\empty % p's
   \let\@@cl@@cl@@N\empty % name
   \scratchcounter\zerocount
   \processcommacommand[#2]\dododefinemultitonecolor
   \bgroup
     \lccode`\.=`\_%
     \lccode`\,=`\_%
     \lccode`\:=`\_%
     \lccode`\;=`\_%
     \lccode`\+=`\_%
     \lccode`\-=`\_%
     \lccode`\*=`\_%
     \lccode`\/=`\_%
%      \lccode`\_=`\_%
     % not needed, other attribute in driver:
     %
     % \@@resetcolorparameters
     % \getparameters[#4]%
     % \ifx\@@cl@@t\@@cl@@z\else
     %   \edef\@@cl@@cl@@N{\@@cl@@cl@@N_\@@cl@@t_\@@cl@@a}%
     % \fi
     \lowercase\@EA{\@EA\xdef\@EA\@@cleancolor\@EA{\@@cl@@cl@@N}}%
   \egroup
   \setxvalue{\??cl\@@cleancolor\s!check}{\noexpand\docheckmultitonecolor{\@@cl@@cl@@D}}%
   \expanded{\defineglobalcolor[\@@cleancolor][#3,#4]}%
   \expanded{\definespotcolor[#1][\@@cleancolor][#4,f=\the\scratchcounter,p={\@@cl@@cl@@P},d={\@@cl@@cl@@D}]}}

\def\docheckmultitonecolor#1%
  {\flushatshipout
     {\let\checkmultitonecolor\gobbleoneargument
      \def\docommand##1{\hbox{\definecolor[\s!dummy-100][##1][p=1]\color[\s!dummy-100]}}%
      \processcommalist[#1]\docommand}}

\def\checkmultitonecolor#1%
  {\csname\??cl#1\s!check\endcsname\letgvalue{\??cl#1\s!check}\relax}

\def\dodefinespotcolor[#1][#2][#3]% todo: always global (REDEFINED)
  {\doifnot{#1}{#2}
     {\@@resetcolorparameters
      \edef\@@cl@@n{#2}%
      \getparameters[\??cl @@][#3]%
      \doifnothing  \@@cl@@p{\let\@@cl@@p\!!plusone}%
      \doifsomething\@@cl@@e{\doregisterspotcolorname{#2}\@@cl@@e}%
      \doglobal\addtocommalist{#2}\allspotcolors
      \setxvalue{\??cr#1}{\colorPpattern}% was \setevalue
      \setgvalue{#1}{\switchtocolor[#1]}}}% was \setvalue

\def\dododefinemultitonecolor#1%
  {\advance\scratchcounter\plusone
   \splitstring#1\at=\to\!!stringa\and\!!stringb
   \ifx\@@cl@@cl@@D\empty
     \let\@@cl@@cl@@D\!!stringa
     \let\@@cl@@cl@@P\!!stringb
     \normalizecolor\!!stringb
     \edef\@@cl@@cl@@N{\!!stringa_\!!stringb}%
   \else
     \edef\@@cl@@cl@@D{\@@cl@@cl@@D,\!!stringa}%
     \edef\@@cl@@cl@@P{\@@cl@@cl@@P,\!!stringb}%
     \normalizecolor\!!stringb
     \edef\@@cl@@cl@@N{\@@cl@@cl@@N_\!!stringa_\!!stringb}%
   \fi}

% \def\dododefinemultitonecolor#1% a/b safe
%   {\advance\scratchcounter\plusone
%    \splitstring#1\at=\to\@@cl@@one\and\@@cl@@two
%    \ifx\@@cl@@cl@@D\empty
%      \let\@@cl@@cl@@D\@@cl@@one
%      \let\@@cl@@cl@@P\@@cl@@two
%      \normalizecolor\@@cl@@two
%      \edef\@@cl@@cl@@N{\@@cl@@one_\@@cl@@two}%
%    \else
%      \edef\@@cl@@cl@@D{\@@cl@@cl@@D,\@@cl@@one}%
%      \edef\@@cl@@cl@@P{\@@cl@@cl@@P,\@@cl@@two}%
%      \normalizecolor\@@cl@@two
%      \edef\@@cl@@cl@@N{\@@cl@@cl@@N_\@@cl@@one_\@@cl@@two}%
%    \fi}

%D We now redefine the color definition macro so that you
%D can define both normal and spotcolors.

\def\definecolor
  {\dotripleempty\dodefinewhatevercolor}

\def\dodefinewhatevercolor[#1][#2][#3]%
  {\ifthirdargument
     \doifassignmentelse{#2}
       {\dododefinecolor[#1][#2,#3]}% actually this is an error
       {\dodefinespotcolor[#1][#2][#3]}% and this the prefered method
   \else
     \dodefinecolor[#1][#2]%
   \fi}

%D The names of colors are stored in a comma separated list
%D only for the purpose of showing them with \type {\showcolor}.
%D
%D \startbuffer
%D \definecolor [SomeKindOfRed] [r=.8,g=.05,b=.05]
%D \stopbuffer
%D
%D \typebuffer
%D \getbuffer
%D
%D This color shows up as \color [SomeKindOfRed] {some kind
%D of red}.
%D
%D \starttyping
%D \setupcolors[state=start]
%D
%D \definecolor[mygreen][green]
%D \definecolor[green][g=.5]
%D
%D \startcolor[mygreen]test\stopcolor
%D
%D \setupcolors[expansion=no]
%D
%D \definecolor[mygreen][green]
%D \definecolor[green][g=.5]
%D
%D \startcolor[mygreen]test\stopcolor
%D \stoptyping

%D \macros
%D   {setupcolor}
%D
%D Color definitions can be grouped in files with the name:
%D
%D \starttyping
%D \f!colorprefix-identifier.tex
%D \stoptyping
%D
%D where \type{\f!colorprefix} is \unprotect {\tttf \f!colorprefix}.
%D Loading such a file is done by \protect
%D
%D \showsetup{setupcolor}
%D
%D Some default colors are specified in \type{colo-rgb.tex},
%D which is loaded into the format by:
%D
%D \starttyping
%D \setupcolor[rgb]
%D \stoptyping

\let\colorstyle\empty

\def\setupcolor
  {\dosingleargument\dosetupcolor}

\def\dosetupcolor[#1]%
  {\doifnot{#1}\colorstyle
     {\def\colorstyle{#1}%
      \processcommalist[#1]\dodosetupcolor}}

\def\dodosetupcolor#1%
  {\makeshortfilename[\truefilename{\f!colorprefix#1}]%
   \startreadingfile
     \readsysfile\shortfilename
       {\showmessage\m!colors4\colorstyle}
       {\showmessage\m!colors5\colorstyle}%
   \stopreadingfile}

\let\usecolors\setupcolor

%D When typesetting for paper, we prefer using the \cap{CMYK}
%D color space, but for on||screen viewing we prefer \cap{RGB}
%D (the previous implementation supported only this scheme).
%D Independant of such specifications, we support some automatic
%D conversions:
%D
%D \startitemize[packed]
%D \item  convert all colors to \cap{RGB}
%D \item  convert all colors to \cap{CMYK}
%D \item  convert all colors to gray scales
%D \stopitemize
%D
%D We also support optimization of colors to gray scales.
%D
%D \startitemize[continue]
%D \item  reduce gray colors to gray scales
%D \item  reduce \cap{CMY} components to \cap{K}
%D \stopitemize
%D
%D These options are communicated by means of:

\newif\ifRGBsupported
\newif\ifCMYKsupported
\newif\ifSPOTsupported
\newif\ifpreferGRAY
\newif\ifGRAYprefered
\newif\ifreduceCMYK

%D The last boolean controls reduction of \cap{CMYK} to
%D \cap{CMY} colors. When set to true, the black component
%D is added to the other ones.
%D
%D Prefering gray is not the same as converting to gray.
%D Conversion treats each color components in a different way,
%D while prefering is just a reduction and thus a
%D space||saving option.

%D The next (internal) switch suppresses duplicate messages.

\newif\ifconverttoGRAY

%D \macros
%D   {startcolormode,stopcolormode,permitcolormode}
%D
%D We use \type{\stopcolormode} to reset the color in
%D whatever color space and do so by calling the corresponding
%D special. Both commands can be used for fast color
%D switching, like in colored verbatim,

\newif\ifpermitcolormode \permitcolormodetrue

\def\dowithcolor#1#2% #1=\action #2=color
  {\ifincolor\ifpermitcolormode
     \ifcsname\??cr\currentpalet#2\endcsname
       \handlecolorwith#1\csname\??cr\currentpalet#2\endcsname\od
     \else\ifcsname\??cr#2\endcsname
       \handlecolorwith#1\csname\??cr#2\endcsname\od
     \fi\fi
   \fi\fi}

\def\startcolormode % includes \ifincolor\ifpermitcolormode
  {%\dostoptransparency % needed for: {test \trans test \notrans test}
   \conditionalstoptransparency
   \dowithcolor\execcolorRCSP}

\def\stopcolormode
  {\ifincolor\ifpermitcolormode
     \supportedstoptransparency
     \dostopcolormode
   \fi\fi}

\def\restorecolormode
  {\ifincolor\ifpermitcolormode
     \supportedstoptransparency
     \dostopcolormode
     \ifx\maintextcolor\empty \else
       \startcolormode\maintextcolor
     \fi
   \fi\fi}

%D Color modes are entered using the next set of commands.
%D The \type{\stop} alternatives are implemented in a way
%D that permits non||grouped use.
%D
%D The, for this module redundant, check if we are in color
%D mode is needed when we use these macros in other modules.

\chardef\currentcolorchannel=0

\newif\iffilterspotcolor \filterspotcolorfalse
\newif\ifdoingspotcolor  \doingspotcolorfalse

\def\registercolorchannel#1%
  {\ifdoingspotcolor \else
     \global\expandafter\chardef\csname\??cs#1\endcsname\zerocount
   \fi}

\def\execcolorRCSP#1:%
  {\csname execcolor#1\endcsname}

\def\execcolorR
  {\iffilterspotcolor
     \@EA\noexeccolorR
   \else
     \@EA\doexeccolorR
   \fi}

\def\execcolorC
  {\iffilterspotcolor
     \@EA\noexeccolorC
   \else
     \@EA\doexeccolorC
   \fi}

\def\execcolorS
  {\iffilterspotcolor
     \@EA\noexeccolorS
   \else
     \@EA\doexeccolorS
   \fi}

\def\execcolorP
  {\iffilterspotcolor
     \@EA\doexeccolorPP
   \else\ifcase\currentcolorchannel
     \@EAEAEA\doexeccolorP
   \else
     \@EAEAEA\noexeccolorP
   \fi\fi}

\def\doexeccolorR#1:#2:#3:%
  {\edef\@@cl@@r{#1}\edef\@@cl@@g{#2}\edef\@@cl@@b{#3}%
   \ifpreferGRAY\ifx\@@cl@@r\@@cr@@g\ifx\@@cl@@r\@@cl@@b
     \GRAYpreferedtrue
   \fi\fi\fi
   \ifincolor\else\RGBsupportedfalse\CMYKsupportedfalse\fi
   \ifGRAYprefered
     \registercolorchannel\c!s
     \let\@@cl@@s\@@cl@@r
     \normalizeGRAY
     \doexeccolorgray
   \else\ifRGBsupported
     \registercolorchannel\c!r
     \normalizeRGB
     \doexeccolorrgb
   \else\ifCMYKsupported
     \registercolorchannel\c!c
     \convertRGBtoCMYK\@@cl@@r\@@cl@@g\@@cl@@b
     \normalizeCMYK
     \doexeccolorcmyk
   \else
     \registercolorchannel\c!s
     \convertRGBtoGRAY\@@cl@@r\@@cl@@g\@@cl@@b
     \normalizeGRAY
     \doexeccolorgray
   \fi\fi\fi
   \exectransparency}

\def\doexeccolorC#1:#2:#3:#4:%
  {\edef\@@cl@@c{#1}\edef\@@cl@@m{#2}\edef\@@cl@@y{#3}\edef\@@cl@@k{#4}%
   \ifpreferGRAY\ifx\@@cl@@k\@@cl@@z\ifx\@@cl@@c\@@cr@@m\ifx\@@cl@@c\@@cl@@y
     \GRAYpreferedtrue
   \fi\fi\fi\fi
   \ifincolor\else\RGBsupportedfalse\CMYKsupportedfalse\fi
   \ifGRAYprefered
     \registercolorchannel\c!s
     \let\@@cl@@s\@@cl@@c
     \normalizeGRAY
     \doexeccolorgray
   \else\ifCMYKsupported
     \registercolorchannel\c!c
     \ifreduceCMYK
       \convertCMYKtoCMY\@@cl@@c\@@cl@@m\@@cl@@y\@@cl@@k
     \fi
     \normalizeCMYK
     \doexeccolorcmyk
   \else\ifRGBsupported
     \registercolorchannel\c!r
     \convertCMYKtoRGB\@@cl@@c\@@cl@@m\@@cl@@y\@@cl@@k
     \normalizeRGB
     \doexeccolorrgb
   \else
     \registercolorchannel\c!s
     \convertCMYKtoGRAY\@@cl@@c\@@cl@@m\@@cl@@y\@@cl@@k
     \normalizeGRAY
     \doexeccolorgray
   \fi\fi\fi
   \exectransparency}

\def\doexeccolorS#1:%
  {\edef\@@cl@@s{#1}%
   \registercolorchannel\c!s
   \normalizeGRAY
   \doexeccolorgray
   \exectransparency}

% \def\doexeccolorP#1:#2:%
%   {\edef\@@cl@@n{#1}%
%    \edef\@@cl@@p{#2}%
%    \registerusedspotcolor\@@cl@@n
%    \ifSPOTsupported
%      \dowithcolor\registerspotcolor\@@cl@@n
%      \dostartspotcolormode\@@cl@@n\@@cl@@p
%    \else
%      \doingspotcolortrue
%      \let\spotcolorfactor\@@cl@@p
%      \factorizecolortrue            % using counter and array
%      \dowithcolor\execcolorRCSP\@@cl@@n
%      \factorizecolorfalse
%      \let\spotcolorfactor\@@cl@@o
%      \doingspotcolorfalse
%    \fi
%    \exectransparency}

\def\doexeccolorP#1:#2:#3:#4:%
  {\edef\@@cl@@n{#1}% name
   \edef\@@cl@@f{#2}% fractions
   \edef\@@cl@@d{#3}% definitions
   \edef\@@cl@@p{#4}%
   \ifx\@@cl@@d\empty
     \let\@@cl@@d\@@cl@@n
   \fi
   \registerusedspotcolor\@@cl@@n
   \ifSPOTsupported
     \checkmultitonecolor\@@cl@@n
     \dowithcolor\registerspotcolor\@@cl@@n
     \dostartspotcolormode\@@cl@@n\@@cl@@p
   \else
     \doingspotcolortrue
     \let\spotcolorfactor\@@cl@@p
     \factorizecolortrue            % using counter and array
     \dowithcolor\execcolorRCSP\@@cl@@n
     \factorizecolorfalse
     \let\spotcolorfactor\@@cl@@o
     \doingspotcolorfalse
   \fi
   \exectransparency}

\def\doexeccolorPindex#1:#2:#3:#4:%
  {\edef\@@cl@@n{#1}%
   \edef\@@cl@@f{#2}%
   \edef\@@cl@@d{#3}%
   \edef\@@cl@@p{#4}%
   \ifx\@@cl@@d\empty
     \let\@@cl@@d\@@cl@@n
   \fi
   \ifSPOTsupported
     \checkmultitonecolor\@@cl@@n
     \dowithcolor\registerindexcolor\@@cl@@n
   \fi
   \noexectransparency}

\def\doexeccolorPP#1:#2:%
  {\edef\@@cl@@n{#1}%
   \edef\@@cl@@p{#2}%
   \registerusedspotcolor\@@cl@@n
   \ifx\@@cl@@n\currentspotcolor
     \normalizeSPOT
     \dostartgraycolormode\@@cl@@p % was spotcolormode
   \else
     \dovidecolor\@@cl@@p\@@cl@@o
   \fi
   \exectransparency}

\def\doexeccolorrgb
  {\ifcase\currentcolorchannel
     \dostartrgbcolormode\@@cl@@r\@@cl@@g\@@cl@@b
   \or \or \or \or
   \or \dostartgraycolormode\@@cl@@r
   \or \dostartgraycolormode\@@cl@@g
   \or \dostartgraycolormode\@@cl@@b
   \fi}

\def\doexeccolorcmyk
  {\ifcase\currentcolorchannel
       \dostartcmykcolormode\@@cl@@c\@@cl@@m\@@cl@@y\@@cl@@k
   \or \negatecolorcomponent\@@cl@@c\dostartgraycolormode\@@cl@@c
   \or \negatecolorcomponent\@@cl@@m\dostartgraycolormode\@@cl@@m
   \or \negatecolorcomponent\@@cl@@y\dostartgraycolormode\@@cl@@y
   \or \negatecolorcomponent\@@cl@@k\dostartgraycolormode\@@cl@@k
   \fi}

\def\doexeccolorgray
  {\ifcase\currentcolorchannel
       \dostartgraycolormode\@@cl@@s
   \or \or \or
   \or \dostartgraycolormode\@@cl@@s
   \or \or \or
   \or \dostartgraycolormode\@@cl@@s
   \fi}

%D When filtering colors, we need to either erase
%D the background, or ignore the foreground.

% \newif\ifhidesplitcolor \hidesplitcolortrue
%
% \def\noexeccolor#1\od
%   {\dostartgraycolormode\@@cl@@o}
%
% \let\noexeccolorS\noexeccolor
% \let\noexeccolorP\noexeccolor

%D Well, here comes some real trickery. When we have the 100\%
%D spot color or black color, we don't want to erase the
%D background. So, instead we hide the content by giving it
%D zero transparency.

% todo : #1#2#3 met #2 > of < and #3 een threshold

\newif\ifhidesplitcolor \hidesplitcolortrue

\def\dohidecolor#1#2%
  {\ifhidesplitcolor
     \ifx#1#2%
       \dostartgraycolormode\@@cl@@o
     \else
       \doregisternonecolor
       \dostartnonecolormode
     \fi
   \else
     \dostartgraycolormode\@@cl@@o
   \fi}

\def\dovidecolor#1#2%
  {\ifhidesplitcolor
     \ifx#1#2%
       \doregisternonecolor
       \dostartnonecolormode
     \else
       \dostartgraycolormode\@@cl@@o
     \fi
   \else
     \dostartgraycolormode\@@cl@@o
   \fi}

% \def\fullytransparentcolor % fails on floats
%   {\dostartgraycolormode\@@cl@@o % better than z
%   %\global\@EA\chardef\csname\@@currenttransparent\endcsname\plusone
%   %\global\intransparenttrue
%    \dostarttransparency10}

\def\noexeccolorR#1:#2:#3:#4\od
  {\edef\@@cl@@r{#1}\edef\@@cl@@g{#2}\edef\@@cl@@b{#3}%
   \dohidecolor\@@cl@@s\@@cl@@o}

\def\noexeccolorC#1:#2:#3:#4:#5\od
  {\edef\@@cl@@c{#1}\edef\@@cl@@m{#2}\edef\@@cl@@y{#3}\edef\@@cl@@k{#4}%
   \dohidecolor\@@cl@@s\@@cl@@o}

\def\noexeccolorS#1:#2\od
  {\edef\@@cl@@s{#1}%
   \dohidecolor\@@cl@@s\@@cl@@o}

% \def\noexeccolorP#1:#2:#3\od
%   {\edef\@@cl@@p{#2}%
%    \dohidecolor\@@cl@@p\@@cl@@z}

\def\noexeccolorP#1:#2:#3:#4:#5\od
  {\edef\@@cl@@p{#4}%
   \dohidecolor\@@cl@@p\@@cl@@z}

%D For the sake of postprocessing (i.e.\ color separation)
%D we can normalize colors, which comes down to giving equal
%D values an equal accuracy and format. This feature is
%D turned off by default due to a speed penalty. This macro
%D also handles spot color percentages.

\newif\iffactorizecolor
\newif\ifnormalizecolor

\def\spotcolorfactor{1}

\def\normalizecolor#1%
  {\colordimen#1\thousandpoint
   \colordimen\spotcolorfactor\colordimen
   \colorcount\colordimen
   \advance\colorcount \medcard
   \divide\colorcount \maxcard
   \edef#1{\realcolorvalue\colorcount}}

\def\normalizespotcolor#1%
  {\colordimen-#1\thousandpoint
   \advance\colordimen\thousandpoint
   \colorcount\colordimen
   \advance\colorcount \medcard
   \divide\colorcount \maxcard
   \edef#1{\realcolorvalue\colorcount}}

\def\donormalizeRGB
  {\normalizecolor\@@cl@@r
   \normalizecolor\@@cl@@g
   \normalizecolor\@@cl@@b}

\def\normalizeRGB
  {\ifnormalizecolor
     \donormalizeRGB
   \else\iffactorizecolor
     \donormalizeRGB
   \fi\fi}

\def\donormalizeCMYK
  {\normalizecolor\@@cl@@c
   \normalizecolor\@@cl@@m
   \normalizecolor\@@cl@@y
   \normalizecolor\@@cl@@k}

\def\normalizeCMYK
  {\ifnormalizecolor
     \donormalizeCMYK
   \else\iffactorizecolor
     \donormalizeCMYK
   \fi\fi}

\def\donormalizeGRAY
  {\normalizecolor\@@cl@@s}

\def\normalizeGRAY
  {\ifnormalizecolor
     \donormalizeGRAY
   \else\iffactorizecolor
     \donormalizeGRAY
   \fi\fi}

\def\normalizeSPOT
  {\normalizespotcolor\@@cl@@p}

%D We need to register spot colors (i.e.\ resources need to
%D be created.

\def\registerspotcolor#1:%
  {\ifcsname\??cl:\c!p:\@@cl@@n\endcsname
     \@EA\dontregisterspotcolor
   \else
     \letgvalue{\??cl:\c!p:\@@cl@@n}\empty
     %\@EA\@EA\csname registerspotcolor#1\endcsname
     \csname registerspotcolor#1\@EA\endcsname
   \fi}

\def\dontregisterspotcolor         #1\od{}
\def\registerspotcolorR   #1:#2:#3:#4\od{\doregisterrgbspotcolor \@@cl@@n\@@cl@@f\@@cl@@d\@@cl@@p{#1}{#2}{#3}}
\def\registerspotcolorC#1:#2:#3:#4:#5\od{\doregistercmykspotcolor\@@cl@@n\@@cl@@f\@@cl@@d\@@cl@@p{#1}{#2}{#3}{#4}}
\def\registerspotcolorS         #1:#2\od{\doregistergrayspotcolor\@@cl@@n\@@cl@@f\@@cl@@d\@@cl@@p{#1}}
\def\registerspotcolorP      #1:#2:#3\od{\doregistergrayspotcolor\@@cl@@n\@@cl@@f\@@cl@@d\@@cl@@p{#2}}

%D Experimental feature:

% \definecolor [darkblue]   [c=1,m=.38,y=0,k=.64] % pantone pms 2965 uncoated m
% \definecolor [darkyellow] [c=0,m=.28,y=1,k=.06] % pantone pms  124 uncoated m
%
% \definecolor [darkblue-50]    [darkblue]   [p=.5]
% \definecolor [darkyellow-50]  [darkyellow] [p=.5]
% \definecolor [darkblue-80]    [darkblue]   [p=.8]
% \definecolor [darkyellow-80]  [darkyellow] [p=.8]
%
% \definecolor [darkblue,darkyellow]  [r=.8]
% \definecolor [darkdull-5030] [darkblue,darkyellow]  [p={.5,.3}]
%
% \setupcolors[state=start]
%
% \blackrule[width=4cm,height=3cm,color=darkblue-50]
% \blackrule[width=4cm,height=3cm,color=darkblue-80]
% \blackrule[width=4cm,height=3cm,color=darkyellow-50]
% \blackrule[width=4cm,height=3cm,color=darkyellow-80]
% \blackrule[width=4cm,height=3cm,color=darkdull-5030]

%D Experimental too (special purpose code).

\def\registerindexcolor#1:%
  {\ifcsname\??cl:i:\@@cl@@n\endcsname
     \@EA\dontregisterindexcolor
   \else
     \letgvalue{\??cl:i:\@@cl@@n}\empty % signal
     \showmessage\m!colors{12}\@@cl@@n
     \@EA\@EA\csname registerindexcolor#1\endcsname
   \fi}

\let\dontregisterindexcolor\dontregisterspotcolor

\def\registerindexcolorR   #1:#2:#3:#4\od{\doregisterrgbindexcolor \@@cl@@n\@@cl@@f\@@cl@@d\@@cl@@p{#1}{#2}{#3}}
\def\registerindexcolorC#1:#2:#3:#4:#5\od{\doregistercmykindexcolor\@@cl@@n\@@cl@@f\@@cl@@d\@@cl@@p{#1}{#2}{#3}{#4}}
\def\registerindexcolorS         #1:#2\od{\doregistergrayindexcolor\@@cl@@n\@@cl@@f\@@cl@@d\@@cl@@p{#1}}
\def\registerindexcolorP      #1:#2:#3\od{\doregistergrayindexcolor\@@cl@@n\@@cl@@f\@@cl@@d\@@cl@@p{#2}}

\def\predefinecolor[#1]%
  {\bgroup
   \flushatshipout{\hbox{\localcolortrue\color[#1]}}% real ones
   \egroup}

\def\predefineindexcolor[#1]%
  {\bgroup
   \flushatshipout{\hbox{\localcolortrue\color[#1]}}% real ones
   \let\doexeccolorP\doexeccolorPindex
   \flushatshipout{\hbox{\localcolortrue\color[#1]}}% index one
   \egroup}

% \def\checkpredefinedcolor[#1]%
%   {\ifcase\internalspotcolorsize{#1}\relax
%      \@EA\predefinecolor\or\@EA\predefinecolor\else\@EA\predefineindexcolor
%    \fi[#1]}

\let\checkpredefinedcolor\predefineindexcolor % we need an index in order to negate bitmaps

%D \startbuffer
%D \definecolor [blue]   [c=1,m=.38,y=0,k=.64] % pantone pms 2965 uncoated m
%D \definecolor [yellow] [c=0,m=.28,y=1,k=.06] % pantone pms  124 uncoated m
%D
%D \definecolor [blue-100]   [blue]   [p=1]
%D \definecolor [yellow-100] [yellow] [p=1]
%D
%D \definemultitonecolor [pdftoolscolor] [blue=.12,yellow=.28] [c=.1,m=.1,y=.3,k=.1]
%D
%D \useexternalfigure[demofig][mill.png][object=no]
%D
%D \startcombination[4*1]
%D   {\externalfigure[demofig]}                      {no color}
%D   {\externalfigure[demofig][color=pdftoolscolor]} {indexed duotone}
%D   {\externalfigure[demofig][color=blue-100]}      {spot color}
%D   {\externalfigure[demofig][color=yellow-100]}    {spot color}
%D \stopcombination
%D \stopbuffer
%D
%D \getbuffer \typebuffer

%D Transparency is handled similar for all three color modes. We
%D can turn transparency off with the following switch:

\newif\iftransparencysupported \transparencysupportedtrue % todo

\def\exectransparency
  {\iftransparencysupported
     \expandafter\doexectransparency
   \else
     \expandafter\noexectransparency
   \fi}

%\def\doexectransparency#1:#2\od
%  {\global\@EA\chardef\csname\@@currenttransparent\endcsname % nasty
%   \ifcase#1\space
%     \zerocount
%   \else
%     \plusone
%     \dostarttransparency{#1}{#2}%
%   \fi}

\def\doexectransparency#1:#2\od
  {\ifcase#1\space
     \global\intransparentfalse
   \else
     \global\intransparentfalse
    %\dostarttransparency{#1}{#2}%
     \supportedstarttransparency{#1}{#2}%
     \global\intransparenttrue
   \fi}

\def\noexectransparency#1\od
  {}

%D Experimental: minimize transparency resets.

\newif\ifintransparent
\newif\ifoptimizetransparency \optimizetransparencytrue % under test

% due to bugs in pdf viewers we used transparancies for
% hiding colors, but now we use none colors

% \def\supportedstoptransparency
%   {\iffilterspotcolor
%      \dostoptransparency
%    \else\iftransparencysupported
%      \dostoptransparency
%    \fi\fi}
%
% \def\conditionalstoptransparency
%   {\iffilterspotcolor
%      \dostoptransparency
%    \else\ifcase\currentcolorchannel
%      \ifoptimizetransparency
%        \ifintransparent
%          \supportedstoptransparency
%          \global\intransparentfalse
%        \fi
%      \else
%        \supportedstoptransparency
%      \fi
%    \else
%      \supportedstoptransparency
%    \fi\fi}

\let\supportedstoptransparency\relax

\def\conditionalstoptransparency
  {\ifoptimizetransparency
     \ifintransparent
       \global\intransparentfalse
       \supportedstoptransparency
     \fi
   \else
     \supportedstoptransparency
   \fi}

\def\supportedstarttransparency
  {\iftransparencysupported
     \globallet\supportedstoptransparency\dostoptransparency
     \expandafter\dostarttransparency
   \else
     \expandafter\gobbletwoarguments
   \fi}

%D We now use the \type {\@@cl@@A} hook to implement
%D symbolic names. These are converted into numbers
%D at definition time (which saves runtime).

\def\definetransparency
  {\dodoubleargument\dodefinetransparency}

\def\dodefinetransparency[#1][#2]%
  {\@EA\chardef\csname\??cl-#1\endcsname#2\relax}

\def\transparencynumber#1%
  {\the\executeifdefined{\??cl-#1}\zerocount}

\definetransparency [none]        [0]  \definetransparency  [0]  [0]
\definetransparency [normal]      [1]  \definetransparency  [1]  [1]
\definetransparency [multiply]    [2]  \definetransparency  [2]  [2]
\definetransparency [screen]      [3]  \definetransparency  [3]  [3]
\definetransparency [overlay]     [4]  \definetransparency  [4]  [4]
\definetransparency [softlight]   [5]  \definetransparency  [5]  [5]
\definetransparency [hardlight]   [6]  \definetransparency  [6]  [6]
\definetransparency [colordodge]  [7]  \definetransparency  [7]  [7]
\definetransparency [colorburn]   [8]  \definetransparency  [8]  [8]
\definetransparency [darken]      [9]  \definetransparency  [9]  [9]
\definetransparency [lighten]    [10]  \definetransparency [10] [10]
\definetransparency [difference] [11]  \definetransparency [11] [11]
\definetransparency [exclusion]  [12]  \definetransparency [12] [12]

%D Now we hook 'm into the patterns:

\def\@@cl@@A{\transparencynumber\@@cl@@a}

%D \macros
%D   {startregistercolor,stopregistercolor,permitcolormode}
%D
%D If you only want to register a color, the switch \type
%D {\ifpermitcolormode} can be used. That way the nested
%D colors know where to go back to.

\def\startregistercolor[#1]%
  {\permitcolormodefalse\startcolor[#1]\permitcolormodetrue}

\def\stopregistercolor
  {\permitcolormodefalse\stopcolor\permitcolormodetrue}

%D We use these macros for implementing text colors
%D (actually, the first application was in foreground
%D colors).
%D
%D \starttyping
%D \starttextcolor[red]
%D   \dorecurse{10}{\input tufte \color[green]{oeps} \par}
%D \stoptextcolor
%D \stoptyping
%D
%D This is more efficient than the alternative:
%D
%D \starttyping
%D \setupbackgrounds[text][foregroundcolor=red]
%D \startregistercolor[red]
%D   \dorecurse{10}{\input tufte \color[green]{oeps} \par}
%D \stopregistercolor
%D \stoptyping

\let\maintextcolor\empty \def\defaulttextcolor{black}

% \def\starttextcolor[#1]%
%   {\doifsomething{#1}
%      {\bgroup
%       \def\stoptextcolor          % also goes ok with \page after
%         {\let\maintextcolor\empty % this one because the top of
%          \stopregistercolor       % page sets the color right (side
%          \egroup}%                % effect)
%       \def\starttextcolor[##1]%
%         {\bgroup
%          \let\stoptextcolor\egroup}%
%       \startregistercolor[#1]%
%       \edef\maintextcolor{#1}}}

\def\@@themaintextcolor{themaintextcolor}

\def\starttextcolor[#1]%
  {\doifsomething{#1}
     {\bgroup
      \def\stoptextcolor          % also goes ok with \page after
        {\let\maintextcolor\empty % this one because the top of
         \stopregistercolor       % page sets the color right (side
         \egroup}%                % effect)
      \def\starttextcolor[##1]%
        {\bgroup
         % \@@themaintextcolor==##1 is catched in \definecolor
         \definecolor[\@@themaintextcolor][##1]%
         \let\stoptextcolor\egroup}%
      \startregistercolor[\@@themaintextcolor]%
      \definecolor[\@@themaintextcolor][#1]%
      \let\maintextcolor\@@themaintextcolor}}

\let\stoptextcolor\relax

%D The following hook permits proper support at the text
%D level. This definition actually belongs in another
%D module.

\ifx\initializemaintextcolor\undefined

  \let\@@clprevcolor\empty

  \def\initializemaintextcolor
    {% saveguard for setting text color to empty after
     % it has been set
     \doifnothing\@@cltextcolor
       {\ifx\@@clprevcolor\empty\else
          \let\@@cltextcolor\defaulttextcolor
        \fi}%
     \doifelsenothing\@@cltextcolor
       {\let\maintextcolor\empty}
       {\edef\@@clprevcolor{\@@cltextcolor}%
        \let\maintextcolor\@@themaintextcolor
        \doifelsenothing\@@cltextcolor % another saveguard
          {\definecolor[\@@themaintextcolor][\defaulttextcolor]}%
          {\definecolor[\@@themaintextcolor][\@@cltextcolor]}%
        \doinitializemaintextcolor}}

  \def\doinitializemaintextcolor
    {\appendtoks\starttextcolor[\@@themaintextcolor]\to\everystarttext
     \appendtoks\stoptextcolor                      \to\everystoptext
     \let\doinitializemaintextcolor\relax}

\fi

%D The next macro can be used to return to the (normal)
%D page color. This macro is used in the same way as
%D \type {\color}.

\def\localstarttextcolor
  {\ifx\maintextcolor\empty
     \startcolormode\defaulttextcolor
   \else
     \startcolormode\maintextcolor
   \fi}

% \def\localstoptextcolor
%   {\stopcolormode}
%
% better:

\def\localstoptextcolor
  {\restorecolormode}

\def\restoretextcolor
  {\ifx\maintextcolor\empty
     \expandafter\dorestoretextcolor
   \else
     % obey main text color
   \fi}

\def\dorestoretextcolor
  {\color[\defaulttextcolor]}

%D We use some reserved names for local color components.
%D Consistent use of these scratch variables saves us
%D unneccessary hash entries.
%D
%D \starttyping
%D \@@cl@@r \@@cl@@g \@@cl@@b
%D \@@cl@@c \@@cl@@m \@@cl@@y \@@cl@@k
%D \@@cl@@s
%D \stoptyping
%D
%D We implement several conversion routines.
%D
%D \starttyping
%D \convertRGBtoCMYK  {r} {g} {b}
%D \convertRGBtoGRAY  {r} {g} {b}
%D \convertCMYKtoRGB  {c} {m} {y} {k}
%D \convertCMYKtoGRAY {c} {m} {y} {k}
%D \convertCMYKtoCMY  {c} {m} {y} {k}
%D \stoptyping
%D
%D The relation between \cap{Gray}, \cap{RGB} and \cap{CMYK}
%D is:
%D
%D \placeformula[-]
%D   \startformula
%D   G = .30r + .59g + .11b
%D     = 1.0 - \min(1.0,\ .30c + .59m + .11y + k)
%D   \stopformula
%D
%D When converting from \cap{CMYK} to \cap{RGB} we use the
%D formula:
%D
%D \placeformula[-]
%D   \startformula
%D   \eqalign
%D     {r &= 1.0 - \min(1.0,\ c+k) \cr
%D      g &= 1.0 - \min(1.0,\ m+k) \cr
%D      b &= 1.0 - \min(1.0,\ y+k)}
%D   \stopformula
%D
%D In the conversion routine the color components are calculated
%D in three digits precision.

\def\realcolorvalue#1%
  {\ifnum#1>\zerocount    % important, first encountered in --modu supp-mpe
   \ifnum#1<\plusten      0.00\the#1\else
   \ifnum#1<\plushundred  0.0\the#1\else
   \ifnum#1<\plusthousand 0.\the#1\else
                          1\fi\fi\fi
   \else                  0\fi}

\def\doconvertCMYKtoRGB#1\k#2\to#3%
  {\ifdim#2\points>#1\points% >= problem, repaired 2/12/2002
     \let#3\@@cl@@z % k >= color
   \else
     \colordimen\onepoint
     \advance\colordimen -#1\points
     \advance\colordimen -#2\points
     \multiply\colordimen \plusthousand
     \colorcount\colordimen
     \advance\colorcount \medcard
     \divide\colorcount \maxcard
     \edef#3{\realcolorvalue\colorcount}%
   \fi}

\def\convertCMYKtoRGB#1#2#3#4%
  {\doconvertCMYKtoRGB#1\k#4\to\@@cl@@r
   \doconvertCMYKtoRGB#2\k#4\to\@@cl@@g
   \doconvertCMYKtoRGB#3\k#4\to\@@cl@@b}

\def\doconvertRGBtoCMYK#1\to#2%
  {\colordimen#1\points
   \multiply\colordimen \plusthousand
   \colorcount\colordimen
   \advance\colorcount \medcard
   \divide\colorcount \maxcard
   \colorcount-\colorcount
   \advance\colorcount \plusthousand
   \edef#2{\realcolorvalue\colorcount}}

\def\convertRGBtoCMYK#1#2#3%
  {\doconvertRGBtoCMYK#1\to\@@cl@@c
   \doconvertRGBtoCMYK#2\to\@@cl@@m
   \doconvertRGBtoCMYK#3\to\@@cl@@y
   \let\@@cl@@k\@@cl@@z}

%D The following switch is mainly meant for (hidden)
%D documentation purposes.

\newif\ifweightGRAY \weightGRAYtrue

\def\nGRAYfactor{333.333}
\def\rGRAYfactor{\ifweightGRAY300\else\nGRAYfactor\fi}
\def\gGRAYfactor{\ifweightGRAY590\else\nGRAYfactor\fi}
\def\bGRAYfactor{\ifweightGRAY110\else\nGRAYfactor\fi}

\def\convertRGBtoGRAY#1#2#3%
  {\colordimen#1\points
   \colordimen\rGRAYfactor\colordimen
   \colorcount\colordimen
   \colordimen#2\points
   \colordimen\gGRAYfactor\colordimen
   \advance\colorcount \colordimen
   \colordimen#3\points
   \colordimen\bGRAYfactor\colordimen
   \advance\colorcount \colordimen
   \advance\colorcount \medcard
   \divide\colorcount \maxcard
   \edef\@@cl@@s{\realcolorvalue\colorcount}}

\def\convertCMYKtoGRAY#1#2#3#4%
  {\convertCMYKtoRGB{#1}{#2}{#3}{#4}%
   \convertRGBtoGRAY\@@cl@@r\@@cl@@g\@@cl@@b}

\def\doconvertCMYKtoCMY#1\k#2\to#3%
  {\colordimen#1\points
   \advance\colordimen #2\points\relax
   \ifdim\colordimen>\onepoint
     \colordimen\onepoint
   %\else
   % \colordimen\colordimen
   \fi
   \multiply\colordimen \plusthousand
   \colorcount\colordimen
   \advance\colorcount \medcard
   \divide\colorcount \maxcard
   \edef#3{\realcolorvalue\colorcount}}

\def\convertCMYKtoCMY#1#2#3#4%
  {\doconvertCMYKtoCMY#1\k#4\to\@@cl@@c
   \doconvertCMYKtoCMY#2\k#4\to\@@cl@@m
   \doconvertCMYKtoCMY#3\k#4\to\@@cl@@y
   \let\@@cl@@k\@@cl@@z}

%D Before we present the color macros, we first define the
%D setup command. This command takes care of setting up the
%D booleans that control local and global behavior (more on
%D that later) and conversion to other color spaces.

\let\currentspotcolor \empty
\let\previousspotcolor\empty

\newif\ifincolor
\newif\iflocalcolor

\def\setupcolors
  {\dosingleargument\dosetupcolors}

\def\resetcolorsplitting
  {\chardef\currentcolorchannel\zerocount
   \let\currentspotcolor\empty
   \filterspotcolorfalse}

\def\colorsplitsuffix{\ifcase\currentcolorchannel\else-\@@clsplit\fi}
\def\colorsplitprefix{\ifcase\currentcolorchannel\else\@@clsplit-\fi}

\def\setcolorsplitting
  {\resetsystemmode{\v!color\colorsplitsuffix}%
   \resetcolorsplitting
   \processaction
     [\@@clsplit]
     [         c=>\chardef\currentcolorchannel1,%
               m=>\chardef\currentcolorchannel2,%
               y=>\chardef\currentcolorchannel3,%
               k=>\chardef\currentcolorchannel4,%
               r=>\chardef\currentcolorchannel5,%
               g=>\chardef\currentcolorchannel6,%
               b=>\chardef\currentcolorchannel7,%
               s=>\chardef\currentcolorchannel8,%
          \v!no=>,%      \currentcolorchannel0,% all colors
      \s!default=>,%      \currentcolorchannel0,% all colors
      \s!unknown=>\filterspotcolortrue
                  \edef\currentspotcolor{\commalistelement}]%
   \setsystemmode{\v!color\colorsplitsuffix}%
   \iffilterspotcolor \let\@@clrgb\v!no \fi}

\def\dosetupcolors[#1]%
  {\getparameters[\??cl][#1]%
   \doifelse\@@clspot\v!yes
     \SPOTsupportedtrue
     \SPOTsupportedfalse
   \doifelsenothing\@@clsplit
     \resetcolorsplitting
     \setcolorsplitting
   \doifelse\@@clreduction\v!yes
     \reduceCMYKtrue
     \reduceCMYKfalse
   \doifelse\@@clexpansion\v!yes
     \freezecolorstrue
     \freezecolorsfalse
   \doifelse\@@clcriterium\v!all
     \hidesplitcolortrue
     \hidesplitcolorfalse
   \doifelse\@@clrgb\v!no
     {\ifRGBsupported     \showmessage\m!colors {9}\v!rgb\RGBsupportedfalse\fi}
     {\ifRGBsupported\else\showmessage\m!colors{10}\v!rgb\RGBsupportedtrue \fi}%
   \doifelse\@@clcmyk\v!no
     {\ifCMYKsupported     \showmessage\m!colors {9}\v!cmyk\CMYKsupportedfalse\fi}
     {\ifCMYKsupported\else\showmessage\m!colors{10}\v!cmyk\CMYKsupportedtrue \fi}%
   % todo : mpspot
   \doifelse\@@clmpcmyk\v!no
     {\ifMPcmykcolors     \showmessage\m!colors {9}{\v!mp\v!cmyk}\MPcmykcolorsfalse\fi}
     {\ifMPcmykcolors\else\showmessage\m!colors{10}{\v!mp\v!cmyk}\MPcmykcolorstrue \fi}%
   \doifelse\@@clmpspot\v!no
     {\ifMPspotcolors     \showmessage\m!colors {9}{\v!mp\v!spot}\MPspotcolorsfalse\fi}
     {\ifMPspotcolors\else\showmessage\m!colors{10}{\v!mp\v!spot}\MPspotcolorstrue \fi}%
   \preferGRAYfalse
   \processaction
     [\@@clconversion]
     [    \v!yes=>\preferGRAYtrue,
       \v!always=>\preferGRAYtrue\RGBsupportedfalse\CMYKsupportedfalse]%
   \ifRGBsupported
     \converttoGRAYfalse
     \forcegrayMPcolorsfalse
   \else\ifCMYKsupported
     \converttoGRAYfalse
     \forcegrayMPcolorsfalse
     \convertMPcolorstrue
     \ifreduceCMYK
       \reduceMPcolorstrue
     \fi
   \else
     \ifconverttoGRAY\else\showmessage\m!colors{11}\empty\fi
     \converttoGRAYtrue
     \forcegrayMPcolorstrue
     \convertMPcolorsfalse
     \reduceMPcolorsfalse
   \fi\fi
   \processaction
     [\@@clstate]
     [ \v!global=>\ifincolor\else\showmessage\m!colors1\colorstyle\fi
                  \incolortrue\localcolorfalse,
        \v!local=>\ifincolor\else\showmessage\m!colors2\colorstyle\fi
                  \incolortrue\localcolortrue,
        \v!start=>\ifincolor\else\showmessage\m!colors1\colorstyle\fi
                  \incolortrue\localcolorfalse
                  \let\@@clstate\v!global,
         \v!stop=>\incolorfalse\localcolorfalse
                  \forcegrayMPcolorstrue]%
   \initializemaintextcolor}

%D \macros
%D   {doifcolorelse}
%D
%D Switching to a color is done by means of the following
%D command. Later on we will explain the use of palets.  We
%D define ourselves a color conditional first.

\let\currentpalet\empty

\def\doifcolorelse#1%
  {\ifcsname\??cr\ifcsname\??cr\currentpalet#1\endcsname\currentpalet\fi#1\endcsname
     \expandafter\firstoftwoarguments
   \else
     \expandafter\secondoftwoarguments
   \fi}

%D \macros
%D   {localstartcolor,localstopcolor}
%D
%D Simple color support, that is without nesting, is provided
%D by:

\def\localstartcolor
  {\ifincolor
     \localcolortrue
     \expandafter\doglobalstartcolor
   \else
     \expandafter\noglobalstartcolor
   \fi}

\def\localstopcolor
  {\ifincolor
     \doglobalstopcolor
   \else
     \noglobalstopcolor
   \fi}

%D \macros
%D   {startcolor,stopcolor}
%D
%D The more save method, the one that saves the current color
%D state and returns to this state afterward, is activated by:
%D
%D \showsetup{startcolor}

\unexpanded\def\startcolor
  {\ifincolor
     \expandafter\doglobalstartcolor
   \else
     \expandafter\noglobalstartcolor
   \fi}

\unexpanded\def\stopcolor
  {\ifincolor
     \doglobalstopcolor
   \else
     \noglobalstopcolor
   \fi}

%D This macros call the global color switching ones. Starting
%D a global, i.e. a possible page boundary crossing, color
%D mode also sets a \type{\mark} in \TEX's internal list.

\newcount\colorlevel

\letvalue{\??cl0C}\empty % saved color
\letvalue{\??cl0S}\empty % stop command

%D We keep a positive color stack for foreground colors, and
%D a negative one for backgrounds. Not that brilliant a
%D solution, but it suits. The signs are swapped when the
%D page ornaments are typeset.

\let\@@colorplus \plusone
\let\@@colorminus\minusone

\def\@@currentcolorname  {\??cl\the\colorlevel C}
\def\@@currentcolorstop  {\??cl\the\colorlevel S}
%def\@@currenttransparent{\??cl\the\colorlevel T}

% \def\currentcolorname
%   {\csname
%      \ifcsname\@@currentcolorname\endcsname\@@currentcolorname\else\s!empty\fi
%    \endcsname}

\letvalue{\??cl*\s!black}\s!black

\def\currentcolorname
  {\csname
     \ifcsname\@@currentcolorname\endcsname
       \expandafter\ifx\csname\@@currentcolorname\endcsname\empty
         \??cl*\s!black
       \else
         \@@currentcolorname
       \fi
     \else
       \??cl*\s!black
     \fi
   \endcsname}

% \def\outercolorname
%   {\ifcsname\@@currentcolorname\endcsname currentcolor\else\s!black\fi}

\def\outercolorname
  {\ifcsname\@@currentcolorname\endcsname
     \expandafter\ifx\csname\@@currentcolorname\endcsname\empty
       \s!black
     \else
       currentcolor%
     \fi
   \else
     \s!black
   \fi}

\def\startcurrentcolor{\startcolor[\outercolorname]}
\def\stopcurrentcolor {\stopcolor}

% not the following, because we need a different tag in order to trick the stack
%
% \def\outercolorname{\executeifdefined\@@currentcolorname\s!black}
%
% \def\startcurrentcolor{\expanded{\startcolor[\s!black]\noexpand\startcolor[\outercolorname]}}
% \def\stopcurrentcolor {\stopcolor\stopcolor}
%
% test case:
%
% \setupcolors[state=start,textcolor=red]
% \starttext
%     red
%         \color[green]{green
%             \startMPcode
%                 label(\sometxt{green\color[blue]{blue}green}, origin) withcolor red;
%                 draw fullcircle scaled 1cm xscaled 2;
%             \stopMPcode
%         green}
%     red
% \stoptext

\def\dodoglobalstartcolor
  {\global\@EA\let\@EA\@@currentcolor\csname\@@currentcolorname\endcsname
   \global\advance\colorlevel \@@colorplus
   \global\@EA\let\csname\@@currentcolorname\endcsname\@@askedcolor
  %\debuggerinfo\m!colors
  %  {start \@@askedcolor\space at level \the\colorlevel}%
   \ifx\@@askedcolor\empty
     \global\@EA\let\csname\@@currentcolorname\endcsname\@@currentcolor
     \global\@EA\let\csname\@@currentcolorstop\endcsname\donoglobalstopcolor
   \else\ifx\@@askedcolor\@@currentcolor
     \global\@EA\let\csname\@@currentcolorstop\endcsname\donoglobalstopcolor
   \else
     \doifcolorelse\@@askedcolor
       {%\docolormark\@@askedcolor
        \ifpermitcolormode\docolormark\@@askedcolor\fi
        \global\@EA\let\csname\@@currentcolorstop\endcsname\dodoglobalstopcolor
        \startcolormode\@@askedcolor}
       {\global\@EA\let\csname\@@currentcolorstop\endcsname\donoglobalstopcolor
        \showmessage\m!colors3\@@askedcolor\empty}%
   \fi\fi}

\def\doglobalstartcolor[#1]%
  {\edef\@@askedcolor{#1}%
   \ifcase\colorlevel\relax
     \ifx\@@askedcolor\empty
       \global\@EA\let\csname\@@currentcolorstop\endcsname\empty
     \else
       \dodoglobalstartcolor
     \fi
   \else
     \dodoglobalstartcolor
   \fi
   \ignorespaces}

\def\noglobalstartcolor[#1]%
  {}

\def\dodoglobalstopcolor
  {\ifcase\colorlevel \else
     \donoglobalstopcolor
     \global\@EA\let\@EA\@@previouscolor\csname\@@currentcolorname\endcsname
     \ifcase\colorlevel\relax
       \ifpermitcolormode
         \docolormark\empty
         \conditionalstoptransparency
         \dostopcolormode
       \fi
     \else % let's do a bit redundant testing here
       \docolormark\@@previouscolor
       \ifx\@@previouscolor\empty
         \ifpermitcolormode
           \conditionalstoptransparency
           \dostopcolormode
         \fi
       \else
         \doifcolorelse\@@previouscolor
           {\ifx\@@currentcolor\@@previouscolor\else
              % alternatively we could let \startcolormode handle this
              \ifpermitcolormode
                \conditionalstoptransparency % really needed
                % more safe but less efficient: \dostopcolormode
              \fi
              \startcolormode\@@previouscolor
            \fi}
           {\ifpermitcolormode
              \conditionalstoptransparency
              \dostopcolormode
            \fi}%
       \fi
     \fi
   \fi}

\def\donoglobalstopcolor
  {\ifcase\colorlevel \else
     \global\@EA\let\@EA\@@currentcolor\csname\@@currentcolorname\endcsname
    %\debuggerinfo{\m!colors}
    %  {stop \@@currentcolor\normalspace at level \the\colorlevel}%
     \global\advance\colorlevel \@@colorminus
   \fi}

\def\doglobalstopcolor
  {\csname\@@currentcolorstop\endcsname}

\let\noglobalstopcolor\relax

%D We don't use grouping and save each stop alternative. This
%D permits be especially useful in for instance local color
%D support in verbatim. Using \type{\bgroup}||\type{\egroup}
%D pairs could interfere with calling commands

%D This color mechanism takes care of nested colors, like in:
%D
%D \startbuffer
%D \color[green]{groen \color[green]{groen \color[red]{rood}} groen}
%D \color[green]{groen \color[]{groen \color[red]{rood}} groen}
%D \color[green]{groen \color[red]{rood \color[red]{rood}} groen}
%D \color[green]{groen \color[green]{groen \color[]{groen}} groen}
%D \color[green]{groen \color[red]{rood} groen}
%D \color[green]{groen \color[]{groen} groen}
%D \color[]{zwart \color[red]{rood} zwart}
%D \color[]{zwart}
%D \stopbuffer
%D
%D \typebuffer
%D
%D or
%D
%D \startvoorbeeld
%D \startlines
%D \getbuffer
%D \stoplines
%D \stopvoorbeeld
%D
%D Crossing page boundaries is of course also handled.
%D Undefined or empty color specifications are treated as
%D efficient as possible.
%D
%D \startbuffer
%D \startcolor[green]
%D   [green] \input tufte [green] \par
%D   \startcolor[]
%D     [green] \input knuth [green] \par
%D     \startcolor[red]
%D       [red] \input tufte [red] \par
%D       \startcolor[yellow]
%D         [yellow] \input knuth [yellow] \par
%D       \stopcolor
%D       [red] \input tufte [red] \par
%D     \stopcolor
%D     [green] \input knuth [green] \par
%D   \stopcolor
%D   [green] \input tufte [green] \par
%D \stopcolor
%D \stopbuffer
%D
%D \startpacked
%D \getbuffer
%D \stoppacked
%D
%D These quotes are typeset by saying:
%D
%D \typebuffer

%D We already mentioned that colors interfere with building
%D the pagebody. This means that when the page is composed,
%D the colors temporary have to be reset. After the page is
%D shipped out, we have to revive the current color.
%D
%D We use \type{\mark}s to keep track of colors across page
%D boundaries. Unfortunately standard \TEX\ supports only one mark,
%D and using this one for color support only would be a waste.
%D We therefore use an adapted version of J.~Fox's multiple mark
%D mechanism as (re|)|implemented in \module{supp-mrk}.

\doifdefinedelse{rawnewmark}
  {\rawnewmark\colormark}
  {\let\colormark\gobbleoneargument}

%D Using this mark mechanism with lots of colors has one
%D major drawback: \TEX's memory tends to overflow when
%D very colorful text is stored in a global box. Even worse is that
%D the processing time grows considerably. We therefore support
%D local as well as global color switching.
%D
%D Of the next macros, \type {\popcolor} is to be used after
%D the actual \type {\shipout} and \type {\startcolorpage} and
%D \type {\stopcolorpage} are called when entering and leaving
%D the \type {\pagebody} builder. In case of emergencies
%D \type {\pushcolor} can be used to undo the current color,
%D for instance when insertions are appended to the page.
%D
%D Out of efficiency we only use marks when needed. The next
%D macro tries to find out if indeed a mark should be set.
%D This macro uses the boolean \type {\ifinpagebody}, which can
%D be defined and set in the module that handles the pagebody.

\def\docolormark#1%
  {\iflocalcolor \else \ifinpagebody \else \ifinframed \else
     \dodocolormark{#1}%
   \fi \fi \fi}

\let\lastcolormark=\empty

\def\dodocolormark#1%
  {\edef\newcolormark{#1}%
   \ifx\newcolormark\lastcolormark\else
     \global\let\lastcolormark\newcolormark
     \@EA\rawsetmark\@EA\colormark\@EA{\lastcolormark}%
   \fi}

%D \macros
%D   {pushcolor, popcolor}
%D
%D Pushing the current state in the output routine simply comes
%D to resetting the color to black, while popping restores the
%D color state to that of before the break.

\def\topofpagecolor{\rawgetbotmark\colormark} % see postponing

\def\pushcolor
  {\stopcolormode}

\def\popcolor
  {\doifsomething{\rawgetbotmark\colormark}
     {%\debuggerinfo\m!colors{popping \getbotmark\colormark}%
      \startcolormode{\rawgetbotmark\colormark}}}

\def\popsplitcolor
  {\getsplitmarks\colormark  % hier wel
   \doifsomething{\rawgetsplitbotmark\colormark}
     {%\debuggerinfo\m!colors{split popping \getsplitbotmark\colormark}%
      \startcolormode{\rawgetsplitbotmark\colormark}}}

\appendtoks\pushcolor    \to\everypushproperties
\appendtoks\popcolor     \to\everypopproperties
\appendtoks\popsplitcolor\to\everypopsplitproperties

% Private macro: only needed in test cases (like multiple
% seperations in one file); no user command!

\def\resynccolor
  {\ifcase\pagetotal % \ifdim\pagetotal=\zeropoint
     \popcolor
   \else\ifx\@@currentcolor\empty
     \ifx\maintextcolor\empty\else
       \startcolormode\maintextcolor
     \fi
   \else
     \startcolormode\@@currentcolor
   \fi\fi}

%D \macros
%D   {startcolorpage, stopcolorpage}
%D
%D Local use can be forced with the next two macros. Nesting
%D is still supported but colors are no longer marked.
%D
%D The next implementation makes (simple) color separation more
%D easy. It also supports nested colors in page backgrounds
%D and texts.

\def\startcolorpage
  {\bgroup
   \let\@@colorplus \minusone
   \let\@@colorminus\plusone
   \let\docolormark\gobbleoneargument
   \edef\savedcolorlevel{\the\colorlevel}%
   \global\colorlevel\zerocount % before \localstartcolor of
   \ifx\maintextcolor\empty     % course, ugly bug removed
     \localstartcolor[\defaulttextcolor]%
   \else
     \localstartcolor[\maintextcolor]%
   \fi}

\def\stopcolorpage
  {\localstopcolor
   \global\colorlevel\savedcolorlevel
   \egroup}

\appendtoks \startcolorpage\to\everystarttextproperties
\prependtoks\stopcolorpage \to\everystoptextproperties

%D \macros
%D   {color,graycolor}
%D
%D This leaves the simple color command:
%D
%D \showsetup{color}
%D \showsetup{graycolor}
%D
%D Which can be used straightforward: \color[green]{green as gras}.
%D We want color support to be similar to font support and
%D therefore implement \type{\color} as:

\unexpanded\def\color[#1]%
  {\groupedcommand{\startcolor[#1]}\stopcolor}

% \let\switchtocolor\color

%D When \type {\somecolor} is issued, we can savely assume
%D grouping. Using \type {\groupedcommand} here (i.e.\ the
%D definition of \type {\color}) is unsafe because in
%D interferes with for instance switching attributes.

%D Also wrong, test in combinations: \type{...{}{\red test}}
%D
%D \def\switchtocolor[#1]%
%D   {\startcolor[#1]\aftergroup\stopcolor}

\def\switchtocolor[#1]% grouping is realy needed, else migration
  {\bgroup\startcolor[#1]\aftergroup\stopcolor\aftergroup\egroup}

\unexpanded\def\color[#1]%
  {\groupedcommand{\startcolor[#1]}\stopcolor}

\unexpanded\def\graycolor[#1]% not \gray because this is a color
  {\groupedcommand{\RGBsupportedfalse\CMYKsupportedfalse\startcolor[#1]}\stopcolor}

\let\grey\graycolor

%D This implementation enables use of defined colors like:
%D
%D \starttyping
%D Look at the {\brightgreen bright} side of life and get
%D yourself no \red{red} head!
%D \stoptyping

%D \macros
%D   {colorvalue, grayvalue}
%D
%D We can typeset the color components using \type{\colorvalue} and
%D \type{\grayvalue}. The commands:
%D
%D \startbuffer
%D color value of SomeKindOfRed: \colorvalue{SomeKindOfRed} \crlf
%D gray value of SomeKindOfRed: \grayvalue{SomeKindOfRed}
%D \stopbuffer
%D
%D \typebuffer
%D
%D show us:
%D
%D \startvoorbeeld
%D \getbuffer
%D \stopvoorbeeld
%D
%D We can speed the following macros a bit up, but this
%D hardly pays off; they are only used in the manual.

\def\realcolorformat#1%
  {\ifnum#1<\plusten      0.00\the#1\else
   \ifnum#1<\plushundred  0.0\the#1\else
   \ifnum#1<\plusthousand 0.\the#1\else
                          1.000\fi\fi\fi}

\def\colorformatseparator{ }

\def\dodoformatcolor#1%
  {\colordimen#1\points\relax
   \ifdim\colordimen>\onepoint
     \colordimen\onepoint
   \fi
   \multiply\colordimen \plusthousand
   \colorcount\colordimen
   \advance\colorcount \medcard
   \divide\colorcount \maxcard \relax
   \realcolorformat\colorcount}

\def\doformatcolorR#1:#2:#3:#4:#5\od
  {\dodoformatcolor{#1}\colorformatseparator
   \dodoformatcolor{#2}\colorformatseparator
   \dodoformatcolor{#3}}

\def\doformatcolorC#1:#2:#3:#4:#5:#6\od
  {\dodoformatcolor{#1}\colorformatseparator
   \dodoformatcolor{#2}\colorformatseparator
   \dodoformatcolor{#3}\colorformatseparator
   \dodoformatcolor{#4}}

\def\doformatcolorS#1:#2:#3\od
  {\dodoformatcolor{#1}}

\def\doformatcolor#1:%
  {\csname doformatcolor#1\endcsname}

\def\colorvalue
   {\dowithcolor\doformatcolor}

\def\doformatgrayR#1:#2:#3:#4:#5\od
  {\convertRGBtoGRAY{#1}{#2}{#3}%
   \dodoformatcolor\@@cl@@s}

\def\doformatgrayC#1:#2:#3:#4:#5:#6\od
  {\convertCMYKtoGRAY{#1}{#2}{#3}{#4}%
   \dodoformatcolor\@@cl@@s}

\def\doformatgrayS#1:#2:#3\od
  {\dodoformatcolor{#1}}

% \def\doformatgrayP#1:#2:#3:#4\od
%   {\dowithcolor\doformatcolor{#1}}

\def\doformatgrayP#1:#2:#3:#4:#5:#6\od
  {\dowithcolor\doformatcolor{#1}}

\def\doformatgray#1:%
  {\csname doformatgray#1\endcsname}

\def\grayvalue
  {\dowithcolor\doformatgray}

%D \macros
%D   {localstartraster,localstopraster,
%D    startraster,stopraster}
%D
%D The previous conversions are not linear and treat each color
%D component according to human perception curves. Pure gray
%D (we call them rasters) has equal color components. In
%D \CONTEXT\ rasters are only used as backgrounds and these
%D don't cross page boundaries in the way color does. Therefore
%D we don't need stacks and marks. Just to be compatible with
%D color support we offer both 'global' and 'local' commands.

\def\localstartraster[#1]%
  {\doifelsenothing{#1}
     {\dostartgraymode\@@rsscreen}
     {\dostartgraymode{#1}}}

\def\localstopraster
  {\dostopgraymode}

\let\startraster\localstartraster
\let\stopraster \localstopraster

%D In this documentation we will not go into too much details
%D on palets. Curious users can find more information on this
%D topic in \from[use of color].
%D
%D At the moment we implemented color in \CONTEXT\ color
%D printing was not yet on the desktop. In spite of this lack our
%D graphics designer made colorfull illustrations. When printed
%D on a black and white printer, distinctive colors can come
%D out equally gray. We therefore decided to use only colors
%D that were distinctive in colors as well as in black and
%D white print.
%D
%D Although none of the graphic packages we used supported
%D logical colors and global color redefition, we build this
%D support into \CONTEXT. This enabled us to experiment and
%D also prepared us for the future.

%D \macros
%D   {definepalet}
%D
%D Colors are grouped in palets. The colors in such a palet can
%D have colorful names, but best is to use names that specify
%D their use, like {\em important} or {\em danger}. As a sort
%D of example \CONTEXT\ has some palets predefined,
%D like:\footnote{At the time I wrote the palet support, I was
%D reading 'A hort history of time' of S.~Hawkins, so that's
%D why we stuck to quarks.}
%D
%D \starttyping
%D \definepalet
%D   [alfa]
%D   [     top=rood:7,
%D      bottom=groen:6,
%D          up=blauw:5,
%D        down=cyaan:4,
%D     strange=magenta:3,
%D       charm=geel:2]
%D \stoptyping
%D
%D It's formal definition is:
%D
%D \showsetup{definepalet}
%D
%D Visualized, such a palet looks like:
%D
%D \startbuffer[palet]
%D \showpalet [alfa] [horizontal,name,number,value]
%D \stopbuffer
%D
%D \startlinecorrection
%D \getbuffer[palet]
%D \stoplinecorrection
%D
%D This bar shows both the color and gray alternatives of the
%D palet components (not visible in black and white print).
%D
%D When needed, one can copy a palet by saying:
%D
%D \starttyping
%D \definepalet [TEXcolorpretty] [colorpretty]
%D \stoptyping
%D
%D This saves us some typing in for instance the modules that
%D deal with pretty verbatim typesetting.

\def\definepalet
  {\dodoubleargument\dodefinepalet}

\def\dodefinepalet[#1][#2]%
  {\doifassignmentelse{#2}
     {%\showmessage\m!colors6{#1}%
      \letvalue{\??pa#1}\empty
      \setevalue{\??pa\??pa#1}{#2}%
      \def\dodododefinepalet[##1=##2]%
        {\doifvaluesomething{\??pa#1}
           {\setevalue{\??pa#1}{\csname\??pa#1\endcsname,}}%
         \setevalue{\??pa#1}{\csname\??pa#1\endcsname##1}%
         \doifassignmentelse{##2}
           {% == \definepalet[test][xx={y=.4}]
            \definecolor[\??pa#1:##1][##2]%
            \iffreezecolors\@EA\setevalue\else\@EA\setvalue\fi
              {\??cr#1:##1}{\csname\??cr\??pa#1:##1\endcsname}}
           {% == \definepalet[test][xx=green]
            \doifdefinedelse{\??cr##2}
              {\iffreezecolors\@EA\setevalue\else\@EA\setvalue\fi
                 {\??cr#1:##1}{\csname\??cr##2\endcsname}}
              {\letvalue{\??cr#1:##1}\colorXpattern}}}%
      \def\dododefinepalet##1%
        {\dodododefinepalet[##1]}%
      \processcommalist[#2]\dododefinepalet}
     {\doifdefined{\??pa#2}
        {\expanded{\dodefinepalet[#1][\csname\??pa\??pa#2\endcsname]}}}}

\let\paletsize\!!zerocount

\def\getpaletsize[#1]%
  {\getcommacommandsize[\csname\??pa\??pa#1\endcsname]%
   \edef\paletsize{\number\commalistsize}}

%D Instead of refering to colors, one can also directly specify
%D a color:
%D
%D \starttyping
%D \definepalet[test][xx=green]
%D \definepalet[test][xx={y=.4}]
%D \stoptyping

%D \macros
%D   {setuppalet}
%D
%D Colors are taken from the current palet, if defined.
%D Setting the current palet is done by:
%D
%D \showsetup{setuppalet}

\let\currentpalet\empty

\def\setuppalet
  {\dosingleempty\dosetuppalet}

\def\dosetuppalet[#1]%
  {\edef\currentpalet{#1}%
   \ifx\currentpalet\empty
     % seems to be a reset
   \else\ifcsname\??pa\currentpalet\endcsname
     \edef\currentpalet{#1:}%
   \else
     \showmessage\m!colors7\currentpalet
     \let\currentpalet\empty
   \fi\fi}

%D \macros
%D   {showpalet}
%D
%D The previous visualization was typeset with:
%D
%D \typebuffer[palet]
%D
%D This commands is defined as:
%D
%D \showsetup{showpalet}

\fetchruntimecommand \showpalet {\f!colorprefix\s!run}

%D \macros
%D   {definecolorgroup}
%D
%D The naming of the colors in this palet suggests some
%D ordening, which in turn is suported by color grouping.
%D
%D \starttyping
%D \definecolorgroup
%D   [red]
%D   [1.00:0.90:0.90,
%D    1.00:0.80:0.80,
%D    1.00:0.70:0.70,
%D    1.00:0.55:0.55,
%D    1.00:0.40:0.40,
%D    1.00:0.25:0.25,
%D    1.00:0.15:0.15,
%D    0.90:0.00:0.00]
%D \stoptyping
%D
%D In such a color group colors are numbered from~$1$ to~$n$.
%D
%D \showsetup{definecolorgroup}
%D
%D This kind of specification is not only more compact than
%D defining each color separate, it also loads faster and takes
%D less bytes.

\def\definecolorgroup
  {\dotripleempty\dodefinecolorgroup}

\def\dodefinecolorgroup[#1][#2][#3]%
  {\ifthirdargument
     \processaction
       [#2]
       [    \v!cmyk=>\edef\currentcolorspace{C},
             \v!rgb=>\edef\currentcolorspace{R},
            \v!gray=>\edef\currentcolorspace{S},
            \v!spot=>\edef\currentcolorspace{P},
               \v!s=>\edef\currentcolorspace{S},
         \s!unknown=>\edef\currentcolorspace{R}]%
     \colorcount\zerocount
     \def\dododefinecolorgroup##1%
       {\advance\colorcount \plusone
        \setevalue{\??cr#1:\the\colorcount}{\currentcolorspace:##1:0:0}}%
     \processcommalist[#3]\dododefinecolorgroup
   \else
     \doifinstringelse{:}{#2}
       {\definecolorgroup[#1][\v!rgb][#2]}
       {\doloop
          {\doifdefinedelse{\??cr#2:\recurselevel}
             {\setevalue{\??cr#1:\recurselevel}%
                {\csname\??cr#2:\recurselevel\endcsname}}
             {\exitloop}}}%
   \fi}

%D \macros
%D   {showcolorgroup}
%D
%D We can show the group by:
%D
%D \startbuffer
%D \showcolorgroup [blue] [horizontal,name,number,value]
%D \stopbuffer
%D
%D \typebuffer
%D
%D or in color:
%D
%D \startlinecorrection
%D \getbuffer
%D \stoplinecorrection
%D
%D which uses:
%D
%D \showsetup{showcolorgroup}

\fetchruntimecommand \showcolorgroup {\f!colorprefix\s!run}

%D There are ten predefined color groups, like
%D \color[green]{\em groen}, \color[red]{\em rood},
%D \color[blue]{\em blauw}, \color[cyan]{\em cyaan},
%D \color[magenta]{\em magenta} and \color[yellow]{\em geel}.
%D
%D \startlinecorrection
%D \hbox to \hsize
%D   {\hss
%D    \showcolorgroup [red]    [vertical,name,number]\hss
%D    \showcolorgroup [green]   [vertical,name]\hss
%D    \showcolorgroup [blue]   [vertical,name]\hss
%D    \showcolorgroup [cyan]   [vertical,name]\hss
%D    \showcolorgroup [magenta] [vertical,name]\hss
%D    \showcolorgroup [yellow]    [vertical,name]\hss}
%D \stoplinecorrection
%D
%D These groups are used to define palets {\em alfa} upto {\em
%D zeta}. As long as we don't use colors from the same row, we
%D get ourselves distinctive palets. By activating such a palet
%D one gains access to its members {\em top} to {\em charm} (of
%D course one should use more suitable names than these).
%D
%D \startlinecorrection
%D \hbox to \hsize
%D   {\showpalet [alfa]    [vertical,name,number]\hss
%D    \showpalet [beta]    [vertical,name]\hss
%D    \showpalet [gamma]   [vertical,name]\hss
%D    \showpalet [delta]   [vertical,name]\hss
%D    \showpalet [epsilon] [vertical,name]\hss
%D    \showpalet [zeta]    [vertical,name]}
%D \stoplinecorrection
%D
%D By using the keyword \type {value} the individual color
%D components are shown too. When printed in color, these
%D showcases show both the colors and the gray value.

%D \macros
%D   {comparepalet}
%D
%D There are some more testing macros available:
%D
%D \startbuffer
%D \comparepalet [alfa]
%D \stopbuffer
%D
%D \typebuffer
%D
%D shows the palet colors against a background:
%D
%D \startlinecorrection
%D \getbuffer
%D \stoplinecorrection
%D
%D The formal definition is:
%D
%D \showsetup{comparepalet}

\fetchruntimecommand \comparepalet {\f!colorprefix\s!run}

%D \macros
%D   {comparecolorgroup}
%D
%D The similar command:
%D
%D \startbuffer
%D \comparecolorgroup [blue]
%D \stopbuffer
%D
%D \typebuffer
%D
%D shows color groups:
%D
%D \startlinecorrection
%D \getbuffer
%D \stoplinecorrection
%D
%D this commands are defined as:
%D
%D \showsetup{comparecolorgroup}

\fetchruntimecommand \comparecolorgroup {\f!colorprefix\s!run}

%D \macros
%D   {showcolor}
%D
%D But let's not forget that we also have the more traditional
%D non||related colors. These show up after:
%D
%D \starttyping
%D \showcolor [name]
%D \stoptyping
%D
%D Where \type{name} for instance can be \type{rgb}.
%D
%D \showsetup{showcolor}

\fetchruntimecommand \showcolor {\f!colorprefix\s!run}

%D It would make sense to put the following code in \type
%D {colo-mps}, but it it rather low level.

%D \macros
%D   {ifMPgraphics, ifMPcmykcolors, MPcolor}
%D
%D A very special macro is \type{\MPcolor}. This one can be
%D used to pass a \CONTEXT\ color to \METAPOST.
%D
%D \starttyping
%D \MPcolor{my own red}
%D \stoptyping
%D
%D This macro returns a \METAPOST\ triplet \type{(R,G,B)}.
%D Unless \CMYK\ color support is turned on with \type
%D {MPcmyk}, only \cap{RGB} colors and gray scales are
%D supported.

\newif\ifMPcmykcolors % \MPcmykcolorsfalse
\newif\ifMPspotcolors % \MPspotcolorsfalse

\def\scaledMPcolor#1#2%
  {\ifMPgraphics
     \handlecolorwith\doMPcolor
       \csname\??cr
         \ifcsname\??cr\currentpalet#2\endcsname\currentpalet\fi
       #2\endcsname
     :::::::\end#1\end
   \else
     #2%
   \fi}

\def\MPcolor{\scaledMPcolor1}

%D Before we had transparency available, the following
%D conversion macro was available:
%D
%D \starttyping
%D \def\doMPcolor#1:#2:#3:#4:#5:#6:#7:#8\end
%D   {\if     #1R(#2,#3,#4)%
%D    \else\if#1C\ifMPcmykcolors cmyk(#2,#3,#4,#5)\else(1-#2-#5,1-#3-#5,1-#4-#5)\fi
%D    \else\if#1S(#2,#2,#2)%
%D    \else      (0,0,0)%
%D    \fi\fi\fi}
%D \stoptyping
%D
%D In order to be useful, this macro is to be fully
%D expandabele.

\def\doMPcolor#1:% #1 can be \relax ! ! ! i.e. an empty color
  {\csname MPc\@EA\ifx\csname MPc\string#1\endcsname\relax B\else#1\fi\endcsname}

% \def\doMPcolor#1:% #1 can be \relax ! ! ! i.e. an empty color
%   {\csname MPc\ifcsname MPc#1\endcsname#1\else B\fi\endcsname}

\def\MPcR{\doMPrgb}
\def\MPcC{\ifMPcmykcolors\@EA\doMPcmykY\else\@EA\doMPcmykN\fi}
\def\MPcS{\doMPgray}
\def\MPcP{\ifMPspotcolors\@EA\doMPspotY\else\@EA\doMPspotN\fi}
\def\MPcB{\doMPblack}

\def\transparentMP {transparent}
\def\cmykMP        {scaledcmyk}
\def\cmykASrgbMP   {scaledcmykasrgb} % not really needed any more
\def\rgbMP         {scaledrgb}
\def\grayMP        {scaledgray}
\def\spotMP        {spotcolor}

\let\processMP\spotMP % for some time, will become obsolete

\def\doMPtransparent#1#2:#3:#4\end
  {\ifcase#2\space(#1)\else\transparentMP(#2,#3,(#1))\fi}

\def\doMPgray#1:#2\end#3\end
  {\doMPtransparent{\grayMP(#1,#3)}#2\end}

\def\doMPrgb#1:#2:#3:#4\end#5\end
  {\doMPtransparent{\rgbMP(#1,#2,#3,#5)}#4\end}

\def\doMPcmykY#1:#2:#3:#4:#5\end#6\end
  {\doMPtransparent{\cmykMP(#1,#2,#3,#4,#6)}#5\end}

\def\doMPcmykN#1:#2:#3:#4:#5\end#6\end
  {\doMPtransparent{\cmykASrgbMP(#1,#2,#3,#4,#6)}#5\end}

% \def\doMPspotY#1:#2:#3\end#4\end
%   {\doMPtransparent{\spotMP("#1",#2)}#3\end}
%
% \def\doMPspotN#1:#2:#3\end#4\end
%   {\scaledMPcolor{#2}{#1}}

\def\doMPspotY#1:#2:#3:#4:#5\end#6\end % best make #3 same as #1 when empty
  {\doMPtransparent{multitonecolor("#1",#2,"#3","#4")}#5\end}

\def\doMPspotN#1:#2:#3:#4:#5\end#6\end
  {\scaledMPcolor{#4}{#1}}

\def\doMPblack#1\end#2\end
  {\unknownMPcolor}

\def\unknownMPcolor
  {(0,0,0)}

%D \macros
%D   {PDFcolor,FDFcolor}
%D
%D Similar alternatives are avaliable for \PDF:

\def\PDFcolor     #1{\handlecolorwith\doPDFcolor     \csname\??cr#1\endcsname:::::::\end}
\def\PDFcolorvalue#1{\handlecolorwith\doPDFcolorvalue\csname\??cr#1\endcsname:::::::\end}
\def\FDFcolor     #1{\handlecolorwith\doFDFcolor     \csname\??cr#1\endcsname:::::::\end}

% \def\doPDFcolor#1:#2:#3:#4:#5:#6:#7:#8\end
%   {\if     #1R#2 #3 #4 rg%
%    \else\if#1C#2 #3 #4 #5 k%
%    \else\if#1S#2 g%
%    \else\if#1P#3 g% todo
%    \else       0 g%
%    \fi\fi\fi\fi}
%
% \def\doPDFcolorvalue#1:#2:#3:#4:#5:#6:#7:#8\end
%   {\if     #1R#2 #3 #4%
%    \else\if#1C#2 #3 #4 #5%
%    \else\if#1S#2%
%    \else\if#1P#3%
%    \else       0%
%    \fi\fi\fi\fi}
%
% \def\doFDFcolor#1:#2:#3:#4:#5:#6:#7:#8\end
%   {[\if     #1R#2 #3 #4%
%     \else\if#1C#2 #3 #4 #5%
%     \else\if#1S#2%
%     \else\if#1P#3% todo
%     \else       0%
%     \fi\fi\fi\fi]}

\def\doPDFcolor#1:#2:#3:#4:#5:#6:#7:#8\end
  {\if     #1R#2 #3 #4 rg%
   \else\if#1C#2 #3 #4 #5 k%
   \else\if#1S#2 g%
   \else\if#1P#5 g%
   \else       0 g%
   \fi\fi\fi\fi}

\def\doPDFcolorvalue#1:#2:#3:#4:#5:#6:#7:#8\end
  {\if     #1R#2 #3 #4%
   \else\if#1C#2 #3 #4 #5%
   \else\if#1S#2%
   \else\if#1P#5%
   \else       0%
   \fi\fi\fi\fi}

\def\doFDFcolor#1:#2:#3:#4:#5:#6:#7:#8\end
  {[\if     #1R#2 #3 #4%
    \else\if#1C#2 #3 #4 #5%
    \else\if#1S#2%
    \else\if#1P#5%
    \else       0%
    \fi\fi\fi\fi]}

% a few more obscure ones:

\def\internalspotcolorname#1{\handlecolorwith\dointernalspotcolorname\csname\??cr#1\endcsname:::::::\end}
\def\internalspotcolorsize#1{\handlecolorwith\dointernalspotcolorsize\csname\??cr#1\endcsname:::::::\end}

\def\dointernalspotcolorname#1:#2:#3:#4:#5:#6:#7:#8\end{\if#1P\ifcase0#3 #1\else#2\fi\else#1\fi}
\def\dointernalspotcolorsize#1:#2:#3:#4:#5:#6:#7:#8\end{\if#1P\ifcase0#3  0\else#3\fi\else 0\fi}

%D \macros
%D   {everyshapebox}
%D
%D A terrible hack, needed because we cannot have marks in
%D shape boxes.

\appendtoks \localcolortrue \to \everyshapebox

%D We default to the colors defined in \module{colo-rgb} and
%D support both \cap{RGB} and \cap{CMYK} output.

\setupcolors
  [\c!state=\v!stop,
   \c!conversion=\v!yes,
   \c!reduction=\v!no,
   \c!rgb=\v!yes,
   \c!cmyk=\v!yes,
   \c!spot=\v!yes,
   \c!mp\c!cmyk=\@@clcmyk,
   \c!mp\c!spot=\@@clspot,
   \c!expansion=\v!no,
   \c!textcolor=,
   \c!split=\v!no,
   \c!criterium=\v!all]

\setupcolor
  [\v!rgb]

%D For the moment we keep the next downward compatibility
%D switch, i.e.\ expanded colors. However, predefined colors
%D and palets are no longer expanded (which is what I wanted
%D in the first place).
%D
%D Well, in case we want to do color separation and use CMYK
%D colors only, this is dangerous since unwanted remapping may
%D take place. Especially when we redefine already defined
%D colors in another color space (e.g. darkgreen is
%D predefined in RGB color space, so a redefinition in CMYK
%D coordinates before RGB mode is disabled, would give
%D unexpected results due to the already frozen color spec.)
%D
%D So, from now on, colors are not frozen any more!

% \appendtoks\setupcolors[\c!expansie=\v!ja]\to\everyjob

%D The next macro is for instance used in figure splitting:

\def\doifseparatingcolorselse
  {\iffilterspotcolor
     \@EA\firstoftwoarguments
   \else\ifcase\currentcolorchannel
     \@EAEAEA\secondoftwoarguments
   \else
     \@EAEAEA\firstoftwoarguments
   \fi\fi}

\def\doifcolorchannelelse#1%
  {\doifseparatingcolorselse
     {\doifelsenothing{#1}
        \secondoftwoarguments
        {\doifelse{#1}\@@clsplit
           \firstoftwoarguments
           \secondoftwoarguments}}
     \secondoftwoarguments}

\def\resetcolorseparation
  {\filterspotcolorfalse
   \chardef\currentcolorchannel\zerocount}

%D These can be used in selecting specific files (like
%D figuredatabases).

% we already have:
%
% \def\colorsplitsuffix{\ifcase\currentcolorchannel\else-\@@clsplitsen\fi}
% \def\colorsplitprefix{\ifcase\currentcolorchannel\else\@@clsplitsen-\fi}

\def\colorchannelprefix{\doifseparatingcolorselse\@@clsplit\empty-}
\def\colorchannelsuffix{-\doifseparatingcolorselse\@@clsplit\empty}

%D As we can see, color support is turned off by default.
%D Reduction of gray colors to gray scales is turned on.

%D \macros
%D   {negatecolorcomponent,negatedcolorcomponent}
%D
%D These speak for themselves. See \type {colo-ext} for usage.

\def\negatecolorcomponent#1% #1 = \macro
  {\scratchdimen\onepoint\advance\scratchdimen-#1\onepoint
   \ifdim\scratchdimen<\zeropoint\scratchdimen\zeropoint\fi
   \edef#1{\withoutpt\the\scratchdimen}}

\let\negatedcolorcomponent\firstofoneargument

\beginETEX

\def\negatedcolorcomponent#1%
  {\ifdim\dimexpr\onepoint-#1\onepoint\relax<\zeropoint
     \!!zerocount
   \else
     \expandafter\withoutpt\the\dimexpr\onepoint-#1\onepoint\relax
   \fi}

\def\negatecolorcomponent#1% #1 = \macro
  {\edef#1{\negatedcolorcomponent{#1}}}

\endETEX

\protect \endinput