(root)/
gettext-0.22.4/
libtextstyle/
lib/
libcroco/
cr-rgb.c
       1  /* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */
       2  
       3  /* libcroco - Library for parsing and applying CSS
       4   * Copyright (C) 2006-2019 Free Software Foundation, Inc.
       5   *
       6   * This file is not part of the GNU gettext program, but is used with
       7   * GNU gettext.
       8   *
       9   * The original copyright notice is as follows:
      10   */
      11  
      12  /*
      13   * This file is part of The Croco Library
      14   *
      15   * Copyright (C) 2003-2004 Dodji Seketeli.  All Rights Reserved.
      16   *
      17   * This program is free software; you can redistribute it and/or
      18   * modify it under the terms of version 2.1 of the GNU Lesser General Public
      19   * License as published by the Free Software Foundation.
      20   *
      21   * This program is distributed in the hope that it will be useful,
      22   * but WITHOUT ANY WARRANTY; without even the implied warranty of
      23   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      24   * GNU General Public License for more details.
      25   *
      26   * You should have received a copy of the GNU Lesser General Public License
      27   * along with this program; if not, write to the Free Software
      28   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
      29   * USA
      30   * 
      31   * Author: Dodji Seketeli
      32   */
      33  
      34  #include <config.h>
      35  
      36  #include <stdio.h>
      37  #include <string.h>
      38  #include <stdlib.h>
      39  #include "cr-rgb.h"
      40  #include "cr-term.h"
      41  #include "cr-parser.h"
      42  
      43  static const CRRgb gv_standard_colors[] = {
      44          {(const guchar*)"aliceblue",   240, 248, 255, FALSE, FALSE, FALSE, {0,0,0}},
      45          {(const guchar*)"antiquewhite",        250, 235, 215, FALSE, FALSE, FALSE, {0,0,0}},
      46          {(const guchar*)"aqua",          0, 255, 255, FALSE, FALSE, FALSE, {0,0,0}},
      47          {(const guchar*)"aquamarine",  127, 255, 212, FALSE, FALSE, FALSE, {0,0,0}},
      48          {(const guchar*)"azure",       240, 255, 255, FALSE, FALSE, FALSE, {0,0,0}},
      49          {(const guchar*)"beige",       245, 245, 220, FALSE, FALSE, FALSE, {0,0,0}},
      50          {(const guchar*)"bisque",      255, 228, 196, FALSE, FALSE, FALSE, {0,0,0}},
      51          {(const guchar*)"black",         0,   0,   0, FALSE, FALSE, FALSE, {0,0,0}},
      52          {(const guchar*)"blanchedalmond",      255, 235, 205, FALSE, FALSE, FALSE, {0,0,0}},
      53          {(const guchar*)"blue",          0,   0, 255, FALSE, FALSE, FALSE, {0,0,0}},
      54          {(const guchar*)"blueviolet",  138,  43, 226, FALSE, FALSE, FALSE, {0,0,0}},
      55          {(const guchar*)"brown",       165,  42,  42, FALSE, FALSE, FALSE, {0,0,0}},
      56          {(const guchar*)"burlywood",   222, 184, 135, FALSE, FALSE, FALSE, {0,0,0}},
      57          {(const guchar*)"cadetblue",    95, 158, 160, FALSE, FALSE, FALSE, {0,0,0}},
      58          {(const guchar*)"chartreuse",  127, 255,   0, FALSE, FALSE, FALSE, {0,0,0}},
      59          {(const guchar*)"chocolate",   210, 105,  30, FALSE, FALSE, FALSE, {0,0,0}},
      60          {(const guchar*)"coral",       255, 127,  80, FALSE, FALSE, FALSE, {0,0,0}},
      61          {(const guchar*)"cornflowerblue",      100, 149, 237, FALSE, FALSE, FALSE, {0,0,0}},
      62          {(const guchar*)"cornsilk",    255, 248, 220, FALSE, FALSE, FALSE, {0,0,0}},
      63          {(const guchar*)"crimson",     220,  20,  60, FALSE, FALSE, FALSE, {0,0,0}},
      64          {(const guchar*)"cyan",          0, 255, 255, FALSE, FALSE, FALSE, {0,0,0}},
      65          {(const guchar*)"darkblue",      0,   0, 139, FALSE, FALSE, FALSE, {0,0,0}},
      66          {(const guchar*)"darkcyan",      0, 139, 139, FALSE, FALSE, FALSE, {0,0,0}},
      67          {(const guchar*)"darkgoldenrod",       184, 134,  11, FALSE, FALSE, FALSE, {0,0,0}},
      68          {(const guchar*)"darkgray",    169, 169, 169, FALSE, FALSE, FALSE, {0,0,0}},
      69          {(const guchar*)"darkgreen",     0, 100,   0, FALSE, FALSE, FALSE, {0,0,0}},
      70          {(const guchar*)"darkgrey",    169, 169, 169, FALSE, FALSE, FALSE, {0,0,0}},
      71          {(const guchar*)"darkkhaki",   189, 183, 107, FALSE, FALSE, FALSE, {0,0,0}},
      72          {(const guchar*)"darkmagenta", 139,   0, 139, FALSE, FALSE, FALSE, {0,0,0}},
      73          {(const guchar*)"darkolivegreen",       85, 107,  47, FALSE, FALSE, FALSE, {0,0,0}},
      74          {(const guchar*)"darkorange",  255, 140,   0, FALSE, FALSE, FALSE, {0,0,0}},
      75          {(const guchar*)"darkorchid",  153,  50, 204, FALSE, FALSE, FALSE, {0,0,0}},
      76          {(const guchar*)"darkred",     139,   0,   0, FALSE, FALSE, FALSE, {0,0,0}},
      77          {(const guchar*)"darksalmon",  233, 150, 122, FALSE, FALSE, FALSE, {0,0,0}},
      78          {(const guchar*)"darkseagreen",        143, 188, 143, FALSE, FALSE, FALSE, {0,0,0}},
      79          {(const guchar*)"darkslateblue",        72,  61, 139, FALSE, FALSE, FALSE, {0,0,0}},
      80          {(const guchar*)"darkslategray",        47,  79,  79, FALSE, FALSE, FALSE, {0,0,0}},
      81          {(const guchar*)"darkslategrey",        47,  79,  79, FALSE, FALSE, FALSE, {0,0,0}},
      82          {(const guchar*)"darkturquoise",         0, 206, 209, FALSE, FALSE, FALSE, {0,0,0}},
      83          {(const guchar*)"darkviolet",  148,   0, 211, FALSE, FALSE, FALSE, {0,0,0}},
      84          {(const guchar*)"deeppink",    255,  20, 147, FALSE, FALSE, FALSE, {0,0,0}},
      85          {(const guchar*)"deepskyblue",   0, 191, 255, FALSE, FALSE, FALSE, {0,0,0}},
      86          {(const guchar*)"dimgray",     105, 105, 105, FALSE, FALSE, FALSE, {0,0,0}},
      87          {(const guchar*)"dimgrey",     105, 105, 105, FALSE, FALSE, FALSE, {0,0,0}},
      88          {(const guchar*)"dodgerblue",   30, 144, 255, FALSE, FALSE, FALSE, {0,0,0}},
      89          {(const guchar*)"firebrick",   178,  34,  34, FALSE, FALSE, FALSE, {0,0,0}},
      90          {(const guchar*)"floralwhite", 255, 250, 240, FALSE, FALSE, FALSE, {0,0,0}},
      91          {(const guchar*)"forestgreen",  34, 139,  34, FALSE, FALSE, FALSE, {0,0,0}},
      92          {(const guchar*)"fuchsia",     255,   0, 255, FALSE, FALSE, FALSE, {0,0,0}},
      93          {(const guchar*)"gainsboro",   220, 220, 220, FALSE, FALSE, FALSE, {0,0,0}},
      94          {(const guchar*)"ghostwhite",  248, 248, 255, FALSE, FALSE, FALSE, {0,0,0}},
      95          {(const guchar*)"gold",        255, 215,   0, FALSE, FALSE, FALSE, {0,0,0}},
      96          {(const guchar*)"goldenrod",   218, 165,  32, FALSE, FALSE, FALSE, {0,0,0}},
      97          {(const guchar*)"gray",        128, 128, 128, FALSE, FALSE, FALSE, {0,0,0}},
      98          {(const guchar*)"green",         0, 128,   0, FALSE, FALSE, FALSE, {0,0,0}},
      99          {(const guchar*)"greenyellow", 173, 255,  47, FALSE, FALSE, FALSE, {0,0,0}},
     100          {(const guchar*)"grey",        128, 128, 128, FALSE, FALSE, FALSE, {0,0,0}},
     101          {(const guchar*)"honeydew",    240, 255, 240, FALSE, FALSE, FALSE, {0,0,0}},
     102          {(const guchar*)"hotpink",     255, 105, 180, FALSE, FALSE, FALSE, {0,0,0}},
     103          {(const guchar*)"indianred",   205,  92,  92, FALSE, FALSE, FALSE, {0,0,0}},
     104          {(const guchar*)"indigo",       75,   0, 130, FALSE, FALSE, FALSE, {0,0,0}},
     105          {(const guchar*)"ivory",       255, 255, 240, FALSE, FALSE, FALSE, {0,0,0}},
     106          {(const guchar*)"khaki",       240, 230, 140, FALSE, FALSE, FALSE, {0,0,0}},
     107          {(const guchar*)"lavender",    230, 230, 250, FALSE, FALSE, FALSE, {0,0,0}},
     108          {(const guchar*)"lavenderblush",       255, 240, 245, FALSE, FALSE, FALSE, {0,0,0}},
     109          {(const guchar*)"lawngreen",   124, 252,   0, FALSE, FALSE, FALSE, {0,0,0}},
     110          {(const guchar*)"lemonchiffon",        255, 250, 205, FALSE, FALSE, FALSE, {0,0,0}},
     111          {(const guchar*)"lightblue",   173, 216, 230, FALSE, FALSE, FALSE, {0,0,0}},
     112          {(const guchar*)"lightcoral",  240, 128, 128, FALSE, FALSE, FALSE, {0,0,0}},
     113          {(const guchar*)"lightcyan",   224, 255, 255, FALSE, FALSE, FALSE, {0,0,0}},
     114          {(const guchar*)"lightgoldenrodyellow",        250, 250, 210, FALSE, FALSE, FALSE, {0,0,0}},
     115          {(const guchar*)"lightgray",   211, 211, 211, FALSE, FALSE, FALSE, {0,0,0}},
     116          {(const guchar*)"lightgreen",  144, 238, 144, FALSE, FALSE, FALSE, {0,0,0}},
     117          {(const guchar*)"lightgrey",   211, 211, 211, FALSE, FALSE, FALSE, {0,0,0}},
     118          {(const guchar*)"lightpink",   255, 182, 193, FALSE, FALSE, FALSE, {0,0,0}},
     119          {(const guchar*)"lightsalmon", 255, 160, 122, FALSE, FALSE, FALSE, {0,0,0}},
     120          {(const guchar*)"lightseagreen",        32, 178, 170, FALSE, FALSE, FALSE, {0,0,0}},
     121          {(const guchar*)"lightskyblue",        135, 206, 250, FALSE, FALSE, FALSE, {0,0,0}},
     122          {(const guchar*)"lightslategray",      119, 136, 153, FALSE, FALSE, FALSE, {0,0,0}},
     123          {(const guchar*)"lightslategrey",      119, 136, 153, FALSE, FALSE, FALSE, {0,0,0}},
     124          {(const guchar*)"lightsteelblue",      176, 196, 222, FALSE, FALSE, FALSE, {0,0,0}},
     125          {(const guchar*)"lightyellow", 255, 255, 224, FALSE, FALSE, FALSE, {0,0,0}},
     126          {(const guchar*)"lime",          0, 255,   0, FALSE, FALSE, FALSE, {0,0,0}},
     127          {(const guchar*)"limegreen",    50, 205,  50, FALSE, FALSE, FALSE, {0,0,0}},
     128          {(const guchar*)"linen",       250, 240, 230, FALSE, FALSE, FALSE, {0,0,0}},
     129          {(const guchar*)"magenta",     255,   0, 255, FALSE, FALSE, FALSE, {0,0,0}},
     130          {(const guchar*)"maroon",      128,   0,   0, FALSE, FALSE, FALSE, {0,0,0}},
     131          {(const guchar*)"mediumaquamarine",    102, 205, 170, FALSE, FALSE, FALSE, {0,0,0}},
     132          {(const guchar*)"mediumblue",    0,   0, 205, FALSE, FALSE, FALSE, {0,0,0}},
     133          {(const guchar*)"mediumorchid",        186,  85, 211, FALSE, FALSE, FALSE, {0,0,0}},
     134          {(const guchar*)"mediumpurple",        147, 112, 219, FALSE, FALSE, FALSE, {0,0,0}},
     135          {(const guchar*)"mediumseagreen",       60, 179, 113, FALSE, FALSE, FALSE, {0,0,0}},
     136          {(const guchar*)"mediumslateblue",     123, 104, 238, FALSE, FALSE, FALSE, {0,0,0}},
     137          {(const guchar*)"mediumspringgreen",     0, 250, 154, FALSE, FALSE, FALSE, {0,0,0}},
     138          {(const guchar*)"mediumturquoise",      72, 209, 204, FALSE, FALSE, FALSE, {0,0,0}},
     139          {(const guchar*)"mediumvioletred",     199,  21, 133, FALSE, FALSE, FALSE, {0,0,0}},
     140          {(const guchar*)"midnightblue",         25,  25, 112, FALSE, FALSE, FALSE, {0,0,0}},
     141          {(const guchar*)"mintcream",   245, 255, 250, FALSE, FALSE, FALSE, {0,0,0}},
     142          {(const guchar*)"mistyrose",   255, 228, 225, FALSE, FALSE, FALSE, {0,0,0}},
     143          {(const guchar*)"moccasin",    255, 228, 181, FALSE, FALSE, FALSE, {0,0,0}},
     144          {(const guchar*)"navajowhite", 255, 222, 173, FALSE, FALSE, FALSE, {0,0,0}},
     145          {(const guchar*)"navy",          0,   0, 128, FALSE, FALSE, FALSE, {0,0,0}},
     146          {(const guchar*)"oldlace",     253, 245, 230, FALSE, FALSE, FALSE, {0,0,0}},
     147          {(const guchar*)"olive",       128, 128,   0, FALSE, FALSE, FALSE, {0,0,0}},
     148          {(const guchar*)"olivedrab",   107, 142,  35, FALSE, FALSE, FALSE, {0,0,0}},
     149          {(const guchar*)"orange",      255, 165,   0, FALSE, FALSE, FALSE, {0,0,0}},
     150          {(const guchar*)"orangered",   255,  69,   0, FALSE, FALSE, FALSE, {0,0,0}},
     151          {(const guchar*)"orchid",      218, 112, 214, FALSE, FALSE, FALSE, {0,0,0}},
     152          {(const guchar*)"palegoldenrod",       238, 232, 170, FALSE, FALSE, FALSE, {0,0,0}},
     153          {(const guchar*)"palegreen",   152, 251, 152, FALSE, FALSE, FALSE, {0,0,0}},
     154          {(const guchar*)"paleturquoise",       175, 238, 238, FALSE, FALSE, FALSE, {0,0,0}},
     155          {(const guchar*)"palevioletred",       219, 112, 147, FALSE, FALSE, FALSE, {0,0,0}},
     156          {(const guchar*)"papayawhip",  255, 239, 213, FALSE, FALSE, FALSE, {0,0,0}},
     157          {(const guchar*)"peachpuff",   255, 218, 185, FALSE, FALSE, FALSE, {0,0,0}},
     158          {(const guchar*)"peru",        205, 133,  63, FALSE, FALSE, FALSE, {0,0,0}},
     159          {(const guchar*)"pink",        255, 192, 203, FALSE, FALSE, FALSE, {0,0,0}},
     160          {(const guchar*)"plum",        221, 160, 221, FALSE, FALSE, FALSE, {0,0,0}},
     161          {(const guchar*)"powderblue",  176, 224, 230, FALSE, FALSE, FALSE, {0,0,0}},
     162          {(const guchar*)"purple",      128,   0, 128, FALSE, FALSE, FALSE, {0,0,0}},
     163          {(const guchar*)"red",         255,   0,   0, FALSE, FALSE, FALSE, {0,0,0}},
     164          {(const guchar*)"rosybrown",   188, 143, 143, FALSE, FALSE, FALSE, {0,0,0}},
     165          {(const guchar*)"royalblue",    65, 105, 225, FALSE, FALSE, FALSE, {0,0,0}},
     166          {(const guchar*)"saddlebrown", 139,  69,  19, FALSE, FALSE, FALSE, {0,0,0}},
     167          {(const guchar*)"salmon",      250, 128, 114, FALSE, FALSE, FALSE, {0,0,0}},
     168          {(const guchar*)"sandybrown",  244, 164,  96, FALSE, FALSE, FALSE, {0,0,0}},
     169          {(const guchar*)"seagreen",     46, 139,  87, FALSE, FALSE, FALSE, {0,0,0}},
     170          {(const guchar*)"seashell",    255, 245, 238, FALSE, FALSE, FALSE, {0,0,0}},
     171          {(const guchar*)"sienna",      160,  82,  45, FALSE, FALSE, FALSE, {0,0,0}},
     172          {(const guchar*)"silver",      192, 192, 192, FALSE, FALSE, FALSE, {0,0,0}},
     173          {(const guchar*)"skyblue",     135, 206, 235, FALSE, FALSE, FALSE, {0,0,0}},
     174          {(const guchar*)"slateblue",   106,  90, 205, FALSE, FALSE, FALSE, {0,0,0}},
     175          {(const guchar*)"slategray",   112, 128, 144, FALSE, FALSE, FALSE, {0,0,0}},
     176          {(const guchar*)"slategrey",   112, 128, 144, FALSE, FALSE, FALSE, {0,0,0}},
     177          {(const guchar*)"snow",        255, 250, 250, FALSE, FALSE, FALSE, {0,0,0}},
     178          {(const guchar*)"springgreen",   0, 255, 127, FALSE, FALSE, FALSE, {0,0,0}},
     179          {(const guchar*)"steelblue",    70, 130, 180, FALSE, FALSE, FALSE, {0,0,0}},
     180          {(const guchar*)"tan",         210, 180, 140, FALSE, FALSE, FALSE, {0,0,0}},
     181          {(const guchar*)"teal",          0, 128, 128, FALSE, FALSE, FALSE, {0,0,0}},
     182          {(const guchar*)"thistle",     216, 191, 216, FALSE, FALSE, FALSE, {0,0,0}},
     183          {(const guchar*)"tomato",      255,  99,  71, FALSE, FALSE, FALSE, {0,0,0}},
     184          {(const guchar*)"transparent", 255, 255, 255, FALSE, FALSE, TRUE, {0,0,0}},
     185          {(const guchar*)"turquoise",    64, 224, 208, FALSE, FALSE, FALSE, {0,0,0}},
     186          {(const guchar*)"violet",      238, 130, 238, FALSE, FALSE, FALSE, {0,0,0}},
     187          {(const guchar*)"wheat",       245, 222, 179, FALSE, FALSE, FALSE, {0,0,0}},
     188          {(const guchar*)"white",       255, 255, 255, FALSE, FALSE, FALSE, {0,0,0}},
     189          {(const guchar*)"whitesmoke",  245, 245, 245, FALSE, FALSE, FALSE, {0,0,0}},
     190          {(const guchar*)"yellow",      255, 255,   0, FALSE, FALSE, FALSE, {0,0,0}},
     191          {(const guchar*)"yellowgreen", 154, 205,  50, FALSE, FALSE, FALSE, {0,0,0}}
     192  };
     193  
     194  /**
     195   * cr_rgb_new:
     196   *
     197   *The default constructor of #CRRgb.
     198   *
     199   *Returns the newly built instance of #CRRgb
     200   */
     201  CRRgb *
     202  cr_rgb_new (void)
     203  {
     204          CRRgb *result = NULL;
     205  
     206          result = g_try_malloc (sizeof (CRRgb));
     207  
     208          if (result == NULL) {
     209                  cr_utils_trace_info ("No more memory");
     210                  return NULL;
     211          }
     212  
     213          memset (result, 0, sizeof (CRRgb));
     214  
     215          return result;
     216  }
     217  
     218  /**
     219   * cr_rgb_new_with_vals:
     220   *@a_red: the red component of the color.
     221   *@a_green: the green component of the color.
     222   *@a_blue: the blue component of the color.
     223   *@a_unit: the unit of the rgb values.
     224   *(either percentage or integer values)
     225   *
     226   *A constructor of #CRRgb.
     227   *
     228   *Returns the newly built instance of #CRRgb.
     229   */
     230  CRRgb *
     231  cr_rgb_new_with_vals (gulong a_red, gulong a_green,
     232                        gulong a_blue, gboolean a_is_percentage)
     233  {
     234          CRRgb *result = NULL;
     235  
     236          result = cr_rgb_new ();
     237  
     238          g_return_val_if_fail (result, NULL);
     239  
     240          result->red = a_red;
     241          result->green = a_green;
     242          result->blue = a_blue;
     243          result->is_percentage = a_is_percentage;
     244  
     245          return result;
     246  }
     247  
     248  /**
     249   * cr_rgb_to_string:
     250   *@a_this: the instance of #CRRgb to serialize.
     251   *
     252   *Serializes the rgb into a zero terminated string.
     253   *
     254   *Returns the zero terminated string containing the serialized
     255   *rgb. MUST BE FREED by the caller using g_free().
     256   */
     257  guchar *
     258  cr_rgb_to_string (CRRgb const * a_this)
     259  {
     260          guchar *result = NULL;
     261          GString *str_buf = NULL;
     262  
     263          str_buf = g_string_new (NULL);
     264          g_return_val_if_fail (str_buf, NULL);
     265  
     266          if (a_this->is_percentage == 1) {
     267                  g_string_append_printf (str_buf, "%ld", a_this->red);
     268  
     269                  g_string_append (str_buf, "%, ");
     270  
     271                  g_string_append_printf (str_buf, "%ld", a_this->green);
     272                  g_string_append (str_buf, "%, ");
     273  
     274                  g_string_append_printf (str_buf, "%ld", a_this->blue);
     275                  g_string_append_c (str_buf, '%');
     276          } else {
     277                  g_string_append_printf (str_buf, "%ld", a_this->red);
     278                  g_string_append (str_buf, ", ");
     279  
     280                  g_string_append_printf (str_buf, "%ld", a_this->green);
     281                  g_string_append (str_buf, ", ");
     282  
     283                  g_string_append_printf (str_buf, "%ld", a_this->blue);
     284          }
     285  
     286          if (str_buf) {
     287                  result = (guchar *) str_buf->str;
     288                  g_string_free (str_buf, FALSE);
     289          }
     290  
     291          return result;
     292  }
     293  
     294  /**
     295   * cr_rgb_dump:
     296   *@a_this: the "this pointer" of
     297   *the current instance of #CRRgb.
     298   *@a_fp: the destination file pointer.
     299   *
     300   *Dumps the current instance of #CRRgb
     301   *to a file.
     302   */
     303  void
     304  cr_rgb_dump (CRRgb const * a_this, FILE * a_fp)
     305  {
     306          guchar *str = NULL;
     307  
     308          g_return_if_fail (a_this);
     309  
     310          str = cr_rgb_to_string (a_this);
     311  
     312          if (str) {
     313                  fprintf (a_fp, "%s", str);
     314                  g_free (str);
     315                  str = NULL;
     316          }
     317  }
     318  
     319  /**
     320   * cr_rgb_compute_from_percentage:
     321   *@a_this: the current instance of #CRRgb
     322   *
     323   *If the rgb values are expressed in percentage,
     324   *compute their real value.
     325   *
     326   *Returns CR_OK upon successful completion, an error code otherwise.
     327   */
     328  enum CRStatus
     329  cr_rgb_compute_from_percentage (CRRgb * a_this)
     330  {
     331          g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
     332  
     333          if (a_this->is_percentage == FALSE)
     334                  return CR_OK;
     335          a_this->red = a_this->red * 255 / 100;
     336          a_this->green = a_this->green * 255 / 100;
     337          a_this->blue = a_this->blue * 255 / 100;
     338          a_this->is_percentage = FALSE;
     339          return CR_OK;
     340  }
     341  
     342  /**
     343   * cr_rgb_set:
     344   *@a_this: the current instance of #CRRgb.
     345   *@a_red: the red value.
     346   *@a_green: the green value.
     347   *@a_blue: the blue value.
     348   *
     349   *Sets rgb values to the RGB.
     350   *
     351   *Returns CR_OK upon successful completion, an error code
     352   *otherwise.
     353   */
     354  enum CRStatus
     355  cr_rgb_set (CRRgb * a_this, gulong a_red,
     356              gulong a_green, gulong a_blue, gboolean a_is_percentage)
     357  {
     358          g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
     359          if (a_is_percentage != FALSE) {
     360                  g_return_val_if_fail (a_red <= 100
     361                                        && a_green <= 100
     362                                        && a_blue <= 100, CR_BAD_PARAM_ERROR);
     363          }
     364  
     365          a_this->is_percentage = a_is_percentage;
     366  
     367          a_this->red = a_red;
     368          a_this->green = a_green;
     369          a_this->blue = a_blue;
     370          a_this->inherit = FALSE ;
     371          a_this->is_transparent = FALSE ;
     372          return CR_OK;
     373  }
     374  
     375  /**
     376   * cr_rgb_set_to_inherit:
     377   *@a_this: the current instance of #CRRgb
     378   *
     379   *sets the value of the rgb to inherit.
     380   *Look at the css spec from chapter 6.1 to 6.2 to understand
     381   *the meaning of "inherit".
     382   *
     383   * Returns CR_OK upon succesful completion, an error code otherwise.
     384   */
     385  enum CRStatus 
     386  cr_rgb_set_to_inherit (CRRgb *a_this, gboolean a_inherit)
     387  {
     388          g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR) ;
     389  
     390          a_this->inherit = a_inherit ;
     391  
     392          return CR_OK ;
     393  }
     394  
     395  /**
     396   * cr_rgb_is_set_to_inherit:
     397   *
     398   * @a_this: the current instance of #CRRgb.
     399   *
     400   * Returns TRUE if the rgb is set to the value "inherit", FALSE otherwise.
     401   */
     402  gboolean
     403  cr_rgb_is_set_to_inherit (CRRgb const *a_this)
     404  {
     405          g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR) ;
     406  
     407          return a_this->inherit ;
     408  }
     409  
     410  /**
     411   * cr_rgb_is_set_to_transparent:
     412   *@a_this: the current instance of
     413   *#CRRgb
     414   *
     415   *Tests if the the rgb is set to the
     416   *value "transparent" or not.
     417   *
     418   *Returns TRUE if the rgb has been set to
     419   *transparent, FALSE otherwise.
     420   */
     421  gboolean 
     422  cr_rgb_is_set_to_transparent (CRRgb const *a_this)
     423  {
     424          g_return_val_if_fail (a_this, FALSE) ;
     425          return a_this->is_transparent ;
     426  }
     427  
     428  
     429  /**
     430   * cr_rgb_set_to_transparent:
     431   *@a_this: the current instance of #CRRgb
     432   *@a_is_transparent: set to transparent or not.
     433   *
     434   *Sets the rgb to the "transparent" value (or not)
     435   *Returns CR_OK upon successfull completion, an error code otherwise.
     436   */
     437  enum CRStatus 
     438  cr_rgb_set_to_transparent (CRRgb *a_this, 
     439                             gboolean a_is_transparent)
     440  {
     441          g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR) ;        
     442          a_this->is_transparent = a_is_transparent ;
     443          return CR_OK ;
     444  }
     445  
     446  /**
     447   * cr_rgb_set_from_rgb:
     448   *@a_this: the current instance of #CRRgb.
     449   *@a_rgb: the rgb to "copy"
     450   *
     451   *Sets the rgb from an other one.
     452   *
     453   *Returns CR_OK upon successful completion, an error code otherwise.
     454   */
     455  enum CRStatus
     456  cr_rgb_set_from_rgb (CRRgb * a_this, CRRgb const * a_rgb)
     457  {
     458          g_return_val_if_fail (a_this && a_rgb, CR_BAD_PARAM_ERROR);
     459  
     460          cr_rgb_copy (a_this, a_rgb) ;
     461  
     462          return CR_OK;
     463  }
     464  
     465  static int
     466  cr_rgb_color_name_compare (const void *a,
     467                             const void *b)
     468  {
     469          const char *a_color_name = a;
     470          const CRRgb *rgb = b;
     471  
     472          return g_ascii_strcasecmp (a_color_name, (const char *) rgb->name);
     473  }
     474  
     475  /**
     476   * cr_rgb_set_from_name:
     477   * @a_this: the current instance of #CRRgb
     478   * @a_color_name: the color name
     479   *
     480   * Returns CR_OK upon successful completion, an error code otherwise.
     481   */
     482  enum CRStatus
     483  cr_rgb_set_from_name (CRRgb * a_this, const guchar * a_color_name)
     484  {
     485          enum CRStatus status = CR_OK;
     486          CRRgb *result;
     487  
     488          g_return_val_if_fail (a_this && a_color_name, CR_BAD_PARAM_ERROR);
     489  
     490          result = bsearch (a_color_name,
     491                            gv_standard_colors,
     492                            G_N_ELEMENTS (gv_standard_colors),
     493                            sizeof (gv_standard_colors[0]),
     494                            cr_rgb_color_name_compare);
     495          if (result != NULL)
     496                  cr_rgb_set_from_rgb (a_this, result);
     497          else
     498                 status = CR_UNKNOWN_TYPE_ERROR;
     499  
     500          return status;
     501  }
     502  
     503  /**
     504   * cr_rgb_set_from_hex_str:
     505   * @a_this: the current instance of #CRRgb
     506   * @a_hex: the hexadecimal value to set.
     507   *
     508   * Returns CR_OK upon successful completion.
     509   */
     510  enum CRStatus
     511  cr_rgb_set_from_hex_str (CRRgb * a_this, const guchar * a_hex)
     512  {
     513          enum CRStatus status = CR_OK;
     514          gulong i = 0;
     515          guchar colors[3] = { 0 };
     516  
     517          g_return_val_if_fail (a_this && a_hex, CR_BAD_PARAM_ERROR);
     518  
     519          if (strlen ((const char *) a_hex) == 3) {
     520                  for (i = 0; i < 3; i++) {
     521                          if (a_hex[i] >= '0' && a_hex[i] <= '9') {
     522                                  colors[i] = a_hex[i] - '0';
     523                                  colors[i] = (colors[i] << 4) | colors[i];
     524                          } else if (a_hex[i] >= 'a' && a_hex[i] <= 'z') {
     525                                  colors[i] = 10 + a_hex[i] - 'a';
     526                                  colors[i] = (colors[i] << 4) | colors[i];
     527                          } else if (a_hex[i] >= 'A' && a_hex[i] <= 'Z') {
     528                                  colors[i] = 10 + a_hex[i] - 'A';
     529                                  colors[i] = (colors[i] << 4) | colors[i];
     530                          } else {
     531                                  status = CR_UNKNOWN_TYPE_ERROR;
     532                          }
     533                  }
     534          } else if (strlen ((const char *) a_hex) == 6) {
     535                  for (i = 0; i < 6; i++) {
     536                          if (a_hex[i] >= '0' && a_hex[i] <= '9') {
     537                                  colors[i / 2] <<= 4;
     538                                  colors[i / 2] |= a_hex[i] - '0';
     539                                  status = CR_OK;
     540                          } else if (a_hex[i] >= 'a' && a_hex[i] <= 'z') {
     541                                  colors[i / 2] <<= 4;
     542                                  colors[i / 2] |= 10 + a_hex[i] - 'a';
     543                                  status = CR_OK;
     544                          } else if (a_hex[i] >= 'A' && a_hex[i] <= 'Z') {
     545                                  colors[i / 2] <<= 4;
     546                                  colors[i / 2] |= 10 + a_hex[i] - 'A';
     547                                  status = CR_OK;
     548                          } else {
     549                                  status = CR_UNKNOWN_TYPE_ERROR;
     550                          }
     551                  }
     552          } else {
     553                  status = CR_UNKNOWN_TYPE_ERROR;
     554          }
     555  
     556          if (status == CR_OK) {
     557                  status = cr_rgb_set (a_this, colors[0],
     558                                       colors[1], colors[2], FALSE);
     559                  cr_rgb_set_to_transparent (a_this, FALSE) ;
     560          }
     561          return status;
     562  }
     563  
     564  /**
     565   * cr_rgb_set_from_term:
     566   *@a_this: the instance of #CRRgb to set
     567   *@a_value: the terminal from which to set
     568   *
     569   *Set the rgb from a terminal symbol
     570   *
     571   * Returns CR_OK upon successful completion, an error code otherwise.
     572   */
     573  enum CRStatus
     574  cr_rgb_set_from_term (CRRgb *a_this, const struct _CRTerm *a_value)
     575  {
     576          enum CRStatus status = CR_OK ;
     577          g_return_val_if_fail (a_this && a_value,
     578                                CR_BAD_PARAM_ERROR) ;
     579  
     580  	switch(a_value->type) {
     581  	case TERM_RGB:
     582                  if (a_value->content.rgb) {
     583                          cr_rgb_set_from_rgb
     584                                  (a_this, a_value->content.rgb) ;
     585                  }
     586  		break ;
     587  	case TERM_IDENT:
     588                  if (a_value->content.str
     589                      && a_value->content.str->stryng
     590                      && a_value->content.str->stryng->str) {
     591  			if (!strncmp ("inherit",
     592                                        a_value->content.str->stryng->str,
     593                                        sizeof ("inherit")-1)) {
     594  				a_this->inherit = TRUE;
     595                                  a_this->is_transparent = FALSE ;
     596  			} else  {
     597                          	status = cr_rgb_set_from_name
     598                                          (a_this,
     599                                           (const guchar *) a_value->content.str->stryng->str) ;
     600  			}
     601                  } else {
     602                          cr_utils_trace_info 
     603                                  ("a_value has NULL string value") ;
     604                  }
     605  		break ;
     606  	case TERM_HASH:
     607                  if (a_value->content.str
     608                      && a_value->content.str->stryng
     609                      && a_value->content.str->stryng->str) {
     610                          status = cr_rgb_set_from_hex_str
     611                                  (a_this, 
     612                                   (const guchar *) a_value->content.str->stryng->str) ;
     613                  } else {
     614                          cr_utils_trace_info
     615                                  ("a_value has NULL string value") ;
     616                  }
     617                  break ;
     618  	default:
     619                  status =  CR_UNKNOWN_TYPE_ERROR ;
     620  	}
     621          return status ;
     622  }
     623  
     624  enum CRStatus 
     625  cr_rgb_copy (CRRgb *a_dest, CRRgb const *a_src)
     626  {
     627          g_return_val_if_fail (a_dest && a_src,
     628                                CR_BAD_PARAM_ERROR) ;
     629  
     630          memcpy (a_dest, a_src, sizeof (CRRgb)) ;
     631          return CR_OK ;
     632  }
     633  
     634  /**
     635   * cr_rgb_destroy:
     636   *@a_this: the "this pointer" of the
     637   *current instance of #CRRgb.
     638   *
     639   *Destructor of #CRRgb.
     640   */
     641  void
     642  cr_rgb_destroy (CRRgb * a_this)
     643  {
     644          g_return_if_fail (a_this);
     645          g_free (a_this);
     646  }
     647  
     648  /**
     649   * cr_rgb_parse_from_buf:
     650   *@a_str: a string that contains a color description
     651   *@a_enc: the encoding of a_str
     652   *
     653   *Parses a text buffer that contains a rgb color
     654   *
     655   *Returns the parsed color, or NULL in case of error
     656   */
     657  CRRgb *
     658  cr_rgb_parse_from_buf (const guchar *a_str,
     659                                enum CREncoding a_enc)
     660  {
     661  	enum CRStatus status = CR_OK ;
     662  	CRTerm *value = NULL ;
     663  	CRParser * parser = NULL;
     664  	CRRgb *result = NULL;
     665  	
     666  	g_return_val_if_fail (a_str, NULL);
     667  	
     668  	parser = cr_parser_new_from_buf ((guchar *) a_str, strlen ((const char *) a_str), a_enc, FALSE);
     669  
     670  	g_return_val_if_fail (parser, NULL);
     671  
     672  	status = cr_parser_try_to_skip_spaces_and_comments (parser) ;
     673  	if (status != CR_OK)
     674  	    	goto cleanup;
     675  
     676  	status = cr_parser_parse_term (parser, &value);
     677  	if (status != CR_OK)
     678  	    	goto cleanup;
     679  
     680  	result = cr_rgb_new ();
     681  	if (!result)
     682  	    	goto cleanup;
     683  
     684  	status = cr_rgb_set_from_term (result, value);
     685  
     686  cleanup:
     687  	if (parser) {
     688  	    	cr_parser_destroy (parser);
     689  		parser = NULL;
     690  	}
     691  	if (value) {
     692  	    	cr_term_destroy(value);
     693  		value = NULL;
     694  	}
     695  	return result ;
     696  }
     697