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