Imported Upstream version 0.18.1.1
[platform/upstream/gettext.git] / gnulib-local / lib / libcroco / cr-style.c
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 
8  * the GNU Lesser General Public
9  * License as published by the Free Software Foundation.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the 
17  * GNU Lesser General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
20  * USA
21  *
22  * Author: Dodji Seketeli.
23  * see COPYRIGTHS file for copyright information
24  */
25
26 #include <config.h>
27 #include <string.h>
28 #include "cr-style.h"
29
30 /**
31  *@file
32  *The definition of the #CRStyle class.
33  */
34
35 /**
36  *A property ID.
37  *Each supported css property has an ID which is
38  *an entry into a property "population" jump table.
39  *each entry of the property population jump table
40  *contains code to tranform the literal form of
41  *a property value into a strongly typed value.
42  */
43 enum CRPropertyID {
44         PROP_ID_NOT_KNOWN = 0,
45         PROP_ID_PADDING_TOP,
46         PROP_ID_PADDING_RIGHT,
47         PROP_ID_PADDING_BOTTOM,
48         PROP_ID_PADDING_LEFT,
49         PROP_ID_PADDING,
50         PROP_ID_BORDER_TOP_WIDTH,
51         PROP_ID_BORDER_RIGHT_WIDTH,
52         PROP_ID_BORDER_BOTTOM_WIDTH,
53         PROP_ID_BORDER_LEFT_WIDTH,
54         PROP_ID_BORDER_WIDTH,
55         PROP_ID_BORDER_TOP_STYLE,
56         PROP_ID_BORDER_RIGHT_STYLE,
57         PROP_ID_BORDER_BOTTOM_STYLE,
58         PROP_ID_BORDER_LEFT_STYLE,
59         PROP_ID_BORDER_STYLE,
60         PROP_ID_BORDER_TOP_COLOR,
61         PROP_ID_BORDER_RIGHT_COLOR,
62         PROP_ID_BORDER_BOTTOM_COLOR,
63         PROP_ID_BORDER_LEFT_COLOR,
64         PROP_ID_BORDER_TOP,
65         PROP_ID_BORDER_RIGHT,
66         PROP_ID_BORDER_BOTTOM,
67         PROP_ID_BORDER_LEFT,
68         PROP_ID_BORDER,
69         PROP_ID_MARGIN_TOP,
70         PROP_ID_MARGIN_RIGHT,
71         PROP_ID_MARGIN_BOTTOM,
72         PROP_ID_MARGIN_LEFT,
73         PROP_ID_MARGIN,
74         PROP_ID_DISPLAY,
75         PROP_ID_POSITION,
76         PROP_ID_TOP,
77         PROP_ID_RIGHT,
78         PROP_ID_BOTTOM,
79         PROP_ID_LEFT,
80         PROP_ID_FLOAT,
81         PROP_ID_WIDTH,
82         PROP_ID_COLOR,
83         PROP_ID_BACKGROUND_COLOR,
84         PROP_ID_FONT_FAMILY,
85         PROP_ID_FONT_SIZE,
86         PROP_ID_FONT_STYLE,
87         PROP_ID_FONT_WEIGHT,
88         PROP_ID_WHITE_SPACE,
89         /*should be the last one. */
90         NB_PROP_IDS
91 };
92
93 typedef struct _CRPropertyDesc CRPropertyDesc;
94
95 struct _CRPropertyDesc {
96         const guchar *name;
97         enum CRPropertyID prop_id;
98 };
99
100 static CRPropertyDesc gv_prop_table[] = {
101         {"padding-top", PROP_ID_PADDING_TOP},
102         {"padding-right", PROP_ID_PADDING_RIGHT},
103         {"padding-bottom", PROP_ID_PADDING_BOTTOM},
104         {"padding-left", PROP_ID_PADDING_LEFT},
105         {"padding", PROP_ID_PADDING},
106         {"border-top-width", PROP_ID_BORDER_TOP_WIDTH},
107         {"border-right-width", PROP_ID_BORDER_RIGHT_WIDTH},
108         {"border-bottom-width", PROP_ID_BORDER_BOTTOM_WIDTH},
109         {"border-left-width", PROP_ID_BORDER_LEFT_WIDTH},
110         {"border-width", PROP_ID_BORDER_WIDTH},
111         {"border-top-style", PROP_ID_BORDER_TOP_STYLE},
112         {"border-right-style", PROP_ID_BORDER_RIGHT_STYLE},
113         {"border-bottom-style", PROP_ID_BORDER_BOTTOM_STYLE},
114         {"border-left-style", PROP_ID_BORDER_LEFT_STYLE},
115         {"border-style", PROP_ID_BORDER_STYLE},
116         {"border-top", PROP_ID_BORDER_TOP},
117         {"border-right", PROP_ID_BORDER_RIGHT},
118         {"border-bottom", PROP_ID_BORDER_BOTTOM},
119         {"border-left", PROP_ID_BORDER_LEFT},
120         {"border", PROP_ID_BORDER},
121         {"margin-top", PROP_ID_MARGIN_TOP},
122         {"margin-right", PROP_ID_MARGIN_RIGHT},
123         {"margin-bottom", PROP_ID_MARGIN_BOTTOM},
124         {"margin-left", PROP_ID_MARGIN_LEFT},
125         {"margin", PROP_ID_MARGIN},
126         {"display", PROP_ID_DISPLAY},
127         {"position", PROP_ID_POSITION},
128         {"top", PROP_ID_TOP},
129         {"right", PROP_ID_RIGHT},
130         {"bottom", PROP_ID_BOTTOM},
131         {"left", PROP_ID_LEFT},
132         {"float", PROP_ID_FLOAT},
133         {"width", PROP_ID_WIDTH},
134         {"color", PROP_ID_COLOR},
135         {"border-top-color", PROP_ID_BORDER_TOP_COLOR},
136         {"border-right-color", PROP_ID_BORDER_RIGHT_COLOR},
137         {"border-bottom-color", PROP_ID_BORDER_BOTTOM_COLOR},
138         {"border-left-color", PROP_ID_BORDER_LEFT_COLOR},
139         {"background-color", PROP_ID_BACKGROUND_COLOR},
140         {"font-family", PROP_ID_FONT_FAMILY},
141         {"font-size", PROP_ID_FONT_SIZE},
142         {"font-style", PROP_ID_FONT_STYLE},
143         {"font-weight", PROP_ID_FONT_WEIGHT},
144         {"white-space", PROP_ID_WHITE_SPACE},
145         /*must be the last one */
146         {NULL, 0}
147 };
148
149 /**
150  *A the key/value pair of this hash table
151  *are:
152  *key => name of the the css propertie found in gv_prop_table
153  *value => matching property id found in gv_prop_table.
154  *So this hash table is here just to retrieval of a property id
155  *from a property name.
156  */
157 static GHashTable *gv_prop_hash = NULL;
158
159 /**
160  *incremented by each new instance of #CRStyle
161  *and decremented at the it destroy time.
162  *When this reaches zero, gv_prop_hash is destroyed.
163  */
164 static gulong gv_prop_hash_ref_count = 0;
165
166 struct CRNumPropEnumDumpInfo {
167         enum CRNumProp code;
168         const gchar *str;
169 };
170
171 static struct CRNumPropEnumDumpInfo gv_num_props_dump_infos[] = {
172         {NUM_PROP_TOP, "top"},
173         {NUM_PROP_RIGHT, "right"},
174         {NUM_PROP_BOTTOM, "bottom"},
175         {NUM_PROP_LEFT, "left"},
176         {NUM_PROP_PADDING_TOP, "padding-top"},
177         {NUM_PROP_PADDING_RIGHT, "padding-right"},
178         {NUM_PROP_PADDING_BOTTOM, "padding-bottom"},
179         {NUM_PROP_PADDING_LEFT, "padding-left"},
180         {NUM_PROP_BORDER_TOP, "border-top"},
181         {NUM_PROP_BORDER_RIGHT, "border-right"},
182         {NUM_PROP_BORDER_BOTTOM, "border-bottom"},
183         {NUM_PROP_BORDER_LEFT, "border-left"},
184         {NUM_PROP_MARGIN_TOP, "margin-top"},
185         {NUM_PROP_MARGIN_RIGHT, "margin-right"},
186         {NUM_PROP_MARGIN_BOTTOM, "margin-bottom"},
187         {NUM_PROP_MARGIN_LEFT, "margin-left"},
188         {NUM_PROP_WIDTH, "width"},
189         {0, NULL}
190 };
191
192 struct CRRgbPropEnumDumpInfo {
193         enum CRRgbProp code;
194         const gchar *str;
195 };
196
197 static struct CRRgbPropEnumDumpInfo gv_rgb_props_dump_infos[] = {
198         {RGB_PROP_BORDER_TOP_COLOR, "border-top-color"},
199         {RGB_PROP_BORDER_RIGHT_COLOR, "border-right-color"},
200         {RGB_PROP_BORDER_BOTTOM_COLOR, "bottom-color"},
201         {RGB_PROP_BORDER_LEFT_COLOR, "left-color"},
202         {RGB_PROP_COLOR, "color"},
203         {RGB_PROP_BACKGROUND_COLOR, "background-color"},
204         {0, NULL}
205 };
206
207 struct CRBorderStylePropEnumDumpInfo {
208         enum CRBorderStyleProp code;
209         const gchar *str;
210
211 };
212
213 static struct CRBorderStylePropEnumDumpInfo gv_border_style_props_dump_infos[]
214         = {
215         {BORDER_STYLE_PROP_TOP, "border-style-top"},
216         {BORDER_STYLE_PROP_RIGHT, "border-style-right"},
217         {BORDER_STYLE_PROP_BOTTOM, "boder-style-bottom"},
218         {BORDER_STYLE_PROP_LEFT, "border-style-left"},
219         {0, NULL}
220 };
221
222 static enum CRStatus
223   cr_style_init_properties (void);
224
225 enum CRDirection {
226         DIR_TOP = 0,
227         DIR_RIGHT,
228         DIR_BOTTOM,
229         DIR_LEFT,
230
231         /*must be the last one */
232         NB_DIRS
233 };
234
235 static const gchar *num_prop_code_to_string (enum CRNumProp a_code);
236
237 static const gchar *rgb_prop_code_to_string (enum CRRgbProp a_code);
238
239 static const gchar *border_style_prop_code_to_string (enum CRBorderStyleProp
240                                                       a_code);
241
242 static enum CRStatus
243 set_prop_padding_x_from_value (CRStyle * a_style,
244                                  CRTerm * a_value, enum CRDirection a_dir);
245
246 static enum CRStatus
247 set_prop_border_x_width_from_value (CRStyle * a_style,
248                                     CRTerm * a_value,
249                                     enum CRDirection a_dir);
250 static enum CRStatus
251 set_prop_border_width_from_value (CRStyle *a_style,
252                                   CRTerm *a_value) ;
253
254 static enum CRStatus
255 set_prop_border_x_style_from_value (CRStyle * a_style,
256                                     CRTerm * a_value,
257                                     enum CRDirection a_dir);
258 static enum CRStatus
259 set_prop_border_style_from_value (CRStyle *a_style,
260                                   CRTerm *a_value) ;
261
262 static enum CRStatus
263 set_prop_margin_x_from_value (CRStyle * a_style, CRTerm * a_value,
264                                 enum CRDirection a_dir);
265
266 static enum CRStatus
267 set_prop_display_from_value (CRStyle * a_style, CRTerm * a_value);
268
269 static enum CRStatus
270 set_prop_position_from_value (CRStyle * a_style, CRTerm * a_value);
271
272 static enum CRStatus
273 set_prop_x_from_value (CRStyle * a_style, CRTerm * a_value,
274                          enum CRDirection a_dir);
275
276 static enum CRStatus
277 set_prop_float (CRStyle * a_style, CRTerm * a_value);
278
279 static enum CRStatus
280 set_prop_width (CRStyle * a_style, CRTerm * a_value);
281
282 static enum CRStatus
283 set_prop_color (CRStyle * a_style, CRTerm * a_value);
284
285 static enum CRStatus
286 set_prop_background_color (CRStyle * a_style, CRTerm * a_value);
287
288 static enum CRStatus
289 set_prop_border_x_color_from_value (CRStyle * a_style, CRTerm * a_value,
290                                       enum CRDirection a_dir);
291
292 static enum CRStatus
293 set_prop_border_x_from_value (CRStyle * a_style, CRTerm * a_value,
294                                 enum CRDirection a_dir);
295
296 static enum CRStatus
297 set_prop_border_from_value (CRStyle * a_style, CRTerm * a_value);
298
299 static enum CRStatus
300 set_prop_padding_from_value (CRStyle * a_style, CRTerm * a_value);
301
302 static enum CRStatus
303 set_prop_margin_from_value (CRStyle * a_style, CRTerm * a_value);
304
305 static enum CRStatus
306 set_prop_font_family_from_value (CRStyle * a_style, CRTerm * a_value);
307
308 static enum CRStatus
309 init_style_font_size_field (CRStyle * a_style);
310
311 static enum CRStatus
312 set_prop_font_size_from_value (CRStyle * a_style, CRTerm * a_value);
313
314 static enum CRStatus
315 set_prop_font_style_from_value (CRStyle * a_style, CRTerm * a_value);
316
317 static enum CRStatus
318 set_prop_font_weight_from_value (CRStyle * a_style, CRTerm * a_value);
319
320 static const gchar *
321 num_prop_code_to_string (enum CRNumProp a_code)
322 {
323         gint len = sizeof (gv_num_props_dump_infos) /
324                 sizeof (struct CRNumPropEnumDumpInfo);
325         if (a_code >= len) {
326                 cr_utils_trace_info ("A field has been added "
327                                      "to 'enum CRNumProp' and no matching"
328                                      " entry has been "
329                                      "added to gv_num_prop_dump_infos table.\n"
330                                      "Please add the missing matching entry");
331                 return NULL;
332         }
333         if (gv_num_props_dump_infos[a_code].code != a_code) {
334                 cr_utils_trace_info ("mismatch between the order of fields in"
335                                      " 'enum CRNumProp' and "
336                                      "the order of entries in "
337                                      "the gv_num_prop_dump_infos table");
338                 return NULL;
339         }
340         return gv_num_props_dump_infos[a_code].str;
341 }
342
343 static const gchar *
344 rgb_prop_code_to_string (enum CRRgbProp a_code)
345 {
346         gint len = sizeof (gv_rgb_props_dump_infos) /
347                 sizeof (struct CRRgbPropEnumDumpInfo);
348
349         if (a_code >= len) {
350                 cr_utils_trace_info ("A field has been added "
351                                      "to 'enum CRRgbProp' and no matching"
352                                      " entry has been "
353                                      "added to gv_rgb_prop_dump_infos table.\n"
354                                      "Please add the missing matching entry");
355                 return NULL;
356         }
357         if (gv_rgb_props_dump_infos[a_code].code != a_code) {
358                 cr_utils_trace_info ("mismatch between the order of fields in"
359                                      " 'enum CRRgbProp' and "
360                                      "the order of entries in "
361                                      "the gv_rgb_props_dump_infos table");
362                 return NULL;
363         }
364         return gv_rgb_props_dump_infos[a_code].str;
365 }
366
367 static const gchar *
368 border_style_prop_code_to_string (enum CRBorderStyleProp a_code)
369 {
370         gint len = sizeof (gv_border_style_props_dump_infos) /
371                 sizeof (struct CRBorderStylePropEnumDumpInfo);
372
373         if (a_code >= len) {
374                 cr_utils_trace_info ("A field has been added "
375                                      "to 'enum CRBorderStyleProp' and no matching"
376                                      " entry has been "
377                                      "added to gv_border_style_prop_dump_infos table.\n"
378                                      "Please add the missing matching entry");
379                 return NULL;
380         }
381         if (gv_border_style_props_dump_infos[a_code].code != a_code) {
382                 cr_utils_trace_info ("mismatch between the order of fields in"
383                                      " 'enum CRBorderStyleProp' and "
384                                      "the order of entries in "
385                                      "the gv_border_style_props_dump_infos table");
386                 return NULL;
387         }
388         return gv_border_style_props_dump_infos[a_code].str;
389 }
390
391 static enum CRStatus
392 cr_style_init_properties (void)
393 {
394
395         if (!gv_prop_hash) {
396                 gulong i = 0;
397
398                 gv_prop_hash = g_hash_table_new (g_str_hash, g_str_equal);
399                 if (!gv_prop_hash) {
400                         cr_utils_trace_info ("Out of memory");
401                         return CR_ERROR;
402                 }
403
404                 /*load gv_prop_hash from gv_prop_table */
405                 for (i = 0; gv_prop_table[i].name; i++) {
406                         g_hash_table_insert
407                                 (gv_prop_hash,
408                                  (gpointer) gv_prop_table[i].name,
409                                  GINT_TO_POINTER (gv_prop_table[i].prop_id));
410                 }
411         }
412
413         return CR_OK;
414 }
415
416 static enum CRPropertyID
417 cr_style_get_prop_id (const guchar * a_prop)
418 {
419         gpointer *raw_id = NULL;
420
421         if (!gv_prop_hash) {
422                 cr_style_init_properties ();
423         }
424
425         raw_id = g_hash_table_lookup (gv_prop_hash, a_prop);
426         if (!raw_id) {
427                 return PROP_ID_NOT_KNOWN;
428         }
429         return GPOINTER_TO_INT (raw_id);
430 }
431
432 static enum CRStatus
433 set_prop_padding_x_from_value (CRStyle * a_style,
434                                CRTerm * a_value, enum CRDirection a_dir)
435 {
436         enum CRStatus status = CR_OK;
437         CRNum *num_val = NULL;
438
439         g_return_val_if_fail (a_style && a_value, CR_BAD_PARAM_ERROR);
440
441         if (a_value->type != TERM_NUMBER && a_value->type != TERM_IDENT)
442                 return CR_BAD_PARAM_ERROR;
443
444         switch (a_dir) {
445         case DIR_TOP:
446                 num_val = &a_style->num_props[NUM_PROP_PADDING_TOP].sv;
447                 break;
448
449         case DIR_RIGHT:
450                 num_val = &a_style->num_props[NUM_PROP_PADDING_RIGHT].sv;
451                 break;
452
453         case DIR_BOTTOM:
454                 num_val = &a_style->num_props[NUM_PROP_PADDING_BOTTOM].sv;
455                 break;
456
457         case DIR_LEFT:
458                 num_val = &a_style->num_props[NUM_PROP_PADDING_LEFT].sv;
459                 break;
460
461         default:
462                 return CR_BAD_PARAM_ERROR;
463         }
464
465         if (a_value->type == TERM_IDENT) {
466                 if (a_value->content.str
467                     && a_value->content.str->stryng
468                     && a_value->content.str->stryng->str
469                     && !strncmp ((guchar *) "inherit",
470                                  a_value->content.str->stryng->str,
471                                  sizeof ("inherit")-1)) {
472                         status = cr_num_set (num_val, 0.0, NUM_INHERIT);
473                         return CR_OK;
474                 } else
475                         return CR_UNKNOWN_TYPE_ERROR;
476         }
477
478         g_return_val_if_fail (a_value->type == TERM_NUMBER
479                               && a_value->content.num, CR_UNKNOWN_TYPE_ERROR);
480
481         switch (a_value->content.num->type) {
482         case NUM_LENGTH_EM:
483         case NUM_LENGTH_EX:
484         case NUM_LENGTH_PX:
485         case NUM_LENGTH_IN:
486         case NUM_LENGTH_CM:
487         case NUM_LENGTH_MM:
488         case NUM_LENGTH_PT:
489         case NUM_LENGTH_PC:
490         case NUM_PERCENTAGE:
491                 status = cr_num_copy (num_val, a_value->content.num);
492                 break;
493         default:
494                 status = CR_UNKNOWN_TYPE_ERROR;
495                 break;
496         }
497
498         return status;
499 }
500
501 static enum CRStatus
502 set_prop_border_x_width_from_value (CRStyle * a_style,
503                                     CRTerm * a_value, 
504                                     enum CRDirection a_dir)
505 {
506         enum CRStatus status = CR_OK;
507         CRNum *num_val = NULL;
508
509         g_return_val_if_fail (a_value && a_style, CR_BAD_PARAM_ERROR);
510
511         switch (a_dir) {
512         case DIR_TOP:
513                 num_val = &a_style->num_props[NUM_PROP_BORDER_TOP].sv;
514                 break;
515
516         case DIR_RIGHT:
517                 num_val = &a_style->num_props[NUM_PROP_BORDER_RIGHT].sv;
518                 break;
519
520         case DIR_BOTTOM:
521                 num_val = &a_style->num_props[NUM_PROP_BORDER_BOTTOM].sv;
522                 break;
523
524         case DIR_LEFT:
525                 num_val = &a_style->num_props[NUM_PROP_BORDER_LEFT].sv;
526                 break;
527
528         default:
529                 return CR_BAD_PARAM_ERROR;
530                 break;
531         }
532
533         if (a_value->type == TERM_IDENT) {
534                 if (a_value->content.str 
535                     && a_value->content.str->stryng
536                     && a_value->content.str->stryng->str) {
537                         if (!strncmp ("thin",
538                                       a_value->content.str->stryng->str,
539                                       sizeof ("thin")-1)) {
540                                 cr_num_set (num_val, BORDER_THIN,
541                                             NUM_LENGTH_PX);
542                         } else if (!strncmp 
543                                    ("medium",
544                                     a_value->content.str->stryng->str,
545                                              sizeof ("medium")-1)) {
546                                 cr_num_set (num_val, BORDER_MEDIUM,
547                                             NUM_LENGTH_PX);
548                         } else if (!strncmp ("thick",
549                                              a_value->content.str->stryng->str,
550                                              sizeof ("thick")-1)) {
551                                 cr_num_set (num_val, BORDER_THICK,
552                                             NUM_LENGTH_PX);
553                         } else {
554                                 return CR_UNKNOWN_TYPE_ERROR;
555                         }
556                 }
557         } else if (a_value->type == TERM_NUMBER) {
558                 if (a_value->content.num) {
559                         cr_num_copy (num_val, a_value->content.num);
560                 }
561         } else if (a_value->type != TERM_NUMBER
562                    || a_value->content.num == NULL) {
563                 return CR_UNKNOWN_TYPE_ERROR;
564         }
565
566         return status;
567 }
568
569 static enum CRStatus
570 set_prop_border_width_from_value (CRStyle *a_style,
571                                   CRTerm *a_value)
572 {
573         CRTerm *cur_term = NULL ;
574         enum CRDirection direction = DIR_TOP ;
575
576         g_return_val_if_fail (a_style && a_value,
577                               CR_BAD_PARAM_ERROR) ;
578         cur_term = a_value ;
579
580         if (!cur_term)
581                 return CR_ERROR ;
582
583         for (direction = DIR_TOP ; 
584              direction < NB_DIRS ; direction ++) {
585                 set_prop_border_x_width_from_value (a_style, 
586                                                     cur_term,
587                                                     direction) ;
588         }
589
590         cur_term = cur_term->next ;
591         if (!cur_term)
592                 return CR_OK ;
593         set_prop_border_x_width_from_value (a_style, cur_term,
594                                             DIR_RIGHT) ;
595         set_prop_border_x_width_from_value (a_style, cur_term,
596                                             DIR_LEFT) ;
597
598         cur_term = cur_term->next ;
599         if (!cur_term)
600                 return CR_OK ;
601         set_prop_border_x_width_from_value (a_style, cur_term,
602                                             DIR_BOTTOM) ;
603
604         cur_term = cur_term->next ;
605         if (!cur_term)
606                 return CR_OK ;
607         set_prop_border_x_width_from_value (a_style, cur_term,
608                                             DIR_LEFT) ;
609
610         return CR_OK ;
611 }
612
613 static enum CRStatus
614 set_prop_border_x_style_from_value (CRStyle * a_style,
615                                     CRTerm * a_value, enum CRDirection a_dir)
616 {
617         enum CRStatus status = CR_OK;
618         enum CRBorderStyle *border_style_ptr = NULL;
619
620         g_return_val_if_fail (a_style && a_value, CR_BAD_PARAM_ERROR);
621
622         switch (a_dir) {
623         case DIR_TOP:
624                 border_style_ptr = &a_style->
625                         border_style_props[BORDER_STYLE_PROP_TOP];
626                 break;
627
628         case DIR_RIGHT:
629                 border_style_ptr =
630                         &a_style->border_style_props[BORDER_STYLE_PROP_RIGHT];
631                 break;
632
633         case DIR_BOTTOM:
634                 border_style_ptr = &a_style->
635                         border_style_props[BORDER_STYLE_PROP_BOTTOM];
636                 break;
637
638         case DIR_LEFT:
639                 border_style_ptr = &a_style->
640                         border_style_props[BORDER_STYLE_PROP_LEFT];
641                 break;
642
643         default:
644                 break;
645         }
646
647         if (a_value->type != TERM_IDENT || !a_value->content.str) {
648                 return CR_UNKNOWN_TYPE_ERROR;
649         }
650
651         if (!strncmp ("none", 
652                       a_value->content.str->stryng->str, 
653                       sizeof ("none")-1)) {
654                 *border_style_ptr = BORDER_STYLE_NONE;
655         } else if (!strncmp ("hidden",
656                              a_value->content.str->stryng->str, 
657                              sizeof ("hidden")-1)) {
658                 *border_style_ptr = BORDER_STYLE_HIDDEN;
659         } else if (!strncmp ("dotted",
660                              a_value->content.str->stryng->str, 
661                              sizeof ("dotted")-1)) {
662                 *border_style_ptr = BORDER_STYLE_DOTTED;
663         } else if (!strncmp ("dashed",
664                              a_value->content.str->stryng->str, sizeof ("dashed")-1)) {
665                 *border_style_ptr = BORDER_STYLE_DASHED;
666         } else if (!strncmp ("solid",
667                              a_value->content.str->stryng->str, sizeof ("solid")-1)) {
668                 *border_style_ptr = BORDER_STYLE_SOLID;
669         } else if (!strncmp ("double",
670                              a_value->content.str->stryng->str, sizeof ("double")-1)) {
671                 *border_style_ptr = BORDER_STYLE_DOUBLE;
672         } else if (!strncmp ("groove",
673                              a_value->content.str->stryng->str, sizeof ("groove")-1)) {
674                 *border_style_ptr = BORDER_STYLE_GROOVE;
675         } else if (!strncmp ("ridge",
676                              a_value->content.str->stryng->str, 
677                              sizeof ("ridge")-1)) {
678                 *border_style_ptr = BORDER_STYLE_RIDGE;
679         } else if (!strncmp ("inset",
680                              a_value->content.str->stryng->str, 
681                              sizeof ("inset")-1)) {
682                 *border_style_ptr = BORDER_STYLE_INSET;
683         } else if (!strncmp ("outset",
684                              a_value->content.str->stryng->str, 
685                              sizeof ("outset")-1)) {
686                 *border_style_ptr = BORDER_STYLE_OUTSET;
687         } else if (!strncmp ("inherit",
688                              a_value->content.str->stryng->str, 
689                              sizeof ("inherit")-1)) {
690                 *border_style_ptr = BORDER_STYLE_INHERIT;
691         } else {
692                 status = CR_UNKNOWN_TYPE_ERROR;
693         }
694
695         return status;
696 }
697
698 static enum CRStatus
699 set_prop_border_style_from_value (CRStyle *a_style,
700                                   CRTerm *a_value)
701 {
702         CRTerm *cur_term = NULL ;
703         enum CRDirection direction = DIR_TOP ;
704
705         g_return_val_if_fail (a_style && a_value, 
706                               CR_BAD_PARAM_ERROR) ;
707
708         cur_term = a_value ;
709         if (!cur_term || cur_term->type != TERM_IDENT) {
710                 return CR_ERROR ;
711         }
712         
713         for (direction = DIR_TOP ; 
714              direction < NB_DIRS ;
715              direction ++) {
716                 set_prop_border_x_style_from_value (a_style, 
717                                                     cur_term,
718                                                     direction) ;
719         }
720         
721         cur_term = cur_term->next ;
722         if (!cur_term || cur_term->type != TERM_IDENT) {
723                 return CR_OK ;
724         }
725         
726         set_prop_border_x_style_from_value (a_style, cur_term, 
727                                             DIR_RIGHT) ;
728         set_prop_border_x_style_from_value (a_style, cur_term, 
729                                             DIR_LEFT) ;
730
731         cur_term = cur_term->next ;
732         if (!cur_term || cur_term->type != TERM_IDENT) {
733                 return CR_OK ;
734         }        
735         set_prop_border_x_style_from_value (a_style, cur_term,
736                                            DIR_BOTTOM) ;
737         
738         cur_term = cur_term->next ;
739         if (!cur_term || cur_term->type != TERM_IDENT) {
740                 return CR_OK ;
741         }
742         set_prop_border_x_style_from_value (a_style, cur_term,
743                                             DIR_LEFT) ;
744         return CR_OK ;
745 }
746
747 static enum CRStatus
748 set_prop_margin_x_from_value (CRStyle * a_style, CRTerm * a_value,
749                               enum CRDirection a_dir)
750 {
751         enum CRStatus status = CR_OK;
752         CRNum *num_val = NULL;
753
754         g_return_val_if_fail (a_style && a_value, CR_BAD_PARAM_ERROR);
755
756         switch (a_dir) {
757         case DIR_TOP:
758                 num_val = &a_style->num_props[NUM_PROP_MARGIN_TOP].sv;
759                 break;
760
761         case DIR_RIGHT:
762                 num_val = &a_style->num_props[NUM_PROP_MARGIN_RIGHT].sv;
763                 break;
764
765         case DIR_BOTTOM:
766                 num_val = &a_style->num_props[NUM_PROP_MARGIN_BOTTOM].sv;
767                 break;
768
769         case DIR_LEFT:
770                 num_val = &a_style->num_props[NUM_PROP_MARGIN_LEFT].sv;
771                 break;
772
773         default:
774                 break;
775         }
776
777         switch (a_value->type) {
778         case TERM_IDENT:
779                 if (a_value->content.str
780                     && a_value->content.str->stryng
781                     && a_value->content.str->stryng->str
782                     && !strcmp (a_value->content.str->stryng->str,
783                                  "inherit")) {
784                         status = cr_num_set (num_val, 0.0, NUM_INHERIT);
785                 } else if (a_value->content.str
786                            && a_value->content.str->stryng
787                            && !strcmp (a_value->content.str->stryng->str,
788                                         "auto")) {
789                         status = cr_num_set (num_val, 0.0, NUM_AUTO);
790                 } else {
791                         status = CR_UNKNOWN_TYPE_ERROR;
792                 }
793                 break ;
794
795         case TERM_NUMBER:
796                 status = cr_num_copy (num_val, a_value->content.num);
797                 break;
798
799         default:
800                 status = CR_UNKNOWN_TYPE_ERROR;
801                 break;
802         }
803
804         return status;
805 }
806
807 struct CRPropDisplayValPair {
808         const guchar *prop_name;
809         enum CRDisplayType type;
810 };
811
812 static enum CRStatus
813 set_prop_display_from_value (CRStyle * a_style, CRTerm * a_value)
814 {
815         static const struct CRPropDisplayValPair disp_vals_map[] = {
816                 {"none", DISPLAY_NONE},
817                 {"inline", DISPLAY_INLINE},
818                 {"block", DISPLAY_BLOCK},
819                 {"run-in", DISPLAY_RUN_IN},
820                 {"compact", DISPLAY_COMPACT},
821                 {"marker", DISPLAY_MARKER},
822                 {"table", DISPLAY_TABLE},
823                 {"inline-table", DISPLAY_INLINE_TABLE},
824                 {"table-row-group", DISPLAY_TABLE_ROW_GROUP},
825                 {"table-header-group", DISPLAY_TABLE_HEADER_GROUP},
826                 {"table-footer-group", DISPLAY_TABLE_FOOTER_GROUP},
827                 {"table-row", DISPLAY_TABLE_ROW},
828                 {"table-column-group", DISPLAY_TABLE_COLUMN_GROUP},
829                 {"table-column", DISPLAY_TABLE_COLUMN},
830                 {"table-cell", DISPLAY_TABLE_CELL},
831                 {"table-caption", DISPLAY_TABLE_CAPTION},
832                 {"inherit", DISPLAY_INHERIT},
833                 {NULL, DISPLAY_NONE}
834         };
835
836         g_return_val_if_fail (a_style && a_value, CR_BAD_PARAM_ERROR);
837
838         switch (a_value->type) {
839         case TERM_IDENT:
840                 {
841                         int i = 0;
842
843                         if (!a_value->content.str
844                             || !a_value->content.str->stryng
845                             || !a_value->content.str->stryng->str)
846                                 break;
847
848                         for (i = 0; disp_vals_map[i].prop_name; i++) {
849                                 if (!strncmp 
850                                     (disp_vals_map[i].prop_name,
851                                      a_value->content.str->stryng->str,
852                                      strlen (disp_vals_map[i].prop_name))) {
853                                         a_style->display =
854                                                 disp_vals_map[i].type;
855                                         break;
856                                 }
857                         }
858                 }
859                 break;
860
861         default:
862                 break;
863         }
864
865         return CR_OK;
866 }
867
868 struct CRPropPositionValPair {
869         const guchar *name;
870         enum CRPositionType type;
871 };
872
873 static enum CRStatus
874 set_prop_position_from_value (CRStyle * a_style, CRTerm * a_value)
875 {
876         enum CRStatus status = CR_UNKNOWN_PROP_VAL_ERROR;
877         static const struct CRPropPositionValPair position_vals_map[] = {
878                 {"static", POSITION_STATIC},
879                 {"relative", POSITION_RELATIVE},
880                 {"absolute", POSITION_ABSOLUTE},
881                 {"fixed", POSITION_FIXED},
882                 {"inherit", POSITION_INHERIT},
883                 {NULL, POSITION_STATIC}
884                 /*must alwas be the last one */
885         };
886
887         g_return_val_if_fail (a_value, CR_BAD_PARAM_ERROR);
888
889         switch (a_value->type) {
890         case TERM_IDENT:
891                 {
892                         int i = 0;
893
894                         if (!a_value->content.str
895                             || !a_value->content.str->stryng
896                             || !a_value->content.str->stryng->str)
897                                 break;
898
899                         for (i = 0; position_vals_map[i].name; i++) {
900                                 if (!strncmp (position_vals_map[i].name,
901                                               a_value->content.str->stryng->str,
902                                               strlen (position_vals_map[i].
903                                                       name))) {
904                                         a_style->position =
905                                                 position_vals_map[i].type;
906                                         status = CR_OK;
907                                         break;
908                                 }
909                         }
910                 }
911                 break;
912
913         default:
914                 break;
915         }
916
917         return CR_OK;
918 }
919
920 static enum CRStatus
921 set_prop_x_from_value (CRStyle * a_style, CRTerm * a_value,
922                        enum CRDirection a_dir)
923 {
924         CRNum *box_offset = NULL;
925
926         g_return_val_if_fail (a_style && a_value, CR_BAD_PARAM_ERROR);
927
928         if (!(a_value->type == TERM_NUMBER)
929             && !(a_value->type == TERM_IDENT)) {
930                 return CR_UNKNOWN_PROP_VAL_ERROR;
931         }
932
933         switch (a_dir) {
934         case DIR_TOP:
935                 box_offset = &a_style->num_props[NUM_PROP_TOP].sv;
936                 break;
937
938         case DIR_RIGHT:
939                 box_offset = &a_style->num_props[NUM_PROP_RIGHT].sv;
940                 break;
941
942         case DIR_BOTTOM:
943                 box_offset = &a_style->num_props[NUM_PROP_BOTTOM].sv;
944                 break;
945         case DIR_LEFT:
946                 box_offset = &a_style->num_props[NUM_PROP_LEFT].sv;
947                 break;
948
949         default:
950                 break;
951         }
952
953         box_offset->type = NUM_AUTO;
954
955         if (a_value->type == TERM_NUMBER && a_value->content.num) {
956                 cr_num_copy (box_offset, a_value->content.num);
957         } else if (a_value->type == TERM_IDENT
958                    && a_value->content.str
959                    && a_value->content.str->stryng
960                    && a_value->content.str->stryng->str) {
961                 if (!strncmp ("inherit",
962                               a_value->content.str->stryng->str,
963                               sizeof ("inherit")-1)) {
964                         cr_num_set (box_offset, 0.0, NUM_INHERIT);
965                 } else if (!strncmp ("auto",
966                                      a_value->content.str->stryng->str,
967                                      sizeof ("auto")-1)) {
968                         box_offset->type = NUM_AUTO;
969                 }
970         }
971
972         return CR_OK;
973 }
974
975 static enum CRStatus
976 set_prop_float (CRStyle * a_style, CRTerm * a_value)
977 {
978         g_return_val_if_fail (a_style && a_value, 
979                               CR_BAD_PARAM_ERROR);
980
981         /*the default float type as specified by the css2 spec */
982         a_style->float_type = FLOAT_NONE;
983
984         if (a_value->type != TERM_IDENT 
985             || !a_value->content.str
986             || !a_value->content.str->stryng
987             || !a_value->content.str->stryng->str) { 
988                 /*unknow type, the float type is set to it's default value */
989                 return CR_OK;
990         }
991
992         if (!strncmp ("none", 
993                       a_value->content.str->stryng->str, 
994                       sizeof ("none")-1)) {
995                 a_style->float_type = FLOAT_NONE;
996         } else if (!strncmp ("left",
997                              a_value->content.str->stryng->str, 
998                              sizeof ("left")-1)) {
999                 a_style->float_type = FLOAT_LEFT;
1000         } else if (!strncmp ("right",
1001                              a_value->content.str->stryng->str, 
1002                              sizeof ("right")-1)) {
1003                 a_style->float_type = FLOAT_RIGHT;
1004         } else if (!strncmp ("inherit",
1005                              a_value->content.str->stryng->str, 
1006                              sizeof ("inherit")-1)) {
1007                 a_style->float_type = FLOAT_INHERIT;
1008         }
1009         return CR_OK;
1010 }
1011
1012 static enum CRStatus
1013 set_prop_width (CRStyle * a_style, CRTerm * a_value)
1014 {
1015         CRNum *width = NULL;
1016         g_return_val_if_fail (a_style 
1017                               && a_value, 
1018                               CR_BAD_PARAM_ERROR);
1019
1020         width = &a_style->num_props[NUM_PROP_WIDTH].sv;
1021         cr_num_set (width, 0.0, NUM_AUTO);
1022
1023         if (a_value->type == TERM_IDENT) {
1024                 if (a_value->content.str 
1025                     && a_value->content.str->stryng
1026                     && a_value->content.str->stryng->str) {
1027                         if (!strncmp ("auto",
1028                                       a_value->content.str->stryng->str,
1029                                       sizeof ("auto")-1)) {
1030                                 cr_num_set (width, 0.0, NUM_AUTO);
1031                         } else if (!strncmp ("inherit",
1032                                              a_value->content.str->stryng->str,
1033                                              sizeof ("inherit")-1)) {
1034                                 cr_num_set (width, 0.0, NUM_INHERIT);
1035                         }
1036                 }
1037         } else if (a_value->type == TERM_NUMBER) {
1038                 if (a_value->content.num) {
1039                         cr_num_copy (&a_style->num_props[NUM_PROP_WIDTH].sv,
1040                                      a_value->content.num);
1041                 }
1042         }
1043         return CR_OK;
1044 }
1045
1046 static enum CRStatus 
1047 set_prop_color (CRStyle * a_style, CRTerm * a_value)
1048 {
1049         enum CRStatus status = CR_OK;
1050         CRRgb *a_rgb = &a_style->rgb_props[RGB_PROP_COLOR].sv;
1051
1052         g_return_val_if_fail (a_style 
1053                               && a_value, CR_BAD_PARAM_ERROR);
1054
1055         status = cr_rgb_set_from_term (a_rgb, a_value);
1056
1057         return status;
1058 }
1059
1060 static enum CRStatus
1061 set_prop_background_color (CRStyle * a_style, CRTerm * a_value)
1062 {
1063         enum CRStatus status = CR_OK;
1064         CRRgb *rgb = &a_style->rgb_props[RGB_PROP_BACKGROUND_COLOR].sv;
1065
1066         g_return_val_if_fail (a_style && a_value, CR_BAD_PARAM_ERROR);
1067
1068         status = cr_rgb_set_from_term (rgb, a_value);
1069         return status;
1070 }
1071
1072 /**
1073  *Sets border-top-color, border-right-color,
1074  *border-bottom-color or border-left-color properties
1075  *in the style structure. The value is taken from a
1076  *css2 term of type IDENT or RGB.
1077  *@param a_style the style structure to set.
1078  *@param a_value the css2 term to take the color information from.
1079  *@param a_dir the direction (TOP, LEFT, RIGHT, or BOTTOM).
1080  *@return CR_OK upon successfull completion, an error code otherwise.
1081  */
1082 static enum CRStatus
1083 set_prop_border_x_color_from_value (CRStyle * a_style, CRTerm * a_value,
1084                                     enum CRDirection a_dir)
1085 {
1086         CRRgb *rgb_color = NULL;
1087         enum CRStatus status = CR_OK;
1088
1089         g_return_val_if_fail (a_style && a_value, CR_BAD_PARAM_ERROR);
1090
1091         switch (a_dir) {
1092         case DIR_TOP:
1093                 rgb_color = &a_style->rgb_props[RGB_PROP_BORDER_TOP_COLOR].sv;
1094                 break;
1095
1096         case DIR_RIGHT:
1097                 rgb_color =
1098                         &a_style->rgb_props[RGB_PROP_BORDER_RIGHT_COLOR].sv;
1099                 break;
1100
1101         case DIR_BOTTOM:
1102                 rgb_color =
1103                         &a_style->rgb_props[RGB_PROP_BORDER_BOTTOM_COLOR].sv;
1104                 break;
1105
1106         case DIR_LEFT:
1107                 rgb_color =
1108                         &a_style->rgb_props[RGB_PROP_BORDER_LEFT_COLOR].sv;
1109                 break;
1110
1111         default:
1112                 cr_utils_trace_info ("unknown DIR type");
1113                 return CR_BAD_PARAM_ERROR;
1114         }
1115
1116         status = CR_UNKNOWN_PROP_VAL_ERROR;
1117
1118         if (a_value->type == TERM_IDENT) {
1119                 if (a_value->content.str 
1120                     && a_value->content.str->stryng
1121                     && a_value->content.str->stryng->str) {
1122                         status = cr_rgb_set_from_name
1123                                 (rgb_color, 
1124                                  a_value->content.str->stryng->str);
1125
1126                 }
1127                 if (status != CR_OK) {
1128                         cr_rgb_set_from_name (rgb_color, "black");
1129                 }
1130         } else if (a_value->type == TERM_RGB) {
1131                 if (a_value->content.rgb) {
1132                         status = cr_rgb_set_from_rgb
1133                                 (rgb_color, a_value->content.rgb);
1134                 }
1135         }
1136         return status;
1137 }
1138
1139 static enum CRStatus
1140 set_prop_border_x_from_value (CRStyle * a_style, CRTerm * a_value,
1141                               enum CRDirection a_dir)
1142 {
1143         CRTerm *cur_term = NULL;
1144
1145         enum CRStatus status = CR_OK;
1146
1147         g_return_val_if_fail (a_style && a_value, CR_BAD_PARAM_ERROR);
1148
1149         for (cur_term = a_value; 
1150              cur_term; 
1151              cur_term = cur_term->next) {
1152                 status = set_prop_border_x_width_from_value (a_style,
1153                                                              cur_term, a_dir);
1154
1155                 if (status != CR_OK) {
1156                         status = set_prop_border_x_style_from_value
1157                                 (a_style, cur_term, a_dir);
1158                 }
1159                 if (status != CR_OK) {
1160                         status = set_prop_border_x_color_from_value
1161                                 (a_style, cur_term, a_dir);
1162                 }
1163         }
1164         return CR_OK;
1165 }
1166
1167 static enum CRStatus
1168 set_prop_border_from_value (CRStyle * a_style, CRTerm * a_value)
1169 {
1170         enum CRDirection direction = 0;
1171
1172         g_return_val_if_fail (a_style && a_value, CR_BAD_PARAM_ERROR);
1173
1174         for (direction = 0; direction < NB_DIRS; direction++) {
1175                 set_prop_border_x_from_value (a_style, 
1176                                               a_value, 
1177                                               direction);
1178         }
1179
1180         return CR_OK;
1181 }
1182
1183 static enum CRStatus
1184 set_prop_padding_from_value (CRStyle * a_style, CRTerm * a_value)
1185 {
1186         CRTerm *cur_term = NULL;
1187         enum CRDirection direction = 0;
1188         enum CRStatus status = CR_OK;
1189         
1190         g_return_val_if_fail (a_style && a_value, CR_BAD_PARAM_ERROR);
1191
1192         cur_term = a_value;
1193
1194         /*filter the eventual non NUMBER terms some user can have written here*/
1195         while (cur_term && cur_term->type != TERM_NUMBER) {
1196                 cur_term = cur_term->next;
1197         }
1198         if (!cur_term)
1199                 return CR_ERROR ;
1200
1201         for (direction = 0; direction < NB_DIRS; direction++) {
1202                 set_prop_padding_x_from_value (a_style, cur_term, direction);
1203         }
1204         cur_term = cur_term->next;
1205
1206         /*filter non NUMBER terms that some users can have written here...*/
1207         while (cur_term && cur_term->type != TERM_NUMBER) {
1208                 cur_term = cur_term->next;
1209         }
1210         /*the user can have just written padding: 1px*/
1211         if (!cur_term)
1212                 return CR_OK;
1213
1214         set_prop_padding_x_from_value (a_style, cur_term, DIR_RIGHT);
1215         set_prop_padding_x_from_value (a_style, cur_term, DIR_LEFT);
1216
1217         while (cur_term && cur_term->type != TERM_NUMBER) {
1218                 cur_term = cur_term->next;
1219         }
1220         if (!cur_term)
1221                 return CR_OK;
1222
1223         set_prop_padding_x_from_value (a_style, cur_term, DIR_BOTTOM);
1224
1225         while (cur_term && cur_term->type != TERM_NUMBER) {
1226                 cur_term = cur_term->next;
1227         }
1228         if (!cur_term)
1229                 return CR_OK;
1230         status = set_prop_padding_x_from_value (a_style, cur_term, DIR_LEFT);
1231         return status;
1232 }
1233
1234 static enum CRStatus
1235 set_prop_margin_from_value (CRStyle * a_style, CRTerm * a_value)
1236 {
1237         CRTerm *cur_term = NULL;
1238         enum CRDirection direction = 0;
1239         enum CRStatus status = CR_OK;
1240
1241         g_return_val_if_fail (a_style && a_value, CR_BAD_PARAM_ERROR);
1242
1243         cur_term = a_value;
1244
1245         while (cur_term && cur_term->type != TERM_NUMBER) {
1246                 cur_term = cur_term->next;
1247         }
1248
1249         if (!cur_term)
1250                 return CR_OK;
1251
1252         for (direction = 0; direction < NB_DIRS; direction++) {
1253                 set_prop_margin_x_from_value (a_style, cur_term, direction);
1254         }
1255         cur_term = cur_term->next;
1256
1257         while (cur_term && cur_term->type != TERM_NUMBER) {
1258                 cur_term = cur_term->next;
1259         }
1260         if (!cur_term)
1261                 return CR_OK;
1262
1263         set_prop_margin_x_from_value (a_style, cur_term, DIR_RIGHT);
1264         set_prop_margin_x_from_value (a_style, cur_term, DIR_LEFT);
1265
1266         while (cur_term && cur_term->type != TERM_NUMBER) {
1267                 cur_term = cur_term->next;
1268         }
1269         if (!cur_term)
1270                 return CR_OK;
1271
1272         set_prop_margin_x_from_value (a_style, cur_term, DIR_BOTTOM);
1273
1274         while (cur_term && cur_term->type != TERM_NUMBER) {
1275                 cur_term = cur_term->next;
1276         }
1277         if (!cur_term)
1278                 return CR_OK;
1279
1280         status = set_prop_margin_x_from_value (a_style, cur_term, DIR_LEFT);        
1281
1282         return status;
1283 }
1284
1285 static enum CRStatus
1286 set_prop_font_family_from_value (CRStyle * a_style, CRTerm * a_value)
1287 {
1288         CRTerm *cur_term = NULL;
1289         CRFontFamily *font_family = NULL,
1290                 *cur_ff = NULL,
1291                 *cur_ff2 = NULL;
1292
1293         g_return_val_if_fail (a_style && a_value, CR_BAD_PARAM_ERROR);
1294
1295         if (a_value->type == TERM_IDENT &&
1296             a_value->content.str &&
1297             a_value->content.str->stryng &&
1298             a_value->content.str->stryng->str &&
1299             !strcmp ("inherit", a_value->content.str->stryng->str))
1300         {
1301                 font_family = cr_font_family_new (FONT_FAMILY_INHERIT, NULL);
1302                 goto out;
1303         }
1304
1305         for (cur_term = a_value; cur_term; cur_term = cur_term->next) {
1306                 switch (cur_term->type) {
1307                 case TERM_IDENT:
1308                         {
1309                                 enum CRFontFamilyType font_type;
1310
1311                                 if (cur_term->content.str
1312                                     && cur_term->content.str->stryng
1313                                     && cur_term->content.str->stryng->str
1314                                     && !strcmp 
1315                                     (cur_term->content.str->stryng->str,
1316                                      "sans-serif")) {
1317                                         font_type = FONT_FAMILY_SANS_SERIF;
1318                                 } else if (cur_term->content.str
1319                                            && cur_term->content.str->stryng
1320                                            && cur_term->content.str->stryng->str
1321                                            && !strcmp 
1322                                            (cur_term->content.str->stryng->str, 
1323                                             "serif")) {
1324                                         font_type = FONT_FAMILY_SERIF;
1325                                 } else if (cur_term->content.str
1326                                            && cur_term->content.str->stryng
1327                                            && cur_term->content.str->stryng->str
1328                                            && !strcmp (cur_term->content.str->stryng->str, 
1329                                                        "cursive")) {
1330                                         font_type = FONT_FAMILY_CURSIVE;
1331                                 } else if (cur_term->content.str
1332                                            && cur_term->content.str->stryng
1333                                            && cur_term->content.str->stryng->str
1334                                            && !strcmp (cur_term->content.str->stryng->str,
1335                                                        "fantasy")) {
1336                                         font_type = FONT_FAMILY_FANTASY;
1337                                 } else if (cur_term->content.str
1338                                            && cur_term->content.str->stryng
1339                                            && cur_term->content.str->stryng->str
1340                                            && !strcmp (cur_term->content.str->stryng->str, 
1341                                                        "monospace")) {
1342                                         font_type = FONT_FAMILY_MONOSPACE;
1343                                 } else {
1344                                         /*
1345                                          *unknown property value.
1346                                          *ignore it.
1347                                          */
1348                                         continue;
1349                                 }
1350
1351                                 cur_ff = cr_font_family_new (font_type, NULL);
1352                         }
1353                         break;
1354
1355                 case TERM_STRING:
1356                         {
1357                                 if (cur_term->content.str
1358                                     && cur_term->content.str->stryng
1359                                     && cur_term->content.str->stryng->str) {
1360                                         cur_ff = cr_font_family_new
1361                                                 (FONT_FAMILY_NON_GENERIC,
1362                                                  cur_term->content.str->stryng->str);
1363                                 }
1364                         }
1365                         break;
1366
1367                 default:
1368                         break;
1369                 }
1370
1371                 cur_ff2 = cr_font_family_append (font_family, cur_ff);
1372                 if (cur_ff2) {
1373                         font_family = cur_ff2;
1374                 }
1375         }
1376
1377  out:
1378         if (font_family) {
1379                 if (a_style->font_family) {
1380                         cr_font_family_destroy (a_style->font_family);
1381                         a_style->font_family = NULL ;
1382                 }
1383                 a_style->font_family = font_family;
1384                 font_family = NULL ;
1385         }
1386
1387         return CR_OK;
1388 }
1389
1390 static enum CRStatus
1391 init_style_font_size_field (CRStyle * a_style)
1392 {
1393         g_return_val_if_fail (a_style, CR_BAD_PARAM_ERROR);
1394
1395         memset (&a_style->font_size, 0, 
1396                sizeof (CRFontSizeVal)) ;
1397         /*
1398         if (!a_style->font_size) {
1399                 a_style->font_size = cr_font_size_new ();
1400                 if (!a_style->font_size) {
1401                         return CR_INSTANCIATION_FAILED_ERROR;
1402                 }
1403         } else {
1404                 cr_font_size_clear (a_style->font_size);
1405         }
1406         */
1407         return CR_OK;
1408 }
1409
1410 static enum CRStatus
1411 set_prop_font_size_from_value (CRStyle * a_style, CRTerm * a_value)
1412 {
1413         enum CRStatus status = CR_OK;
1414
1415         g_return_val_if_fail (a_style && a_value, CR_BAD_PARAM_ERROR);
1416
1417         switch (a_value->type) {
1418         case TERM_IDENT:
1419                 if (a_value->content.str
1420                     && a_value->content.str->stryng
1421                     && a_value->content.str->stryng->str
1422                     && !strcmp (a_value->content.str->stryng->str,
1423                                 "xx-small")) {
1424                         status = init_style_font_size_field (a_style);
1425                         g_return_val_if_fail (status == CR_OK, status);
1426
1427                         a_style->font_size.sv.type =
1428                                 PREDEFINED_ABSOLUTE_FONT_SIZE;
1429                         a_style->font_size.sv.value.predefined =
1430                                 FONT_SIZE_XX_SMALL;
1431
1432                 } else if (a_value->content.str
1433                            && a_value->content.str->stryng
1434                            && a_value->content.str->stryng->str
1435                            && !strcmp (a_value->content.str->stryng->str, 
1436                                        "x-small")) {
1437                         status = init_style_font_size_field (a_style);
1438                         g_return_val_if_fail (status == CR_OK, status);
1439
1440                         a_style->font_size.sv.type =
1441                                 PREDEFINED_ABSOLUTE_FONT_SIZE;
1442                         a_style->font_size.sv.value.predefined =
1443                                 FONT_SIZE_X_SMALL;
1444                 } else if (a_value->content.str
1445                            && a_value->content.str->stryng
1446                            && a_value->content.str->stryng->str
1447                            && !strcmp (a_value->content.str->stryng->str, 
1448                                        "small")) {
1449                         status = init_style_font_size_field (a_style);
1450                         g_return_val_if_fail (status == CR_OK, status);
1451
1452                         a_style->font_size.sv.type =
1453                                 PREDEFINED_ABSOLUTE_FONT_SIZE;
1454                         a_style->font_size.sv.value.predefined =
1455                                 FONT_SIZE_SMALL;
1456                 } else if (a_value->content.str
1457                            && a_value->content.str->stryng
1458                            && a_value->content.str->stryng->str
1459                            && !strcmp (a_value->content.str->stryng->str, "medium")) {
1460                         status = init_style_font_size_field (a_style);
1461                         g_return_val_if_fail (status == CR_OK, status);
1462
1463                         a_style->font_size.sv.type =
1464                                 PREDEFINED_ABSOLUTE_FONT_SIZE;
1465                         a_style->font_size.sv.value.predefined =
1466                                 FONT_SIZE_MEDIUM;
1467                 } else if (a_value->content.str
1468                            && a_value->content.str->stryng
1469                            && a_value->content.str->stryng->str
1470                            && !strcmp (a_value->content.str->stryng->str, 
1471                                        "large")) {
1472                         status = init_style_font_size_field (a_style);
1473                         g_return_val_if_fail (status == CR_OK, status);
1474
1475                         a_style->font_size.sv.type =
1476                                 PREDEFINED_ABSOLUTE_FONT_SIZE;
1477                         a_style->font_size.sv.value.predefined =
1478                                 FONT_SIZE_LARGE;
1479                 } else if (a_value->content.str
1480                            && a_value->content.str->stryng
1481                            && a_value->content.str->stryng->str
1482                            && !strcmp (a_value->content.str->stryng->str, 
1483                                        "x-large")) {
1484                         status = init_style_font_size_field (a_style);
1485                         g_return_val_if_fail (status == CR_OK, status);
1486
1487                         a_style->font_size.sv.type =
1488                                 PREDEFINED_ABSOLUTE_FONT_SIZE;
1489                         a_style->font_size.sv.value.predefined =
1490                                 FONT_SIZE_X_LARGE;
1491                 } else if (a_value->content.str
1492                            && a_value->content.str->stryng
1493                            && a_value->content.str->stryng->str
1494                            && !strcmp (a_value->content.str->stryng->str, 
1495                                        "xx-large")) {
1496                         status = init_style_font_size_field (a_style);
1497                         g_return_val_if_fail (status == CR_OK, status);
1498
1499                         a_style->font_size.sv.type =
1500                                 PREDEFINED_ABSOLUTE_FONT_SIZE;
1501                         a_style->font_size.sv.value.predefined =
1502                                 FONT_SIZE_XX_LARGE;
1503                 } else if (a_value->content.str
1504                            && a_value->content.str->stryng
1505                            && a_value->content.str->stryng->str
1506                            && !strcmp (a_value->content.str->stryng->str, 
1507                                        "larger")) {
1508                         status = init_style_font_size_field (a_style);
1509                         g_return_val_if_fail (status == CR_OK, status);
1510
1511                         a_style->font_size.sv.type = RELATIVE_FONT_SIZE;
1512                         a_style->font_size.sv.value.relative = FONT_SIZE_LARGER;
1513                 } else if (a_value->content.str
1514                            && a_value->content.str->stryng
1515                            && a_value->content.str->stryng->str
1516                            && !strcmp (a_value->content.str->stryng->str, 
1517                                        "smaller")) {
1518                         status = init_style_font_size_field (a_style);
1519                         g_return_val_if_fail (status == CR_OK, status);
1520
1521                         a_style->font_size.sv.type = RELATIVE_FONT_SIZE;
1522                         a_style->font_size.sv.value.relative =
1523                                 FONT_SIZE_SMALLER;
1524                 } else if (a_value->content.str
1525                            && a_value->content.str->stryng
1526                            && a_value->content.str->stryng->str
1527                            && !strcmp (a_value->content.str->stryng->str, "inherit")) {
1528                         status = init_style_font_size_field (a_style);
1529                         g_return_val_if_fail (status == CR_OK, status);
1530                         a_style->font_size.sv.type = INHERITED_FONT_SIZE;
1531
1532                 } else {
1533                         cr_utils_trace_info ("Unknow value of font-size") ;
1534                         status = init_style_font_size_field (a_style);
1535                         return CR_UNKNOWN_PROP_VAL_ERROR;
1536                 }
1537                 break;
1538
1539         case TERM_NUMBER:
1540                 if (a_value->content.num) {
1541                         status = init_style_font_size_field (a_style);
1542                         g_return_val_if_fail (status == CR_OK, status);
1543
1544                         a_style->font_size.sv.type = ABSOLUTE_FONT_SIZE;
1545                         cr_num_copy (&a_style->font_size.sv.value.absolute,
1546                                      a_value->content.num) ;
1547                 }
1548                 break;
1549
1550         default:
1551                 status = init_style_font_size_field (a_style);
1552                 return CR_UNKNOWN_PROP_VAL_ERROR;
1553         }
1554         return CR_OK;
1555 }
1556
1557 static enum CRStatus
1558 set_prop_font_style_from_value (CRStyle * a_style, CRTerm * a_value)
1559 {
1560         enum CRStatus status = CR_OK;
1561
1562         g_return_val_if_fail (a_style && a_value, CR_BAD_PARAM_ERROR);
1563
1564         switch (a_value->type) {
1565         case TERM_IDENT:
1566                 if (a_value->content.str 
1567                     && a_value->content.str->stryng
1568                     && a_value->content.str->stryng->str) {
1569                         if (!strcmp (a_value->content.str->stryng->str, "normal")) {
1570                                 a_style->font_style = FONT_STYLE_NORMAL;
1571                         } else if (!strcmp
1572                                    (a_value->content.str->stryng->str,
1573                                     "italic")) {
1574                                 a_style->font_style = FONT_STYLE_ITALIC;
1575                         } else if (!strcmp
1576                                    (a_value->content.str->stryng->str,
1577                                     "oblique")) {
1578                                 a_style->font_style = FONT_STYLE_OBLIQUE;
1579                         } else if (!strcmp
1580                                    (a_value->content.str->stryng->str,
1581                                     "inherit")) {
1582                                 a_style->font_style = FONT_STYLE_INHERIT;
1583                         } else {
1584                                 status = CR_UNKNOWN_PROP_VAL_ERROR;
1585                         }
1586                 }
1587                 break;
1588
1589         default:
1590                 status = CR_UNKNOWN_PROP_VAL_ERROR;
1591                 break;
1592         }
1593
1594         return status;
1595 }
1596
1597 static enum CRStatus
1598 set_prop_font_weight_from_value (CRStyle * a_style, CRTerm * a_value)
1599 {
1600         enum CRStatus status = CR_OK;
1601
1602         g_return_val_if_fail (a_style && a_value, CR_BAD_PARAM_ERROR);
1603
1604         switch (a_value->type) {
1605         case TERM_IDENT:
1606                 if (a_value->content.str 
1607                     && a_value->content.str->stryng
1608                     && a_value->content.str->stryng->str) {
1609                         if (!strcmp (a_value->content.str->stryng->str, 
1610                                      "normal")) {
1611                                 a_style->font_weight = FONT_WEIGHT_NORMAL;
1612                         } else if (!strcmp (a_value->content.str->stryng->str,
1613                                             "bold")) {
1614                                 a_style->font_weight = FONT_WEIGHT_BOLD;
1615                         } else if (!strcmp (a_value->content.str->stryng->str,
1616                                             "bolder")) {
1617                                 a_style->font_weight = FONT_WEIGHT_BOLDER;
1618                         } else if (!strcmp (a_value->content.str->stryng->str,
1619                                             "lighter")) {
1620                                 a_style->font_weight = FONT_WEIGHT_LIGHTER;
1621                         } else if (!strcmp (a_value->content.str->stryng->str,
1622                                             "inherit")) {
1623                                 a_style->font_weight = FONT_WEIGHT_INHERIT;
1624
1625                         } else {
1626                                 status = CR_UNKNOWN_PROP_VAL_ERROR;
1627                         }
1628
1629                 }
1630                 break;
1631
1632         case TERM_NUMBER:
1633                 if (a_value->content.num
1634                     && (a_value->content.num->type == NUM_GENERIC
1635                         || a_value->content.num->type == NUM_AUTO)) {
1636                         if (a_value->content.num->val <= 150) {
1637                                 a_style->font_weight = FONT_WEIGHT_100;
1638                         } else if (a_value->content.num->val <= 250) {
1639                                 a_style->font_weight = FONT_WEIGHT_200;
1640                         } else if (a_value->content.num->val <= 350) {
1641                                 a_style->font_weight = FONT_WEIGHT_300;
1642                         } else if (a_value->content.num->val <= 450) {
1643                                 a_style->font_weight = FONT_WEIGHT_400;
1644                         } else if (a_value->content.num->val <= 550) {
1645                                 a_style->font_weight = FONT_WEIGHT_500;
1646                         } else if (a_value->content.num->val <= 650) {
1647                                 a_style->font_weight = FONT_WEIGHT_600;
1648                         } else if (a_value->content.num->val <= 750) {
1649                                 a_style->font_weight = FONT_WEIGHT_700;
1650                         } else if (a_value->content.num->val <= 850) {
1651                                 a_style->font_weight = FONT_WEIGHT_800;
1652                         } else {
1653                                 a_style->font_weight = FONT_WEIGHT_900;
1654                         }
1655                 }
1656                 break;
1657
1658         default:
1659                 status = CR_UNKNOWN_PROP_VAL_ERROR;
1660                 break;
1661         }
1662
1663         return status;
1664 }
1665
1666 static enum CRStatus
1667 set_prop_white_space_from_value (CRStyle * a_style, CRTerm * a_value)
1668 {
1669         enum CRStatus status = CR_OK;
1670
1671         g_return_val_if_fail (a_style && a_value, CR_BAD_PARAM_ERROR);
1672
1673         switch (a_value->type) {
1674         case TERM_IDENT:
1675                 if (a_value->content.str && a_value->content.str->stryng) {
1676                         if (!strcmp (a_value->content.str->stryng->str, "normal")) {
1677                                 a_style->white_space = WHITE_SPACE_NORMAL;
1678                         } else if (!strcmp (a_value->content.str->stryng->str, 
1679                                             "pre")) {
1680                                 a_style->font_weight = WHITE_SPACE_PRE;
1681                         } else if (!strcmp (a_value->content.str->stryng->str,
1682                                             "nowrap")) {
1683                                 a_style->white_space = WHITE_SPACE_NOWRAP;
1684                         } else if (!strcmp (a_value->content.str->stryng->str,
1685                                             "inherit")) {
1686                                 a_style->white_space = WHITE_SPACE_INHERIT;
1687                         } else {
1688                                 status = CR_UNKNOWN_PROP_VAL_ERROR;
1689                         }
1690                 }
1691                 break;
1692         default:
1693                 status = CR_UNKNOWN_PROP_VAL_ERROR;
1694                 break;
1695         }
1696
1697         return status;
1698 }
1699
1700 /******************
1701  *Public methods
1702  ******************/
1703
1704 /**
1705  *Default constructor of #CRStyle.
1706  *@param a_set_props_to_initial_values if TRUE, the style properties
1707  *will be set to the default values. Only the style properties of the
1708  *root box should be set to their initial values.
1709  *Otherwise, the style values are set to their default value.
1710  *Read the CSS2 spec, chapters 6.1.1 to 6.2.
1711  */
1712 CRStyle *
1713 cr_style_new (gboolean a_set_props_to_initial_values)
1714 {
1715         CRStyle *result = NULL;
1716
1717         result = g_try_malloc (sizeof (CRStyle));
1718         if (!result) {
1719                 cr_utils_trace_info ("Out of memory");
1720                 return NULL;
1721         }
1722         memset (result, 0, sizeof (CRStyle));
1723         gv_prop_hash_ref_count++;
1724
1725         if (a_set_props_to_initial_values == TRUE) {
1726                 cr_style_set_props_to_initial_values (result);
1727         } else {
1728                 cr_style_set_props_to_default_values (result);
1729         }
1730
1731         return result;
1732 }
1733
1734 /**
1735  *Sets the style properties to their default values according to the css2 spec
1736  * i.e inherit if the property is inherited, its initial value otherwise.
1737  *@param a_this the current instance of #CRStyle.
1738  *@return CR_OK upon successfull completion, an error code otherwise.
1739  */
1740 enum CRStatus 
1741 cr_style_set_props_to_default_values (CRStyle * a_this)
1742 {
1743         glong i = 0;
1744
1745         g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
1746         
1747         for (i = 0; i < NB_NUM_PROPS; i++)
1748         {
1749                 switch (i)
1750                 {
1751                 case NUM_PROP_WIDTH:
1752                 case NUM_PROP_TOP:
1753                 case NUM_PROP_RIGHT:
1754                 case NUM_PROP_BOTTOM:
1755                 case NUM_PROP_LEFT:
1756                         cr_num_set (&a_this->num_props[i].sv, 0, NUM_AUTO);
1757                         break;
1758
1759                 case NUM_PROP_PADDING_TOP:
1760                 case NUM_PROP_PADDING_RIGHT:
1761                 case NUM_PROP_PADDING_BOTTOM:
1762                 case NUM_PROP_PADDING_LEFT:
1763                 case NUM_PROP_BORDER_TOP:
1764                 case NUM_PROP_BORDER_RIGHT:
1765                 case NUM_PROP_BORDER_BOTTOM:
1766                 case NUM_PROP_BORDER_LEFT:
1767                 case NUM_PROP_MARGIN_TOP:
1768                 case NUM_PROP_MARGIN_RIGHT:
1769                 case NUM_PROP_MARGIN_BOTTOM:
1770                 case NUM_PROP_MARGIN_LEFT:
1771                         cr_num_set (&a_this->num_props[i].sv,
1772                                     0, NUM_LENGTH_PX);
1773                         break;
1774
1775                 default:
1776                         cr_utils_trace_info ("Unknown property");
1777                         break;
1778                 }
1779         }
1780
1781         for (i = 0; i < NB_RGB_PROPS; i++) {
1782                 
1783                 switch (i) {
1784                         /*default foreground color is black */
1785                 case RGB_PROP_COLOR:
1786                         /*
1787                          *REVIEW: color is inherited and the default value is
1788                          *ua dependant.
1789                          */
1790                         cr_rgb_set_to_inherit (&a_this->rgb_props[i].sv,
1791                                                TRUE) ;
1792                         break;
1793
1794                         /*default background color is white */
1795                 case RGB_PROP_BACKGROUND_COLOR:
1796                         /* TODO: the default value should be transparent */
1797                         cr_rgb_set (&a_this->rgb_props[i].sv,
1798                                     255, 255, 255, FALSE);
1799                         cr_rgb_set_to_transparent (&a_this->rgb_props[i].sv,
1800                                                    TRUE) ;
1801                         break;
1802
1803                 default:
1804                         /* 
1805                          *TODO: for BORDER_COLOR the initial value should
1806                          * be the same as COLOR 
1807                          */
1808                         cr_rgb_set (&a_this->rgb_props[i].sv, 0, 0, 0,
1809                                     FALSE);
1810                         break;
1811                 }
1812         }
1813
1814         for (i = 0; i < NB_BORDER_STYLE_PROPS; i++) {
1815                 a_this->border_style_props[i] = BORDER_STYLE_NONE;
1816         }
1817
1818         a_this->display = DISPLAY_INLINE;
1819         a_this->position = POSITION_STATIC;
1820         a_this->float_type = FLOAT_NONE;
1821         a_this->parent_style = NULL;
1822         a_this->font_style = FONT_STYLE_INHERIT;
1823         a_this->font_variant = FONT_VARIANT_INHERIT;
1824         a_this->font_weight = FONT_WEIGHT_INHERIT;
1825         a_this->font_family = NULL;
1826         
1827         cr_font_size_set_to_inherit (&a_this->font_size.sv) ;
1828         cr_font_size_clear (&a_this->font_size.cv) ;
1829         cr_font_size_clear (&a_this->font_size.av) ;
1830
1831         /* To make the inheritance resolution possible and efficient */
1832         a_this->inherited_props_resolved = FALSE ;
1833         return CR_OK;
1834 }
1835
1836 /**
1837  *Sets the style properties to their initial value according to the css2 spec.
1838  *This function should be used to initialize the style of the root element
1839  *of an xml tree.
1840  *Some properties are user agent dependant like font-family, and
1841  *are not initialized, read the spec to make you renderer compliant.
1842  *@param a_this the current instance of #CRStyle.
1843  *@return CR_OK upon successfull completion, an error code otherwise.
1844  */
1845 enum CRStatus 
1846 cr_style_set_props_to_initial_values (CRStyle *a_this)
1847 {
1848         glong i = 0;
1849
1850         g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
1851
1852         for (i = 0; i < NB_NUM_PROPS; i++) {
1853                 switch (i) {
1854                 case NUM_PROP_WIDTH:
1855                         cr_num_set (&a_this->num_props[i].sv, 800,
1856                                     NUM_LENGTH_PX) ;
1857                         break ;
1858                 case NUM_PROP_TOP:
1859                 case NUM_PROP_RIGHT:
1860                 case NUM_PROP_BOTTOM:
1861                 case NUM_PROP_LEFT:
1862                         cr_num_set (&a_this->num_props[i].sv, 0, NUM_AUTO);
1863                         break;
1864
1865                 case NUM_PROP_PADDING_TOP:
1866                 case NUM_PROP_PADDING_RIGHT:
1867                 case NUM_PROP_PADDING_BOTTOM:
1868                 case NUM_PROP_PADDING_LEFT:
1869                 case NUM_PROP_BORDER_TOP:
1870                 case NUM_PROP_BORDER_RIGHT:
1871                 case NUM_PROP_BORDER_BOTTOM:
1872                 case NUM_PROP_BORDER_LEFT:
1873                 case NUM_PROP_MARGIN_TOP:
1874                 case NUM_PROP_MARGIN_RIGHT:
1875                 case NUM_PROP_MARGIN_BOTTOM:
1876                 case NUM_PROP_MARGIN_LEFT:
1877                         cr_num_set (&a_this->num_props[i].sv,
1878                                     0, NUM_LENGTH_PX);
1879                         break;
1880
1881                 default:
1882                         cr_utils_trace_info ("Unknown property");
1883                         break;
1884                 }
1885         }
1886
1887         for (i = 0; i < NB_RGB_PROPS; i++) {
1888
1889                 switch (i) {
1890                         /*default foreground color is black */
1891                 case RGB_PROP_COLOR:
1892                         cr_rgb_set (&a_this->rgb_props[i].sv, 0, 0, 0, FALSE);
1893                         break;
1894
1895                         /*default background color is white */
1896                 case RGB_PROP_BACKGROUND_COLOR:
1897                         cr_rgb_set (&a_this->rgb_props[i].sv,
1898                                     255, 255, 255, FALSE);
1899                         cr_rgb_set_to_transparent (&a_this->rgb_props[i].sv,
1900                                                    TRUE) ;                        
1901                         break;
1902                 default:
1903                         cr_rgb_set (&a_this->rgb_props[i].sv, 0, 0, 0, FALSE);
1904                         break;
1905                 }
1906         }
1907
1908         for (i = 0; i < NB_BORDER_STYLE_PROPS; i++) {
1909                 a_this->border_style_props[i] = BORDER_STYLE_NONE;
1910         }
1911
1912         a_this->display = DISPLAY_BLOCK;
1913         a_this->position = POSITION_STATIC;
1914         a_this->float_type = FLOAT_NONE;
1915         a_this->font_style = FONT_STYLE_NORMAL;
1916         a_this->font_variant = FONT_VARIANT_NORMAL;
1917         a_this->font_weight = FONT_WEIGHT_NORMAL;
1918         a_this->font_stretch = FONT_STRETCH_NORMAL;
1919         a_this->white_space = WHITE_SPACE_NORMAL;
1920         cr_font_size_set_predefined_absolute_font_size
1921                 (&a_this->font_size.sv, FONT_SIZE_MEDIUM) ;
1922         a_this->inherited_props_resolved = FALSE ;
1923
1924         return CR_OK;
1925 }
1926
1927 /**
1928  *Resolves the inherited properties.
1929  *The function sets the "inherited" properties to either the value of
1930  *their parent properties.
1931  *This function is *NOT* recursive. So the inherited properties of
1932  *the parent style must have been resolved prior to calling this function.
1933  *@param a_this the instance where 
1934  *@return CR_OK if a root node is found and the propagation is successful,
1935  *an error code otherwise
1936  */
1937 enum CRStatus 
1938 cr_style_resolve_inherited_properties (CRStyle *a_this)
1939 {
1940         enum CRStatus ret = CR_OK;
1941         glong i = 0;
1942
1943         g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
1944         g_return_val_if_fail (a_this->parent_style, CR_BAD_PARAM_ERROR) ;
1945
1946         if (a_this->inherited_props_resolved == TRUE)
1947                 return CR_OK ;
1948
1949         for (i=0 ; i < NB_NUM_PROPS ;i++) {
1950                 if (a_this->num_props[i].sv.type == NUM_INHERIT) {
1951                         cr_num_copy (&a_this->num_props[i].cv,
1952                                      &a_this->parent_style->num_props[i].cv);
1953                 }
1954         }
1955         for (i=0; i < NB_RGB_PROPS; i++) {
1956                 if (cr_rgb_is_set_to_inherit (&a_this->rgb_props[i].sv) == TRUE) {
1957                         cr_rgb_copy (
1958                                 &a_this->rgb_props[i].cv,
1959                                 &a_this->parent_style->rgb_props[i].cv);
1960                 }
1961         }
1962         for (i = 0; i < NB_BORDER_STYLE_PROPS; i++) {
1963                 if (a_this->border_style_props[i] == BORDER_STYLE_INHERIT) {
1964                         a_this->border_style_props[i] =
1965                           a_this->parent_style->border_style_props[i];
1966                 }
1967         }
1968
1969         if (a_this->display == DISPLAY_INHERIT) {
1970                 a_this->display = a_this->parent_style->display;
1971         }
1972         if (a_this->position == POSITION_INHERIT) {
1973                 a_this->position = a_this->parent_style->position;
1974         }
1975         if (a_this->float_type == FLOAT_INHERIT) {
1976                 a_this->float_type = a_this->parent_style->float_type;
1977         }
1978         if (a_this->font_style == FONT_STYLE_INHERIT) {
1979                 a_this->font_style = a_this->parent_style->font_style;
1980         }
1981         if (a_this->font_variant == FONT_VARIANT_INHERIT) {
1982                 a_this->font_variant = a_this->parent_style->font_variant;
1983         }
1984         if (a_this->font_weight == FONT_WEIGHT_INHERIT) {
1985                 a_this->font_weight = a_this->parent_style->font_weight;
1986         }
1987         if (a_this->font_stretch == FONT_STRETCH_INHERIT) {
1988                 a_this->font_stretch = a_this->parent_style->font_stretch;
1989         }
1990         /*NULL is inherit marker for font_famiy*/
1991         if (a_this->font_family == NULL)  {
1992                 a_this->font_family = a_this->parent_style->font_family;
1993         }
1994         if (a_this->font_size.sv.type == INHERITED_FONT_SIZE) {
1995                 cr_font_size_copy (&a_this->font_size.cv,
1996                                    &a_this->parent_style->font_size.cv) ;
1997         }
1998         a_this->inherited_props_resolved = TRUE ;
1999         return ret;
2000 }
2001
2002 /**
2003  *Walks through a css2 property declaration, and populated the
2004  *according field(s) in the #CRStyle structure.
2005  *If the properties or their value(s) are/is not known, 
2006  *sets the corresponding field(s) of #CRStyle to its/their default 
2007  *value(s)
2008  *@param a_this the instance of #CRStyle to set.
2009  *@param a_decl the declaration from which the #CRStyle fields are set.
2010  *@return CR_OK upon successfull completion, an error code otherwise.
2011  */
2012 enum CRStatus
2013 cr_style_set_style_from_decl (CRStyle * a_this, CRDeclaration * a_decl)
2014 {
2015         CRTerm *value = NULL;
2016         enum CRStatus status = CR_OK;
2017
2018         enum CRPropertyID prop_id = PROP_ID_NOT_KNOWN;
2019
2020         g_return_val_if_fail (a_this && a_decl
2021                               && a_decl
2022                               && a_decl->property
2023                               && a_decl->property->stryng
2024                               && a_decl->property->stryng->str,
2025                               CR_BAD_PARAM_ERROR);
2026
2027         prop_id = cr_style_get_prop_id
2028                 (a_decl->property->stryng->str);
2029
2030         value = a_decl->value;
2031         switch (prop_id) {
2032         case PROP_ID_PADDING_TOP:
2033                 status = set_prop_padding_x_from_value
2034                         (a_this, value, DIR_TOP);
2035                 break;
2036
2037         case PROP_ID_PADDING_RIGHT:
2038                 status = set_prop_padding_x_from_value
2039                         (a_this, value, DIR_RIGHT);
2040                 break;
2041         case PROP_ID_PADDING_BOTTOM:
2042                 status = set_prop_padding_x_from_value
2043                         (a_this, value, DIR_BOTTOM);
2044                 break;
2045
2046         case PROP_ID_PADDING_LEFT:
2047                 status = set_prop_padding_x_from_value
2048                         (a_this, value, DIR_LEFT);
2049                 break;
2050
2051         case PROP_ID_PADDING:
2052                 status = set_prop_padding_from_value (a_this, value) ;
2053                 break;
2054
2055         case PROP_ID_BORDER_TOP_WIDTH:
2056                 status = set_prop_border_x_width_from_value (a_this, value,
2057                                                              DIR_TOP);
2058                 break;
2059
2060         case PROP_ID_BORDER_RIGHT_WIDTH:
2061                 status = set_prop_border_x_width_from_value (a_this, value,
2062                                                              DIR_RIGHT);
2063                 break;
2064
2065         case PROP_ID_BORDER_BOTTOM_WIDTH:
2066                 status = set_prop_border_x_width_from_value (a_this, value,
2067                                                              DIR_BOTTOM);
2068                 break;
2069
2070         case PROP_ID_BORDER_LEFT_WIDTH:
2071                 status = set_prop_border_x_width_from_value (a_this, value,
2072                                                              DIR_LEFT);
2073                 break;
2074
2075         case PROP_ID_BORDER_WIDTH:
2076                 status = set_prop_border_width_from_value (a_this, value) ;
2077                 break ;
2078
2079         case PROP_ID_BORDER_TOP_STYLE:
2080                 status = set_prop_border_x_style_from_value (a_this, value,
2081                                                              DIR_TOP);
2082                 break;
2083
2084         case PROP_ID_BORDER_RIGHT_STYLE:
2085                 status = set_prop_border_x_style_from_value (a_this, value,
2086                                                              DIR_RIGHT);
2087                 break;
2088
2089         case PROP_ID_BORDER_BOTTOM_STYLE:
2090                 status = set_prop_border_x_style_from_value (a_this, value,
2091                                                              DIR_BOTTOM);
2092                 break;
2093
2094         case PROP_ID_BORDER_LEFT_STYLE:
2095                 status = set_prop_border_x_style_from_value (a_this, value,
2096                                                              DIR_LEFT);
2097                 break;
2098
2099         case PROP_ID_BORDER_STYLE:
2100                 status = set_prop_border_style_from_value (a_this, value) ;
2101                 break ;
2102
2103         case PROP_ID_BORDER_TOP_COLOR:
2104                 status = set_prop_border_x_color_from_value (a_this, value,
2105                                                              DIR_TOP);
2106                 break;
2107
2108         case PROP_ID_BORDER_RIGHT_COLOR:
2109                 status = set_prop_border_x_color_from_value (a_this, value,
2110                                                              DIR_RIGHT);
2111                 break;
2112
2113         case PROP_ID_BORDER_BOTTOM_COLOR:
2114                 status = set_prop_border_x_color_from_value (a_this, value,
2115                                                              DIR_BOTTOM);
2116                 break;
2117
2118         case PROP_ID_BORDER_LEFT_COLOR:
2119                 status = set_prop_border_x_color_from_value (a_this, value,
2120                                                              DIR_BOTTOM);
2121                 break;
2122
2123         case PROP_ID_BORDER_TOP:
2124                 status = set_prop_border_x_from_value (a_this, value,
2125                                                        DIR_TOP);
2126                 break;
2127
2128         case PROP_ID_BORDER_RIGHT:
2129                 status = set_prop_border_x_from_value (a_this, value,
2130                                                        DIR_RIGHT);
2131                 break;
2132
2133         case PROP_ID_BORDER_BOTTOM:
2134                 status = set_prop_border_x_from_value (a_this, value,
2135                                                        DIR_BOTTOM);
2136                 break;
2137
2138         case PROP_ID_BORDER_LEFT:
2139                 status = set_prop_border_x_from_value (a_this, value,
2140                                                        DIR_LEFT);
2141                 break;
2142
2143         case PROP_ID_MARGIN_TOP:
2144                 status = set_prop_margin_x_from_value (a_this, value,
2145                                                        DIR_TOP);
2146                 break;
2147
2148         case PROP_ID_BORDER:
2149                 status = set_prop_border_from_value (a_this, value);
2150                 break;
2151
2152         case PROP_ID_MARGIN_RIGHT:
2153                 status = set_prop_margin_x_from_value (a_this, value,
2154                                                        DIR_RIGHT);
2155                 break;
2156
2157         case PROP_ID_MARGIN_BOTTOM:
2158                 status = set_prop_margin_x_from_value (a_this, value,
2159                                                        DIR_BOTTOM);
2160                 break;
2161
2162         case PROP_ID_MARGIN_LEFT:
2163                 status = set_prop_margin_x_from_value (a_this, value,
2164                                                        DIR_LEFT);
2165                 break;
2166
2167         case PROP_ID_MARGIN:
2168                 status = set_prop_margin_from_value (a_this, value);
2169                 break;
2170
2171         case PROP_ID_DISPLAY:
2172                 status = set_prop_display_from_value (a_this, value);
2173                 break;
2174
2175         case PROP_ID_POSITION:
2176                 status = set_prop_position_from_value (a_this, value);
2177                 break;
2178
2179         case PROP_ID_TOP:
2180                 status = set_prop_x_from_value (a_this, value, DIR_TOP);
2181                 break;
2182
2183         case PROP_ID_RIGHT:
2184                 status = set_prop_x_from_value (a_this, value, DIR_RIGHT);
2185                 break;
2186
2187         case PROP_ID_BOTTOM:
2188                 status = set_prop_x_from_value (a_this, value, DIR_BOTTOM);
2189                 break;
2190
2191         case PROP_ID_LEFT:
2192                 status = set_prop_x_from_value (a_this, value, DIR_LEFT);
2193                 break;
2194
2195         case PROP_ID_FLOAT:
2196                 status = set_prop_float (a_this, value);
2197                 break;
2198
2199         case PROP_ID_WIDTH:
2200                 status = set_prop_width (a_this, value);
2201                 break;
2202
2203         case PROP_ID_COLOR:
2204                 status = set_prop_color (a_this, value);
2205                 break;
2206
2207         case PROP_ID_BACKGROUND_COLOR:
2208                 status = set_prop_background_color (a_this, value);
2209                 break;
2210
2211         case PROP_ID_FONT_FAMILY:
2212                 status = set_prop_font_family_from_value (a_this, value);
2213                 break;
2214
2215         case PROP_ID_FONT_SIZE:
2216                 status = set_prop_font_size_from_value (a_this, value);
2217                 break;
2218
2219         case PROP_ID_FONT_STYLE:
2220                 status = set_prop_font_style_from_value (a_this, value);
2221                 break;
2222
2223         case PROP_ID_FONT_WEIGHT:
2224                 status = set_prop_font_weight_from_value (a_this, value);
2225                 break;
2226
2227         case PROP_ID_WHITE_SPACE:
2228                 status = set_prop_white_space_from_value(a_this, value);
2229                 break;
2230
2231         default:
2232                 return CR_UNKNOWN_TYPE_ERROR;
2233
2234         }
2235
2236         return status;
2237 }
2238
2239 /**
2240  *Increases the reference count
2241  *of the current instance of #CRStyle.
2242  *@param a_this the current instance of #CRStyle.
2243  *@return CR_OK upon successfull completion, an error code
2244  *otherwise.
2245  */
2246 enum CRStatus
2247 cr_style_ref (CRStyle * a_this)
2248 {
2249         g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
2250
2251         a_this->ref_count++;
2252         return CR_OK;
2253 }
2254
2255 /**
2256  *Decreases the reference count of
2257  *the current instance of #CRStyle.
2258  *If the reference count reaches 0, the
2259  *instance of #CRStyle is destoyed.
2260  *@param a_this the current instance of #CRStyle.
2261  *@return TRUE if the instance has been destroyed, FALSE
2262  *otherwise.
2263  */
2264 gboolean
2265 cr_style_unref (CRStyle * a_this)
2266 {
2267         g_return_val_if_fail (a_this, FALSE);
2268
2269         if (a_this->ref_count)
2270                 a_this->ref_count--;
2271
2272         if (!a_this->ref_count) {
2273                 cr_style_destroy (a_this);
2274                 return TRUE;
2275         }
2276
2277         return FALSE;
2278 }
2279
2280 /**
2281  *Duplicates the current instance of #CRStyle .
2282  *The newly created instance of #CRStyle must be
2283  *freed using cr_style_destroy ().
2284  *@param a_this the current instance of #CRStyle.
2285  *@return the newly duplicated instance of #CRStyle.
2286  */
2287 CRStyle *
2288 cr_style_dup (CRStyle * a_this)
2289 {
2290         CRStyle *result = NULL;
2291
2292         g_return_val_if_fail (a_this, NULL);
2293
2294         result = cr_style_new (FALSE);
2295         if (!result) {
2296                 cr_utils_trace_info ("Out of memory");
2297                 return NULL;
2298         }
2299         cr_style_copy (result, a_this);
2300         return result;
2301 }
2302
2303 /**
2304  *Copies a style data structure into another.
2305  *TODO: this is actually broken because it's based
2306  *on memcpy although some data stuctures of CRStyle should
2307  *be properly duplicated.
2308  *@param a_dest the destination style datastructure
2309  *@param a_src the source style datastructure.
2310  *@return CR_OK upon succesfull completion, an error code otherwise
2311  */
2312 enum CRStatus
2313 cr_style_copy (CRStyle * a_dest, CRStyle * a_src)
2314 {
2315         g_return_val_if_fail (a_dest && a_src, CR_BAD_PARAM_ERROR);
2316
2317         memcpy (a_dest, a_src, sizeof (CRStyle));
2318         return CR_OK;
2319 }
2320
2321 /**
2322  *dump a CRNumpPropVal in a string.
2323  *@param a_prop_val the numerical property value to dump
2324  *@param a_str the string to dump the numerical propertie into.
2325  *Note that the string value is appended to a_str.
2326  *@param a_nb_indent the number white chars of indentation.
2327  */
2328 enum CRStatus
2329 cr_style_num_prop_val_to_string (CRNumPropVal * a_prop_val,
2330                                  GString * a_str, guint a_nb_indent)
2331 {
2332         enum CRStatus status = CR_OK;
2333         guchar *tmp_str = NULL;
2334         GString *str = NULL;
2335
2336         g_return_val_if_fail (a_prop_val && a_str, CR_BAD_PARAM_ERROR);
2337
2338         str = g_string_new (NULL);
2339         cr_utils_dump_n_chars2 (' ', str, a_nb_indent);
2340         g_string_append (str, "NumPropVal {");
2341         tmp_str = cr_num_to_string (&a_prop_val->sv);
2342         if (!tmp_str) {
2343                 status = CR_ERROR;
2344                 goto cleanup;
2345         }
2346         g_string_append_printf (str, "sv: %s ", tmp_str);
2347         g_free (tmp_str);
2348         tmp_str = NULL;
2349         
2350         tmp_str = cr_num_to_string (&a_prop_val->cv);
2351         if (!tmp_str) {
2352                 status = CR_ERROR;
2353                 goto cleanup;
2354         }
2355         g_string_append_printf (str, "cv: %s ", tmp_str);
2356         g_free (tmp_str);
2357         tmp_str = NULL;
2358
2359         tmp_str = cr_num_to_string (&a_prop_val->av);
2360         if (!tmp_str) {
2361                 status = CR_ERROR;
2362                 goto cleanup;
2363         }
2364         g_string_append_printf (str, "av: %s ", tmp_str);
2365         g_free (tmp_str);
2366         tmp_str = NULL;
2367         g_string_append (str, "}");
2368         g_string_append (a_str, str->str);
2369         status = CR_OK;
2370       cleanup:
2371
2372         if (tmp_str) {
2373                 g_free (tmp_str);
2374                 tmp_str = NULL;
2375         }
2376         if (str) {
2377                 g_string_free (str, TRUE);
2378         }
2379         return status;
2380 }
2381
2382 enum CRStatus
2383 cr_style_rgb_prop_val_to_string (CRRgbPropVal * a_prop_val,
2384                                  GString * a_str, guint a_nb_indent)
2385 {
2386         enum CRStatus status = CR_OK;
2387         guchar *tmp_str = NULL;
2388         GString *str = NULL;
2389
2390         g_return_val_if_fail (a_prop_val && a_str, CR_BAD_PARAM_ERROR);
2391
2392         str = g_string_new (NULL);
2393
2394         cr_utils_dump_n_chars2 (' ', str, a_nb_indent);
2395         g_string_append (str, "RGBPropVal {");
2396         tmp_str = cr_rgb_to_string (&a_prop_val->sv);
2397         if (!tmp_str) {
2398                 status = CR_ERROR;
2399                 goto cleanup;
2400         }
2401         g_string_append_printf (str, "sv: %s ", tmp_str);
2402         g_free (tmp_str);
2403         tmp_str = NULL;
2404         tmp_str = cr_rgb_to_string (&a_prop_val->cv);
2405         if (!tmp_str) {
2406                 status = CR_ERROR;
2407                 goto cleanup;
2408         }
2409         g_string_append_printf (str, "cv: %s ", tmp_str);
2410         g_free (tmp_str);
2411         tmp_str = NULL;
2412         tmp_str = cr_rgb_to_string (&a_prop_val->av);
2413         if (!tmp_str) {
2414                 status = CR_ERROR;
2415                 goto cleanup;
2416         }
2417         g_string_append_printf (str, "av: %s ", tmp_str);
2418         g_free (tmp_str);
2419         tmp_str = NULL;
2420
2421         g_string_append (str, "}");
2422         g_string_append (a_str, str->str);
2423         status = CR_OK;
2424       cleanup:
2425
2426         if (tmp_str) {
2427                 g_free (tmp_str);
2428                 tmp_str = NULL;
2429         }
2430         if (str) {
2431                 g_string_free (str, TRUE);
2432         }
2433         return status;
2434 }
2435
2436 enum CRStatus
2437 cr_style_border_style_to_string (enum CRBorderStyle a_prop,
2438                                  GString * a_str, guint a_nb_indent)
2439 {
2440         gchar *str = NULL;
2441
2442         g_return_val_if_fail (a_str, CR_BAD_PARAM_ERROR);
2443
2444         switch (a_prop) {
2445         case BORDER_STYLE_NONE:
2446                 str = (gchar *) "border-style-none";
2447                 break;
2448         case BORDER_STYLE_HIDDEN:
2449                 str = (gchar *) "border-style-hidden";
2450                 break;
2451         case BORDER_STYLE_DOTTED:
2452                 str = (gchar *) "border-style-dotted";
2453                 break;
2454         case BORDER_STYLE_DASHED:
2455                 str = (gchar *) "border-style-dashed";
2456                 break;
2457         case BORDER_STYLE_SOLID:
2458                 str = (gchar *) "border-style-solid";
2459                 break;
2460         case BORDER_STYLE_DOUBLE:
2461                 str = (gchar *) "border-style-double";
2462                 break;
2463         case BORDER_STYLE_GROOVE:
2464                 str = (gchar *) "border-style-groove";
2465                 break;
2466         case BORDER_STYLE_RIDGE:
2467                 str = (gchar *) "border-style-ridge";
2468                 break;
2469         case BORDER_STYLE_INSET:
2470                 str = (gchar *) "border-style-inset";
2471                 break;
2472         case BORDER_STYLE_OUTSET:
2473                 str = (gchar *) "border-style-outset";
2474                 break;
2475         default:
2476                 str = (gchar *) "unknown border style";
2477                 break;
2478         }
2479         cr_utils_dump_n_chars2 (' ', a_str, a_nb_indent);
2480         g_string_append (a_str, str);
2481         return CR_OK;
2482 }
2483
2484 enum CRStatus
2485 cr_style_display_type_to_string (enum CRDisplayType a_code,
2486                                  GString * a_str, guint a_nb_indent)
2487 {
2488         gchar *str = NULL;
2489
2490         g_return_val_if_fail (a_str, CR_BAD_PARAM_ERROR);
2491
2492         switch (a_code) {
2493         case DISPLAY_NONE:
2494                 str = (gchar *) "display-none";
2495                 break;
2496         case DISPLAY_INLINE:
2497                 str = (gchar *) "display-inline";
2498                 break;
2499         case DISPLAY_BLOCK:
2500                 str = (gchar *) "display-block";
2501                 break;
2502         case DISPLAY_LIST_ITEM:
2503                 str = (gchar *) "display-list-item";
2504                 break;
2505         case DISPLAY_RUN_IN:
2506                 str = (gchar *) "display-run-in";
2507                 break;
2508         case DISPLAY_COMPACT:
2509                 str = (gchar *) "display-compact";
2510                 break;
2511         case DISPLAY_MARKER:
2512                 str = (gchar *) "display-marker";
2513                 break;
2514         case DISPLAY_TABLE:
2515                 str = (gchar *) "display-table";
2516                 break;
2517         case DISPLAY_INLINE_TABLE:
2518                 str = (gchar *) "display-inline-table";
2519                 break;
2520         case DISPLAY_TABLE_ROW_GROUP:
2521                 str = (gchar *) "display-table-row-group";
2522                 break;
2523         case DISPLAY_TABLE_HEADER_GROUP:
2524                 str = (gchar *) "display-table-header-group";
2525                 break;
2526         case DISPLAY_TABLE_FOOTER_GROUP:
2527                 str = (gchar *) "display-table-footer-group";
2528                 break;
2529         case DISPLAY_TABLE_ROW:
2530                 str = (gchar *) "display-table-row";
2531                 break;
2532         case DISPLAY_TABLE_COLUMN_GROUP:
2533                 str = (gchar *) "display-table-column-group";
2534                 break;
2535         case DISPLAY_TABLE_COLUMN:
2536                 str = (gchar *) "display-table-column";
2537                 break;
2538         case DISPLAY_TABLE_CELL:
2539                 str = (gchar *) "display-table-cell";
2540                 break;
2541         case DISPLAY_TABLE_CAPTION:
2542                 str = (gchar *) "display-table-caption";
2543                 break;
2544         case DISPLAY_INHERIT:
2545                 str = (gchar *) "display-inherit";
2546                 break;
2547         default:
2548                 str = (gchar *) "unknown display property";
2549                 break;
2550         }
2551         cr_utils_dump_n_chars2 (' ', a_str, a_nb_indent);
2552         g_string_append (a_str, str);
2553         return CR_OK;
2554
2555 }
2556
2557 enum CRStatus
2558 cr_style_position_type_to_string (enum CRPositionType a_code,
2559                                   GString * a_str, guint a_nb_indent)
2560 {
2561         gchar *str = NULL;
2562
2563         g_return_val_if_fail (a_str, CR_BAD_PARAM_ERROR);
2564
2565         switch (a_code) {
2566         case POSITION_STATIC:
2567                 str = (gchar *) "position-static";
2568                 break;
2569         case POSITION_RELATIVE:
2570                 str = (gchar *) "position-relative";
2571                 break;
2572         case POSITION_ABSOLUTE:
2573                 str = (gchar *) "position-absolute";
2574                 break;
2575         case POSITION_FIXED:
2576                 str = (gchar *) "position-fixed";
2577                 break;
2578         case POSITION_INHERIT:
2579                 str = (gchar *) "position-inherit";
2580                 break;
2581         default:
2582                 str = (gchar *) "unknown static property";
2583         }
2584         cr_utils_dump_n_chars2 (' ', a_str, a_nb_indent);
2585         g_string_append (a_str, str);
2586         return CR_OK;
2587 }
2588
2589 enum CRStatus
2590 cr_style_float_type_to_string (enum CRFloatType a_code,
2591                                GString * a_str, guint a_nb_indent)
2592 {
2593         gchar *str = NULL;
2594
2595         g_return_val_if_fail (a_str, CR_BAD_PARAM_ERROR);
2596
2597         switch (a_code) {
2598         case FLOAT_NONE:
2599                 str = (gchar *) "float-none";
2600                 break;
2601         case FLOAT_LEFT:
2602                 str = (gchar *) "float-left";
2603                 break;
2604         case FLOAT_RIGHT:
2605                 str = (gchar *) "float-right";
2606                 break;
2607         case FLOAT_INHERIT:
2608                 str = (gchar *) "float-inherit";
2609                 break;
2610         default:
2611                 str = (gchar *) "unknown float property value";
2612                 break;
2613         }
2614         cr_utils_dump_n_chars2 (' ', a_str, a_nb_indent);
2615         g_string_append (a_str, str);
2616         return CR_OK;
2617 }
2618
2619 enum CRStatus
2620 cr_style_white_space_type_to_string (enum CRWhiteSpaceType a_code,
2621                                      GString * a_str, guint a_nb_indent)
2622 {
2623         gchar *str = NULL;
2624
2625         g_return_val_if_fail (a_str, CR_BAD_PARAM_ERROR);
2626
2627         switch (a_code) {
2628         case WHITE_SPACE_NORMAL:
2629                 str = (gchar *) "normal";
2630                 break;
2631         case WHITE_SPACE_PRE:
2632                 str = (gchar *) "pre";
2633                 break;
2634         case WHITE_SPACE_NOWRAP:
2635                 str = (gchar *) "nowrap";
2636                 break;
2637         case WHITE_SPACE_INHERIT:
2638                 str = (gchar *) "inherited";
2639                 break;
2640         default:
2641                 str = (gchar *) "unknow white space property value";
2642                 break;
2643         }
2644         cr_utils_dump_n_chars2 (' ', a_str, a_nb_indent);
2645         g_string_append (a_str, str);
2646         return CR_OK;
2647 }
2648  
2649 /**
2650  *Serializes in instance of #CRStyle into
2651  *a string
2652  *@param a_this the instance of #CRStyle to serialize
2653  *@param a_str the string to serialise the style into.
2654  *if *a_str is NULL, a new GString is instanciated, otherwise
2655  *the style serialisation is appended to the existed *a_str
2656  *@param the number of white space char to use for indentation.
2657  *@return CR_OK upon successful completion, an error code otherwise.
2658  */
2659 enum CRStatus
2660 cr_style_to_string (CRStyle * a_this, GString ** a_str, guint a_nb_indent)
2661 {
2662         const gint INTERNAL_INDENT = 2;
2663         gint indent = a_nb_indent + INTERNAL_INDENT;
2664         gchar *tmp_str = NULL;
2665         GString *str = NULL;
2666         gint i = 0;
2667
2668         g_return_val_if_fail (a_this && a_str, CR_BAD_PARAM_ERROR);
2669
2670         if (!*a_str) {
2671                 str = g_string_new (NULL);
2672         } else {
2673                 str = *a_str;
2674         }
2675         cr_utils_dump_n_chars2 (' ', str, a_nb_indent);
2676         g_string_append (str, "style {\n");
2677
2678         /*loop over the num_props and to_string() them */
2679         for (i = NUM_PROP_TOP; i < NB_NUM_PROPS; i++) {
2680                 /*
2681                  *to_string() the name of the num_prop
2682                  *(using num_prop_code_to_string)
2683                  *before outputing it value
2684                  */
2685                 cr_utils_dump_n_chars2 (' ', str, indent);
2686                 tmp_str = (gchar *) num_prop_code_to_string (i);
2687                 if (tmp_str) {
2688                         g_string_append_printf (str, "%s: ", tmp_str);
2689                 } else {
2690                         g_string_append (str, "NULL");
2691                 }
2692                 tmp_str = NULL;
2693                 cr_style_num_prop_val_to_string (&a_this->num_props[i], str,
2694                                                  a_nb_indent +
2695                                                  INTERNAL_INDENT);
2696                 g_string_append (str, "\n");
2697         }
2698         /*loop over the rgb_props and to_string() them all */
2699         for (i = RGB_PROP_BORDER_TOP_COLOR; i < NB_RGB_PROPS; i++) {
2700                 tmp_str = (gchar *) rgb_prop_code_to_string (i);
2701                 cr_utils_dump_n_chars2 (' ', str, indent);
2702                 if (tmp_str) {
2703                         g_string_append_printf (str, "%s: ", tmp_str);
2704                 } else {
2705                         g_string_append (str, "NULL: ");
2706                 }
2707                 tmp_str = NULL;
2708                 cr_style_rgb_prop_val_to_string (&a_this->rgb_props[i], str,
2709                                                  a_nb_indent +
2710                                                  INTERNAL_INDENT);
2711                 g_string_append (str, "\n");
2712         }
2713         /*loop over the border_style_props and to_string() them */
2714         for (i = BORDER_STYLE_PROP_TOP; i < NB_BORDER_STYLE_PROPS; i++) {
2715                 tmp_str = (gchar *) border_style_prop_code_to_string (i);
2716                 cr_utils_dump_n_chars2 (' ', str, indent);
2717                 if (tmp_str) {
2718                         g_string_append_printf (str, "%s: ", tmp_str);
2719                 } else {
2720                         g_string_append (str, "NULL: ");
2721                 }
2722                 tmp_str = NULL;
2723                 cr_style_border_style_to_string (a_this->
2724                                                  border_style_props[i], str,
2725                                                  0);
2726                 g_string_append (str, "\n");
2727         }
2728         cr_utils_dump_n_chars2 (' ', str, indent);
2729         g_string_append (str, "display: ");
2730         cr_style_display_type_to_string (a_this->display, str, 0);
2731         g_string_append (str, "\n");
2732
2733         cr_utils_dump_n_chars2 (' ', str, indent);
2734         g_string_append (str, "position: ");
2735         cr_style_position_type_to_string (a_this->position, str, 0);
2736         g_string_append (str, "\n");
2737
2738         cr_utils_dump_n_chars2 (' ', str, indent);
2739         g_string_append (str, "float-type: ");
2740         cr_style_float_type_to_string (a_this->float_type, str, 0);
2741         g_string_append (str, "\n");
2742
2743         cr_utils_dump_n_chars2 (' ', str, indent);
2744         g_string_append (str, "white-space: ");
2745         cr_style_white_space_type_to_string (a_this->white_space, str, 0);
2746         g_string_append (str, "\n");
2747
2748         cr_utils_dump_n_chars2 (' ', str, indent);
2749         g_string_append (str, "font-family: ");
2750         tmp_str = cr_font_family_to_string (a_this->font_family, TRUE);
2751         if (tmp_str) {
2752                 g_string_append (str, tmp_str);
2753                 g_free (tmp_str);
2754                 tmp_str = NULL;
2755         } else {
2756                 g_string_append (str, "NULL");
2757         }
2758         g_string_append (str, "\n");
2759
2760         cr_utils_dump_n_chars2 (' ', str, indent);
2761         tmp_str = cr_font_size_to_string (&a_this->font_size.sv);
2762         if (tmp_str) {
2763                 g_string_append_printf (str, "font-size {sv:%s, ",
2764                                         tmp_str) ;
2765         } else {
2766                 g_string_append (str, "font-size {sv:NULL, ");
2767         }
2768         tmp_str = cr_font_size_to_string (&a_this->font_size.cv);
2769         if (tmp_str) {
2770                 g_string_append_printf (str, "cv:%s, ", tmp_str);
2771         } else {
2772                 g_string_append (str, "cv:NULL, ");
2773         }
2774         tmp_str = cr_font_size_to_string (&a_this->font_size.av);
2775         if (tmp_str) {
2776                 g_string_append_printf (str, "av:%s}", tmp_str);
2777         } else {
2778                 g_string_append (str, "av:NULL}");
2779         }
2780
2781         tmp_str = NULL;
2782         g_string_append (str, "\n");
2783
2784         cr_utils_dump_n_chars2 (' ', str, indent);
2785         tmp_str = cr_font_size_adjust_to_string (a_this->font_size_adjust);
2786         if (tmp_str) {
2787                 g_string_append_printf (str, "font-size-adjust: %s", tmp_str);
2788         } else {
2789                 g_string_append (str, "font-size-adjust: NULL");
2790         }
2791         tmp_str = NULL;
2792         g_string_append (str, "\n");
2793
2794         cr_utils_dump_n_chars2 (' ', str, indent);
2795         tmp_str = (gchar *) cr_font_style_to_string (a_this->font_style);
2796         if (tmp_str) {
2797                 g_string_append_printf (str, "font-style: %s", tmp_str);
2798         } else {
2799                 g_string_append (str, "font-style: NULL");
2800         }
2801         tmp_str = NULL;
2802         g_string_append (str, "\n");
2803
2804         cr_utils_dump_n_chars2 (' ', str, indent);
2805         tmp_str = (gchar *) cr_font_variant_to_string (a_this->font_variant);
2806         if (tmp_str) {
2807                 g_string_append_printf (str, "font-variant: %s", tmp_str);
2808         } else {
2809                 g_string_append (str, "font-variant: NULL");
2810         }
2811         tmp_str = NULL;
2812         g_string_append (str, "\n");
2813
2814         cr_utils_dump_n_chars2 (' ', str, indent);
2815         tmp_str = (gchar *) cr_font_weight_to_string (a_this->font_weight);
2816         if (tmp_str) {
2817                 g_string_append_printf (str, "font-weight: %s", tmp_str);
2818         } else {
2819                 g_string_append (str, "font-weight: NULL");
2820         }
2821         tmp_str = NULL;
2822         g_string_append (str, "\n");
2823
2824         cr_utils_dump_n_chars2 (' ', str, indent);
2825         tmp_str = (gchar *) cr_font_stretch_to_string (a_this->font_stretch);
2826         if (tmp_str) {
2827                 g_string_append_printf (str, "font-stretch: %s", tmp_str);
2828         } else {
2829                 g_string_append (str, "font-stretch: NULL");
2830         }
2831         tmp_str = NULL;
2832         g_string_append (str, "\n");
2833
2834
2835         cr_utils_dump_n_chars2 (' ', str, a_nb_indent);
2836         g_string_append (str, "}");
2837
2838         return CR_OK;
2839 }
2840
2841 /**
2842  *Destructor of the #CRStyle class.
2843  *@param a_this the instance to destroy.
2844  */
2845 void
2846 cr_style_destroy (CRStyle * a_this)
2847 {
2848         g_return_if_fail (a_this);
2849
2850         g_free (a_this);
2851 }
2852