Code

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