Main Page | Alphabetical List | Data Structures | File List | Data Fields | Globals | Related Pages

cr-style.c

Go to the documentation of this file.
00001 /* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */
00002 
00003 /*
00004  * This file is part of The Croco Library
00005  *
00006  * This program is free software; you can redistribute it and/or
00007  * modify it under the terms of version 2.1 of 
00008  * the GNU Lesser General Public
00009  * License as published by the Free Software Foundation.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the 
00017  * GNU Lesser General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
00020  * USA
00021  *
00022  * see COPYRIGTHS file for copyright information
00023  */
00024 
00025 /*
00026  *$Id: cr-style.c,v 1.23 2004/03/07 13:22:48 dodji Exp $
00027  */
00028 #include <string.h>
00029 #include "cr-style.h"
00030 
00031 /**
00032  *@file
00033  *The definition of the #CRStyle class.
00034  */
00035 
00036 /**
00037  *A property ID.
00038  *Each supported css property has an ID which is
00039  *an entry into a property "population" jump table.
00040  *each entry of the property population jump table
00041  *contains code to tranform the literal form of
00042  *a property value into a strongly typed value.
00043  */
00044 enum CRPropertyID {
00045         PROP_ID_NOT_KNOWN = 0,
00046         PROP_ID_PADDING_TOP,
00047         PROP_ID_PADDING_RIGHT,
00048         PROP_ID_PADDING_BOTTOM,
00049         PROP_ID_PADDING_LEFT,
00050         PROP_ID_PADDING,
00051         PROP_ID_BORDER_TOP_WIDTH,
00052         PROP_ID_BORDER_RIGHT_WIDTH,
00053         PROP_ID_BORDER_BOTTOM_WIDTH,
00054         PROP_ID_BORDER_LEFT_WIDTH,
00055         PROP_ID_BORDER_TOP_STYLE,
00056         PROP_ID_BORDER_RIGHT_STYLE,
00057         PROP_ID_BORDER_BOTTOM_STYLE,
00058         PROP_ID_BORDER_LEFT_STYLE,
00059         PROP_ID_BORDER_TOP_COLOR,
00060         PROP_ID_BORDER_RIGHT_COLOR,
00061         PROP_ID_BORDER_BOTTOM_COLOR,
00062         PROP_ID_BORDER_LEFT_COLOR,
00063         PROP_ID_BORDER_TOP,
00064         PROP_ID_BORDER_RIGHT,
00065         PROP_ID_BORDER_BOTTOM,
00066         PROP_ID_BORDER_LEFT,
00067         PROP_ID_BORDER,
00068         PROP_ID_MARGIN_TOP,
00069         PROP_ID_MARGIN_RIGHT,
00070         PROP_ID_MARGIN_BOTTOM,
00071         PROP_ID_MARGIN_LEFT,
00072         PROP_ID_MARGIN,
00073         PROP_ID_DISPLAY,
00074         PROP_ID_POSITION,
00075         PROP_ID_TOP,
00076         PROP_ID_RIGHT,
00077         PROP_ID_BOTTOM,
00078         PROP_ID_LEFT,
00079         PROP_ID_FLOAT,
00080         PROP_ID_WIDTH,
00081         PROP_ID_COLOR,
00082         PROP_ID_BACKGROUND_COLOR,
00083         PROP_ID_FONT_FAMILY,
00084         PROP_ID_FONT_SIZE,
00085         PROP_ID_FONT_STYLE,
00086         PROP_ID_FONT_WEIGHT,
00087         /*should be the last one. */
00088         NB_PROP_IDS
00089 };
00090 
00091 typedef struct _CRPropertyDesc CRPropertyDesc;
00092 
00093 struct _CRPropertyDesc {
00094         const guchar *name;
00095         enum CRPropertyID prop_id;
00096 };
00097 
00098 static CRPropertyDesc gv_prop_table[] = {
00099         {"padding-top", PROP_ID_PADDING_TOP},
00100         {"padding-right", PROP_ID_PADDING_RIGHT},
00101         {"padding-bottom", PROP_ID_PADDING_BOTTOM},
00102         {"padding-left", PROP_ID_PADDING_LEFT},
00103         {"padding", PROP_ID_PADDING},
00104         {"border-top-width", PROP_ID_BORDER_TOP_WIDTH},
00105         {"border-right-width", PROP_ID_BORDER_RIGHT_WIDTH},
00106         {"border-bottom-width", PROP_ID_BORDER_BOTTOM_WIDTH},
00107         {"border-left-width", PROP_ID_BORDER_LEFT_WIDTH},
00108         {"border-top-style", PROP_ID_BORDER_TOP_STYLE},
00109         {"border-right-style", PROP_ID_BORDER_RIGHT_STYLE},
00110         {"border-bottom-style", PROP_ID_BORDER_BOTTOM_STYLE},
00111         {"border-left-style", PROP_ID_BORDER_LEFT_STYLE},
00112         {"border-top", PROP_ID_BORDER_TOP},
00113         {"border-right", PROP_ID_BORDER_RIGHT},
00114         {"border-bottom", PROP_ID_BORDER_BOTTOM},
00115         {"border-left", PROP_ID_BORDER_LEFT},
00116         {"border", PROP_ID_BORDER},
00117         {"margin-top", PROP_ID_MARGIN_TOP},
00118         {"margin-right", PROP_ID_MARGIN_RIGHT},
00119         {"margin-bottom", PROP_ID_MARGIN_BOTTOM},
00120         {"margin-left", PROP_ID_MARGIN_LEFT},
00121         {"margin", PROP_ID_MARGIN},
00122         {"display", PROP_ID_DISPLAY},
00123         {"position", PROP_ID_POSITION},
00124         {"top", PROP_ID_TOP},
00125         {"right", PROP_ID_RIGHT},
00126         {"bottom", PROP_ID_BOTTOM},
00127         {"left", PROP_ID_LEFT},
00128         {"float", PROP_ID_FLOAT},
00129         {"width", PROP_ID_WIDTH},
00130         {"color", PROP_ID_COLOR},
00131         {"background-color", PROP_ID_BACKGROUND_COLOR},
00132         {"font-family", PROP_ID_FONT_FAMILY},
00133         {"font-size", PROP_ID_FONT_SIZE},
00134         {"font-style", PROP_ID_FONT_STYLE},
00135         {"font-weight", PROP_ID_FONT_WEIGHT},
00136         /*must be the last one */
00137         {NULL, 0}
00138 };
00139 
00140 /**
00141  *A the key/value pair of this hash table
00142  *are:
00143  *key => name of the the css propertie found in gv_prop_table
00144  *value => matching property id found in gv_prop_table.
00145  *So this hash table is here just to retrieval of a property id
00146  *from a property name.
00147  */
00148 static GHashTable *gv_prop_hash = NULL;
00149 
00150 /**
00151  *incremented by each new instance of #CRStyle
00152  *and decremented at the it destroy time.
00153  *When this reaches zero, gv_prop_hash is destroyed.
00154  */
00155 static gulong gv_prop_hash_ref_count = 0;
00156 
00157 struct CRNumPropEnumDumpInfo {
00158         enum CRNumProp code;
00159         const gchar *str;
00160 };
00161 
00162 static struct CRNumPropEnumDumpInfo gv_num_props_dump_infos[] = {
00163         {NUM_PROP_TOP, "top"},
00164         {NUM_PROP_RIGHT, "right"},
00165         {NUM_PROP_BOTTOM, "bottom"},
00166         {NUM_PROP_LEFT, "left"},
00167         {NUM_PROP_PADDING_TOP, "padding-top"},
00168         {NUM_PROP_PADDING_RIGHT, "padding-right"},
00169         {NUM_PROP_PADDING_BOTTOM, "padding-bottom"},
00170         {NUM_PROP_PADDING_LEFT, "padding-left"},
00171         {NUM_PROP_BORDER_TOP, "border-top"},
00172         {NUM_PROP_BORDER_RIGHT, "border-right"},
00173         {NUM_PROP_BORDER_BOTTOM, "border-bottom"},
00174         {NUM_PROP_BORDER_LEFT, "border-left"},
00175         {NUM_PROP_MARGIN_TOP, "margin-top"},
00176         {NUM_PROP_MARGIN_RIGHT, "margin-right"},
00177         {NUM_PROP_MARGIN_BOTTOM, "margin-bottom"},
00178         {NUM_PROP_MARGIN_LEFT, "margin-left"},
00179         {NUM_PROP_WIDTH, "width"},
00180         {0, NULL}
00181 };
00182 
00183 struct CRRgbPropEnumDumpInfo {
00184         enum CRRgbProp code;
00185         const gchar *str;
00186 };
00187 
00188 static struct CRRgbPropEnumDumpInfo gv_rgb_props_dump_infos[] = {
00189         {RGB_PROP_BORDER_TOP_COLOR, "border-top-color"},
00190         {RGB_PROP_BORDER_RIGHT_COLOR, "border-right-color"},
00191         {RGB_PROP_BORDER_BOTTOM_COLOR, "bottom-color"},
00192         {RGB_PROP_BORDER_LEFT_COLOR, "left-color"},
00193         {RGB_PROP_COLOR, "color"},
00194         {RGB_PROP_BACKGROUND_COLOR, "background-color"},
00195         {0, NULL}
00196 };
00197 
00198 struct CRBorderStylePropEnumDumpInfo {
00199         enum CRBorderStyleProp code;
00200         const gchar *str;
00201 
00202 };
00203 
00204 static struct CRBorderStylePropEnumDumpInfo gv_border_style_props_dump_infos[]
00205         = {
00206         {BORDER_STYLE_PROP_TOP, "border-style-top"},
00207         {BORDER_STYLE_PROP_RIGHT, "border-style-right"},
00208         {BORDER_STYLE_PROP_BOTTOM, "boder-style-bottom"},
00209         {BORDER_STYLE_PROP_LEFT, "border-style-left"},
00210         {0, NULL}
00211 };
00212 
00213 static enum CRStatus
00214   cr_style_init_properties (void);
00215 
00216 enum CRDirection {
00217         DIR_TOP = 0,
00218         DIR_RIGHT,
00219         DIR_BOTTOM,
00220         DIR_LEFT,
00221 
00222         /*must be the last one */
00223         NB_DIRS
00224 };
00225 
00226 static const gchar *num_prop_code_to_string (enum CRNumProp a_code);
00227 
00228 static const gchar *rgb_prop_code_to_string (enum CRRgbProp a_code);
00229 
00230 static const gchar *border_style_prop_code_to_string (enum CRBorderStyleProp
00231                                                       a_code);
00232 
00233 static enum CRStatus
00234   set_prop_padding_x_from_value (CRStyle * a_style,
00235                                  CRTerm * a_value, enum CRDirection a_dir);
00236 
00237 static enum CRStatus
00238   set_prop_border_x_width_from_value (CRStyle * a_style,
00239                                       CRTerm * a_value,
00240                                       enum CRDirection a_dir);
00241 
00242 static enum CRStatus
00243   set_prop_border_x_style_from_value (CRStyle * a_style,
00244                                       CRTerm * a_value,
00245                                       enum CRDirection a_dir);
00246 
00247 static enum CRStatus
00248   set_prop_margin_x_from_value (CRStyle * a_style, CRTerm * a_value,
00249                                 enum CRDirection a_dir);
00250 
00251 static enum CRStatus
00252   set_prop_display_from_value (CRStyle * a_style, CRTerm * a_value);
00253 
00254 static enum CRStatus
00255   set_prop_position_from_value (CRStyle * a_style, CRTerm * a_value);
00256 
00257 static enum CRStatus
00258   set_prop_x_from_value (CRStyle * a_style, CRTerm * a_value,
00259                          enum CRDirection a_dir);
00260 
00261 static enum CRStatus
00262   set_prop_float (CRStyle * a_style, CRTerm * a_value);
00263 
00264 static enum CRStatus
00265   set_prop_width (CRStyle * a_style, CRTerm * a_value);
00266 
00267 static enum CRStatus
00268   set_prop_color (CRStyle * a_style, CRTerm * a_value);
00269 
00270 static enum CRStatus
00271   set_prop_background_color (CRStyle * a_style, CRTerm * a_value);
00272 
00273 static enum CRStatus
00274   set_prop_border_x_color_from_value (CRStyle * a_style, CRTerm * a_value,
00275                                       enum CRDirection a_dir);
00276 
00277 static enum CRStatus
00278   set_prop_border_x_from_value (CRStyle * a_style, CRTerm * a_value,
00279                                 enum CRDirection a_dir);
00280 
00281 static enum CRStatus
00282   set_prop_border_from_value (CRStyle * a_style, CRTerm * a_value);
00283 
00284 static enum CRStatus
00285   set_prop_padding_from_value (CRStyle * a_style, CRTerm * a_value);
00286 
00287 static enum CRStatus
00288   set_prop_margin_from_value (CRStyle * a_style, CRTerm * a_value);
00289 
00290 static enum CRStatus
00291   set_prop_font_family_from_value (CRStyle * a_style, CRTerm * a_value);
00292 
00293 static enum CRStatus
00294   init_style_font_size_field (CRStyle * a_style);
00295 
00296 static enum CRStatus
00297   set_prop_font_size_from_value (CRStyle * a_style, CRTerm * a_value);
00298 
00299 static enum CRStatus
00300   set_prop_font_style_from_value (CRStyle * a_style, CRTerm * a_value);
00301 
00302 static enum CRStatus
00303   set_prop_font_weight_from_value (CRStyle * a_style, CRTerm * a_value);
00304 
00305 static const gchar *
00306 num_prop_code_to_string (enum CRNumProp a_code)
00307 {
00308         gint len = sizeof (gv_num_props_dump_infos) /
00309                 sizeof (struct CRNumPropEnumDumpInfo);
00310         if (a_code >= len) {
00311                 cr_utils_trace_info ("A field has been added "
00312                                      "to 'enum CRNumProp' and no matching"
00313                                      " entry has been "
00314                                      "added to gv_num_prop_dump_infos table.\n"
00315                                      "Please add the missing matching entry");
00316                 return NULL;
00317         }
00318         if (gv_num_props_dump_infos[a_code].code != a_code) {
00319                 cr_utils_trace_info ("mismatch between the order of fields in"
00320                                      " 'enum CRNumProp' and "
00321                                      "the order of entries in "
00322                                      "the gv_num_prop_dump_infos table");
00323                 return NULL;
00324         }
00325         return gv_num_props_dump_infos[a_code].str;
00326 }
00327 
00328 static const gchar *
00329 rgb_prop_code_to_string (enum CRRgbProp a_code)
00330 {
00331         gint len = sizeof (gv_rgb_props_dump_infos) /
00332                 sizeof (struct CRRgbPropEnumDumpInfo);
00333 
00334         if (a_code >= len) {
00335                 cr_utils_trace_info ("A field has been added "
00336                                      "to 'enum CRRgbProp' and no matching"
00337                                      " entry has been "
00338                                      "added to gv_rgb_prop_dump_infos table.\n"
00339                                      "Please add the missing matching entry");
00340                 return NULL;
00341         }
00342         if (gv_rgb_props_dump_infos[a_code].code != a_code) {
00343                 cr_utils_trace_info ("mismatch between the order of fields in"
00344                                      " 'enum CRRgbProp' and "
00345                                      "the order of entries in "
00346                                      "the gv_rgb_props_dump_infos table");
00347                 return NULL;
00348         }
00349         return gv_rgb_props_dump_infos[a_code].str;
00350 }
00351 
00352 static const gchar *
00353 border_style_prop_code_to_string (enum CRBorderStyleProp a_code)
00354 {
00355         gint len = sizeof (gv_border_style_props_dump_infos) /
00356                 sizeof (struct CRBorderStylePropEnumDumpInfo);
00357 
00358         if (a_code >= len) {
00359                 cr_utils_trace_info ("A field has been added "
00360                                      "to 'enum CRBorderStyleProp' and no matching"
00361                                      " entry has been "
00362                                      "added to gv_border_style_prop_dump_infos table.\n"
00363                                      "Please add the missing matching entry");
00364                 return NULL;
00365         }
00366         if (gv_border_style_props_dump_infos[a_code].code != a_code) {
00367                 cr_utils_trace_info ("mismatch between the order of fields in"
00368                                      " 'enum CRBorderStyleProp' and "
00369                                      "the order of entries in "
00370                                      "the gv_border_style_props_dump_infos table");
00371                 return NULL;
00372         }
00373         return gv_border_style_props_dump_infos[a_code].str;
00374 }
00375 
00376 static enum CRStatus
00377 cr_style_init_properties (void)
00378 {
00379 
00380         if (!gv_prop_hash) {
00381                 gulong i = 0;
00382 
00383                 gv_prop_hash = g_hash_table_new (g_str_hash, g_str_equal);
00384                 if (!gv_prop_hash) {
00385                         cr_utils_trace_info ("Out of memory");
00386                         return CR_ERROR;
00387                 }
00388 
00389                 /*load gv_prop_hash from gv_prop_table */
00390                 for (i = 0; gv_prop_table[i].name; i++) {
00391                         g_hash_table_insert
00392                                 (gv_prop_hash,
00393                                  (gpointer) gv_prop_table[i].name,
00394                                  GINT_TO_POINTER (gv_prop_table[i].prop_id));
00395                 }
00396         }
00397 
00398         return CR_OK;
00399 }
00400 
00401 static enum CRPropertyID
00402 cr_style_get_prop_id (const guchar * a_prop)
00403 {
00404         gpointer *raw_id = NULL;
00405 
00406         if (!gv_prop_hash) {
00407                 cr_style_init_properties ();
00408         }
00409 
00410         raw_id = g_hash_table_lookup (gv_prop_hash, a_prop);
00411         if (!raw_id) {
00412                 return PROP_ID_NOT_KNOWN;
00413         }
00414         return GPOINTER_TO_INT (raw_id);
00415 }
00416 
00417 static enum CRStatus
00418 set_prop_padding_x_from_value (CRStyle * a_style,
00419                                CRTerm * a_value, enum CRDirection a_dir)
00420 {
00421         enum CRStatus status = CR_OK;
00422         CRNum *num_val = NULL,
00423                 *parent_num_val = NULL;
00424 
00425         g_return_val_if_fail (a_style && a_value, CR_BAD_PARAM_ERROR);
00426 
00427         if (a_value->type != TERM_NUMBER && a_value->type != TERM_IDENT)
00428                 return CR_BAD_PARAM_ERROR;
00429 
00430         switch (a_dir) {
00431         case DIR_TOP:
00432                 num_val = &a_style->num_props[NUM_PROP_PADDING_TOP].sv;
00433                 parent_num_val =
00434                         &a_style->parent_style->
00435                         num_props[NUM_PROP_PADDING_TOP].sv;
00436                 break;
00437 
00438         case DIR_RIGHT:
00439                 num_val = &a_style->num_props[NUM_PROP_PADDING_RIGHT].sv;
00440                 parent_num_val =
00441                         &a_style->parent_style->
00442                         num_props[NUM_PROP_PADDING_RIGHT].sv;
00443 
00444                 num_val = &a_style->num_props[NUM_PROP_PADDING_RIGHT].sv;
00445                 parent_num_val =
00446                         &a_style->parent_style->
00447                         num_props[NUM_PROP_PADDING_RIGHT].sv;
00448                 break;
00449 
00450         case DIR_BOTTOM:
00451                 num_val = &a_style->num_props[NUM_PROP_PADDING_BOTTOM].sv;
00452                 parent_num_val =
00453                         &a_style->parent_style->
00454                         num_props[NUM_PROP_PADDING_BOTTOM].sv;
00455                 break;
00456 
00457         case DIR_LEFT:
00458                 num_val = &a_style->num_props[NUM_PROP_PADDING_LEFT].sv;
00459                 parent_num_val =
00460                         &a_style->parent_style->
00461                         num_props[NUM_PROP_PADDING_LEFT].sv;
00462                 break;
00463 
00464         default:
00465                 return CR_BAD_PARAM_ERROR;
00466         }
00467 
00468         if (a_value->type == TERM_IDENT) {
00469                 if (a_value->content.str
00470                     && a_value->content.str->str
00471                     && !strncmp ((guchar *) "inherited",
00472                                  a_value->content.str->str,
00473                                  strlen ("inherited"))) {
00474                         cr_num_copy (num_val, parent_num_val);
00475                         return CR_OK;
00476                 } else
00477                         return CR_UNKNOWN_TYPE_ERROR;
00478         }
00479 
00480         g_return_val_if_fail (a_value->type == TERM_NUMBER
00481                               && a_value->content.num, CR_UNKNOWN_TYPE_ERROR);
00482 
00483         switch (a_value->content.num->type) {
00484         case NUM_LENGTH_EM:
00485         case NUM_LENGTH_EX:
00486         case NUM_LENGTH_PX:
00487         case NUM_LENGTH_IN:
00488         case NUM_LENGTH_CM:
00489         case NUM_LENGTH_MM:
00490         case NUM_LENGTH_PT:
00491         case NUM_LENGTH_PC:
00492         case NUM_PERCENTAGE:
00493                 status = cr_num_copy (num_val, a_value->content.num);
00494                 break;
00495         default:
00496                 status = CR_UNKNOWN_TYPE_ERROR;
00497                 break;
00498         }
00499 
00500         return status;
00501 }
00502 
00503 static enum CRStatus
00504 set_prop_border_x_width_from_value (CRStyle * a_style,
00505                                     CRTerm * a_value, enum CRDirection a_dir)
00506 {
00507         enum CRStatus status = CR_OK;
00508         CRNum *num_val = NULL;
00509 
00510         g_return_val_if_fail (a_value && a_style, CR_BAD_PARAM_ERROR);
00511 
00512         switch (a_dir) {
00513         case DIR_TOP:
00514                 num_val = &a_style->num_props[NUM_PROP_BORDER_TOP].sv;
00515                 break;
00516 
00517         case DIR_RIGHT:
00518                 num_val = &a_style->num_props[NUM_PROP_BORDER_RIGHT].sv;
00519                 break;
00520 
00521         case DIR_BOTTOM:
00522                 num_val = &a_style->num_props[NUM_PROP_BORDER_BOTTOM].sv;
00523                 break;
00524 
00525         case DIR_LEFT:
00526                 num_val = &a_style->num_props[NUM_PROP_BORDER_LEFT].sv;
00527                 break;
00528 
00529         default:
00530                 return CR_BAD_PARAM_ERROR;
00531                 break;
00532         }
00533 
00534         if (a_value->type == TERM_IDENT) {
00535                 if (a_value->content.str && a_value->content.str->str) {
00536                         if (!strncmp ("thin",
00537                                       a_value->content.str->str,
00538                                       strlen ("thin"))) {
00539                                 cr_num_set (num_val, BORDER_THIN,
00540                                             NUM_LENGTH_PX);
00541                         } else if (!strncmp ("medium",
00542                                              a_value->content.str->str,
00543                                              strlen ("medium"))) {
00544                                 cr_num_set (num_val, BORDER_MEDIUM,
00545                                             NUM_LENGTH_PX);
00546                         } else if (!strncmp ("thick",
00547                                              a_value->content.str->str,
00548                                              strlen ("thick"))) {
00549                                 cr_num_set (num_val, BORDER_THICK,
00550                                             NUM_LENGTH_PX);
00551                         } else {
00552                                 return CR_UNKNOWN_TYPE_ERROR;
00553                         }
00554                 }
00555         } else if (a_value->type == TERM_NUMBER) {
00556                 if (a_value->content.num) {
00557                         cr_num_copy (num_val, a_value->content.num);
00558                 }
00559         } else if (a_value->type != TERM_NUMBER
00560                    || a_value->content.num == NULL) {
00561                 return CR_UNKNOWN_TYPE_ERROR;
00562         }
00563 
00564         return status;
00565 }
00566 
00567 static enum CRStatus
00568 set_prop_border_x_style_from_value (CRStyle * a_style,
00569                                     CRTerm * a_value, enum CRDirection a_dir)
00570 {
00571         enum CRStatus status = CR_OK;
00572         enum CRBorderStyle *border_style_ptr = NULL,
00573                 *parent_border_style_ptr = NULL;
00574 
00575         g_return_val_if_fail (a_style && a_value, CR_BAD_PARAM_ERROR);
00576 
00577         switch (a_dir) {
00578         case DIR_TOP:
00579                 border_style_ptr = &a_style->
00580                         border_style_props[BORDER_STYLE_PROP_TOP];
00581                 parent_border_style_ptr = (a_style->parent_style) ?
00582                         &a_style->parent_style->
00583                         border_style_props[BORDER_STYLE_PROP_TOP] : NULL;
00584 
00585                 break;
00586 
00587         case DIR_RIGHT:
00588                 border_style_ptr =
00589                         &a_style->border_style_props[BORDER_STYLE_PROP_RIGHT];
00590 
00591                 parent_border_style_ptr = (a_style->parent_style) ?
00592                         &a_style->parent_style->
00593                         border_style_props[BORDER_STYLE_PROP_RIGHT] : NULL;
00594                 break;
00595 
00596         case DIR_BOTTOM:
00597                 border_style_ptr = &a_style->
00598                         border_style_props[BORDER_STYLE_PROP_BOTTOM];
00599                 parent_border_style_ptr = (a_style->parent_style) ?
00600                         &a_style->parent_style->
00601                         border_style_props[BORDER_STYLE_PROP_BOTTOM] : NULL;
00602                 break;
00603 
00604         case DIR_LEFT:
00605                 border_style_ptr = &a_style->
00606                         border_style_props[BORDER_STYLE_PROP_LEFT];
00607                 parent_border_style_ptr = (a_style->parent_style) ?
00608                         &a_style->parent_style->
00609                         border_style_props[BORDER_STYLE_PROP_LEFT] : NULL;
00610                 break;
00611 
00612         default:
00613                 break;
00614         }
00615 
00616         if (a_value->type != TERM_IDENT || !a_value->content.str) {
00617                 return CR_UNKNOWN_TYPE_ERROR;
00618         }
00619 
00620         if (!strncmp ("none", a_value->content.str->str, strlen ("none"))) {
00621                 *border_style_ptr = BORDER_STYLE_NONE;
00622         } else if (!strncmp ("hidden",
00623                              a_value->content.str->str, strlen ("hidden"))) {
00624                 *border_style_ptr = BORDER_STYLE_HIDDEN;
00625         } else if (!strncmp ("dotted",
00626                              a_value->content.str->str, strlen ("dotted"))) {
00627                 *border_style_ptr = BORDER_STYLE_DOTTED;
00628         } else if (!strncmp ("dashed",
00629                              a_value->content.str->str, strlen ("dashed"))) {
00630                 *border_style_ptr = BORDER_STYLE_DASHED;
00631         } else if (!strncmp ("solid",
00632                              a_value->content.str->str, strlen ("solid"))) {
00633                 *border_style_ptr = BORDER_STYLE_SOLID;
00634         } else if (!strncmp ("double",
00635                              a_value->content.str->str, strlen ("double"))) {
00636                 *border_style_ptr = BORDER_STYLE_DOUBLE;
00637         } else if (!strncmp ("groove",
00638                              a_value->content.str->str, strlen ("groove"))) {
00639                 *border_style_ptr = BORDER_STYLE_GROOVE;
00640         } else if (!strncmp ("ridge",
00641                              a_value->content.str->str, strlen ("ridge"))) {
00642                 *border_style_ptr = BORDER_STYLE_RIDGE;
00643         } else if (!strncmp ("inset",
00644                              a_value->content.str->str, strlen ("inset"))) {
00645                 *border_style_ptr = BORDER_STYLE_INSET;
00646         } else if (!strncmp ("outset",
00647                              a_value->content.str->str, strlen ("outset"))) {
00648                 *border_style_ptr = BORDER_STYLE_OUTSET;
00649         } else if (!strncmp ("inherit",
00650                              a_value->content.str->str, strlen ("inherit"))) {
00651                 if (parent_border_style_ptr)
00652                         *border_style_ptr = *parent_border_style_ptr;
00653         } else {
00654                 status = CR_UNKNOWN_TYPE_ERROR;
00655         }
00656 
00657         return status;
00658 }
00659 
00660 static enum CRStatus
00661 set_prop_margin_x_from_value (CRStyle * a_style, CRTerm * a_value,
00662                               enum CRDirection a_dir)
00663 {
00664         enum CRStatus status = CR_OK;
00665         CRNum *num_val = NULL,
00666                 *parent_num_val = NULL;
00667 
00668         g_return_val_if_fail (a_style && a_value, CR_BAD_PARAM_ERROR);
00669 
00670         switch (a_dir) {
00671         case DIR_TOP:
00672                 num_val = &a_style->num_props[NUM_PROP_MARGIN_TOP].sv;
00673                 parent_num_val =
00674                         &a_style->parent_style->
00675                         num_props[NUM_PROP_MARGIN_TOP].sv;
00676                 break;
00677 
00678         case DIR_RIGHT:
00679                 num_val = &a_style->num_props[NUM_PROP_MARGIN_RIGHT].sv;
00680 
00681                 parent_num_val =
00682                         &a_style->parent_style->
00683                         num_props[NUM_PROP_MARGIN_RIGHT].sv;
00684                 break;
00685 
00686         case DIR_BOTTOM:
00687                 num_val = &a_style->num_props[NUM_PROP_MARGIN_BOTTOM].sv;
00688                 parent_num_val =
00689                         &a_style->parent_style->
00690                         num_props[NUM_PROP_MARGIN_BOTTOM].sv;
00691                 break;
00692 
00693         case DIR_LEFT:
00694                 num_val = &a_style->num_props[NUM_PROP_MARGIN_LEFT].sv;
00695                 parent_num_val =
00696                         &a_style->parent_style->
00697                         num_props[NUM_PROP_MARGIN_LEFT].sv;
00698                 break;
00699 
00700         default:
00701                 break;
00702         }
00703 
00704         switch (a_value->type) {
00705         case TERM_IDENT:
00706                 if (a_value->content.str
00707                     && a_value->content.str->str
00708                     && !strncmp (a_value->content.str->str,
00709                                  "inherit", strlen ("inherit"))) {
00710                         status = cr_num_copy (num_val, parent_num_val);
00711                 } else if (a_value->content.str
00712                            && a_value->content.str->str
00713                            && !strncmp (a_value->content.str->str,
00714                                         "auto", strlen ("auto"))) {
00715                         status = cr_num_set (num_val, 0.0, NUM_AUTO);
00716                 } else {
00717                         status = CR_UNKNOWN_TYPE_ERROR;
00718                 }
00719 
00720         case TERM_NUMBER:
00721                 status = cr_num_copy (num_val, a_value->content.num);
00722                 break;
00723 
00724         default:
00725                 status = CR_UNKNOWN_TYPE_ERROR;
00726                 break;
00727         }
00728 
00729         return status;
00730 }
00731 
00732 struct CRPropDisplayValPair {
00733         const guchar *prop_name;
00734         enum CRDisplayType type;
00735 };
00736 
00737 static enum CRStatus
00738 set_prop_display_from_value (CRStyle * a_style, CRTerm * a_value)
00739 {
00740         enum CRDisplayType default_display_val = DISPLAY_INLINE;
00741         static const struct CRPropDisplayValPair disp_vals_map[] = {
00742                 {"none", DISPLAY_NONE},
00743                 {"inline", DISPLAY_INLINE},
00744                 {"block", DISPLAY_BLOCK},
00745                 {"run-in", DISPLAY_RUN_IN},
00746                 {"compact", DISPLAY_COMPACT},
00747                 {"marker", DISPLAY_MARKER},
00748                 {"table", DISPLAY_TABLE},
00749                 {"inline-table", DISPLAY_INLINE_TABLE},
00750                 {"table-row-group", DISPLAY_TABLE_ROW_GROUP},
00751                 {"table-header-group", DISPLAY_TABLE_HEADER_GROUP},
00752                 {"table-footer-group", DISPLAY_TABLE_FOOTER_GROUP},
00753                 {"table-row", DISPLAY_TABLE_ROW},
00754                 {"table-column-group", DISPLAY_TABLE_COLUMN_GROUP},
00755                 {"table-column", DISPLAY_TABLE_COLUMN},
00756                 {"table-cell", DISPLAY_TABLE_CELL},
00757                 {"table-caption", DISPLAY_TABLE_CAPTION},
00758                 {"inherit", DISPLAY_INHERIT},
00759                 {NULL, DISPLAY_NONE}
00760         };
00761 
00762         g_return_val_if_fail (a_style && a_value, CR_BAD_PARAM_ERROR);
00763 
00764         /*Sets to its default value according to the css2 spec. */
00765         a_style->display = default_display_val;
00766 
00767         switch (a_value->type) {
00768         case TERM_IDENT:
00769                 {
00770                         int i = 0;
00771 
00772                         if (!a_value->content.str
00773                             || !a_value->content.str->str)
00774                                 break;
00775 
00776                         for (i = 0; disp_vals_map[i].prop_name; i++) {
00777                                 if (!strncmp (disp_vals_map[i].prop_name,
00778                                               a_value->content.str->str,
00779                                               strlen
00780                                               (disp_vals_map[i].prop_name))) {
00781                                         a_style->display =
00782                                                 disp_vals_map[i].type;
00783                                         break;
00784                                 }
00785                         }
00786 
00787                         if (a_style->display == DISPLAY_INHERIT) {
00788                                 if (a_style->parent_style) {
00789                                         a_style->display =
00790                                                 a_style->parent_style->
00791                                                 display;
00792                                 } else {
00793                                         a_style->display =
00794                                                 default_display_val;
00795                                 }
00796                         }
00797                 }
00798                 break;
00799 
00800         default:
00801                 break;
00802         }
00803 
00804         return CR_OK;
00805 }
00806 
00807 struct CRPropPositionValPair {
00808         const guchar *name;
00809         enum CRPositionType type;
00810 };
00811 
00812 static enum CRStatus
00813 set_prop_position_from_value (CRStyle * a_style, CRTerm * a_value)
00814 {
00815         enum CRStatus status = CR_UNKNOWN_PROP_VAL_ERROR;
00816         static const struct CRPropPositionValPair position_vals_map[] = {
00817                 {"static", POSITION_STATIC},
00818                 {"relative", POSITION_RELATIVE},
00819                 {"absolute", POSITION_ABSOLUTE},
00820                 {"fixed", POSITION_FIXED},
00821                 {"inherited", POSITION_INHERIT},
00822                 {NULL, POSITION_STATIC}
00823                 /*must alwas be the last one */
00824         };
00825 
00826         g_return_val_if_fail (a_value, CR_BAD_PARAM_ERROR);
00827 
00828         /*set to it's default value according to the css2 spec */
00829         a_style->position = POSITION_STATIC;
00830 
00831         switch (a_value->type) {
00832         case TERM_IDENT:
00833                 {
00834                         int i = 0;
00835 
00836                         if (!a_value->content.str
00837                             || !a_value->content.str->str)
00838                                 break;
00839 
00840                         for (i = 0; position_vals_map[i].name; i++) {
00841                                 if (!strncmp (position_vals_map[i].name,
00842                                               a_value->content.str->str,
00843                                               strlen (position_vals_map[i].
00844                                                       name))) {
00845                                         a_style->position =
00846                                                 position_vals_map[i].type;
00847                                         status = CR_OK;
00848                                         break;
00849                                 }
00850                         }
00851                         if (a_style->position == POSITION_INHERIT) {
00852                                 if (a_style->parent_style) {
00853                                         a_style->position =
00854                                                 a_style->parent_style->
00855                                                 position;
00856                                 } else {
00857                                         a_style->position = POSITION_STATIC;
00858                                 }
00859                         }
00860                 }
00861                 break;
00862 
00863         default:
00864                 break;
00865         }
00866 
00867         return CR_OK;
00868 }
00869 
00870 static enum CRStatus
00871 set_prop_x_from_value (CRStyle * a_style, CRTerm * a_value,
00872                        enum CRDirection a_dir)
00873 {
00874         CRNum *box_offset = NULL,
00875                 *parent_box_offset = NULL;
00876 
00877         g_return_val_if_fail (a_style && a_value, CR_BAD_PARAM_ERROR);
00878 
00879         if (!(a_value->type == TERM_NUMBER)
00880             && !(a_value->type == TERM_IDENT)) {
00881                 return CR_UNKNOWN_PROP_VAL_ERROR;
00882         }
00883 
00884         switch (a_dir) {
00885         case DIR_TOP:
00886                 box_offset = &a_style->num_props[NUM_PROP_TOP].sv;
00887                 if (a_style->parent_style)
00888                         parent_box_offset =
00889                                 &a_style->parent_style->
00890                                 num_props[NUM_PROP_TOP].sv;
00891                 break;
00892 
00893         case DIR_RIGHT:
00894                 box_offset = &a_style->num_props[NUM_PROP_RIGHT].sv;
00895                 if (a_style->parent_style)
00896                         parent_box_offset = &a_style->parent_style->
00897                                 num_props[NUM_PROP_RIGHT].sv;
00898                 break;
00899 
00900         case DIR_BOTTOM:
00901                 box_offset = &a_style->num_props[NUM_PROP_BOTTOM].sv;
00902                 if (a_style->parent_style)
00903                         parent_box_offset =
00904                                 &a_style->parent_style->
00905                                 num_props[NUM_PROP_BOTTOM].sv;
00906                 break;
00907         case DIR_LEFT:
00908                 box_offset = &a_style->num_props[NUM_PROP_LEFT].sv;
00909                 if (a_style->parent_style)
00910                         parent_box_offset =
00911                                 &a_style->parent_style->
00912                                 num_props[NUM_PROP_LEFT].sv;
00913                 break;
00914 
00915         default:
00916                 break;
00917         }
00918 
00919         box_offset->type = NUM_AUTO;
00920 
00921         if (a_value->type == TERM_NUMBER && a_value->content.num) {
00922                 cr_num_copy (box_offset, a_value->content.num);
00923         } else if (a_value->type == TERM_IDENT
00924                    && a_value->content.str && a_value->content.str->str) {
00925                 if (!strncmp ("inherit",
00926                               a_value->content.str->str,
00927                               strlen ("inherit"))) {
00928                         cr_num_copy (box_offset, parent_box_offset);
00929                 } else if (!strncmp ("auto",
00930                                      a_value->content.str->str,
00931                                      strlen ("auto"))) {
00932                         box_offset->type = NUM_AUTO;
00933                 }
00934         }
00935 
00936         return CR_OK;
00937 }
00938 
00939 static enum CRStatus
00940 set_prop_float (CRStyle * a_style, CRTerm * a_value)
00941 {
00942         g_return_val_if_fail (a_style && a_value, CR_BAD_PARAM_ERROR);
00943 
00944         /*the default float type as specified by the css2 spec */
00945         a_style->float_type = FLOAT_NONE;
00946 
00947         if (a_value->type != TERM_IDENT || !a_value->content.str || !a_value->content.str->str) { /*unknow type, the float type is set to it's default value */
00948                 return CR_OK;
00949         }
00950 
00951         if (!strncmp ("none", a_value->content.str->str, strlen ("none"))) {
00952                 a_style->float_type = FLOAT_NONE;
00953         } else if (!strncmp ("left",
00954                              a_value->content.str->str, strlen ("left"))) {
00955                 a_style->float_type = FLOAT_LEFT;
00956         } else if (!strncmp ("right",
00957                              a_value->content.str->str, strlen ("right"))) {
00958                 a_style->float_type = FLOAT_RIGHT;
00959         } else if (!strncmp ("inherit",
00960                              a_value->content.str->str, strlen ("inherit"))) {
00961                 a_style->float_type = a_style->parent_style->float_type;
00962         }
00963 
00964         return CR_OK;
00965 }
00966 
00967 static enum CRStatus
00968 set_prop_width (CRStyle * a_style, CRTerm * a_value)
00969 {
00970         g_return_val_if_fail (a_style && a_value, CR_BAD_PARAM_ERROR);
00971 
00972         a_style->num_props[NUM_PROP_WIDTH].sv.type = NUM_AUTO;
00973 
00974         if (a_value->type == TERM_IDENT) {
00975                 if (a_value->content.str && a_value->content.str->str) {
00976                         if (!strncmp ("auto",
00977                                       a_value->content.str->str,
00978                                       strlen ("auto"))) {
00979                                 a_style->num_props[NUM_PROP_WIDTH].sv.type =
00980                                         NUM_AUTO;
00981                         } else if (!strncmp ("inherit",
00982                                              a_value->content.str->str,
00983                                              strlen ("inherit"))) {
00984                                 cr_num_copy
00985                                         (&a_style->
00986                                          num_props[NUM_PROP_WIDTH].sv,
00987                                          &a_style->parent_style->
00988                                          num_props[NUM_PROP_WIDTH].sv);
00989                         }
00990                 }
00991         } else if (a_value->type == TERM_NUMBER) {
00992                 if (a_value->content.num) {
00993                         cr_num_copy (&a_style->num_props[NUM_PROP_WIDTH].sv,
00994                                      a_value->content.num);
00995                 }
00996         }
00997 
00998         return CR_OK;
00999 }
01000 
01001 static enum CRStatus 
01002 set_prop_color (CRStyle * a_style, CRTerm * a_value)
01003 {
01004         enum CRStatus status = CR_OK;
01005         CRRgb *a_rgb = &a_style->rgb_props[RGB_PROP_COLOR].sv;
01006 
01007         g_return_val_if_fail (a_style && a_value, CR_BAD_PARAM_ERROR);
01008 
01009         status = cr_rgb_set_from_term (a_rgb, a_value);
01010 
01011         return status;
01012 }
01013 
01014 static enum CRStatus
01015 set_prop_background_color (CRStyle * a_style, CRTerm * a_value)
01016 {
01017         enum CRStatus status = CR_OK;
01018         CRRgb *a_rgb = &a_style->rgb_props[RGB_PROP_BACKGROUND_COLOR].sv;
01019 
01020         g_return_val_if_fail (a_style && a_value, CR_BAD_PARAM_ERROR);
01021 
01022         status = cr_rgb_set_from_term (a_rgb, a_value);
01023 
01024         return status;
01025 }
01026 
01027 /**
01028  *Sets border-top-color, border-right-color,
01029  *border-bottom-color or border-left-color properties
01030  *in the style structure. The value is taken from a
01031  *css2 term of type IDENT or RGB.
01032  *@param a_style the style structure to set.
01033  *@param a_value the css2 term to take the color information from.
01034  *@param a_dir the direction (TOP, LEFT, RIGHT, or BOTTOM).
01035  *@return CR_OK upon successfull completion, an error code otherwise.
01036  */
01037 static enum CRStatus
01038 set_prop_border_x_color_from_value (CRStyle * a_style, CRTerm * a_value,
01039                                     enum CRDirection a_dir)
01040 {
01041         CRRgb *rgb_color = NULL;
01042         enum CRStatus status = CR_OK;
01043 
01044         g_return_val_if_fail (a_style && a_value, CR_BAD_PARAM_ERROR);
01045 
01046         switch (a_dir) {
01047         case DIR_TOP:
01048                 rgb_color = &a_style->rgb_props[RGB_PROP_BORDER_TOP_COLOR].sv;
01049                 break;
01050 
01051         case DIR_RIGHT:
01052                 rgb_color =
01053                         &a_style->rgb_props[RGB_PROP_BORDER_RIGHT_COLOR].sv;
01054                 break;
01055 
01056         case DIR_BOTTOM:
01057                 rgb_color =
01058                         &a_style->rgb_props[RGB_PROP_BORDER_BOTTOM_COLOR].sv;
01059                 break;
01060 
01061         case DIR_LEFT:
01062                 rgb_color =
01063                         &a_style->rgb_props[RGB_PROP_BORDER_LEFT_COLOR].sv;
01064                 break;
01065 
01066         default:
01067                 cr_utils_trace_info ("unknown DIR type");
01068                 return CR_BAD_PARAM_ERROR;
01069         }
01070 
01071         status = CR_UNKNOWN_PROP_VAL_ERROR;
01072 
01073         if (a_value->type == TERM_IDENT) {
01074                 if (a_value->content.str && a_value->content.str->str) {
01075                         status = cr_rgb_set_from_name
01076                                 (rgb_color, a_value->content.str->str);
01077 
01078                 }
01079 
01080                 if (status != CR_OK) {
01081                         cr_rgb_set_from_name (rgb_color, "black");
01082                 }
01083         } else if (a_value->type == TERM_RGB) {
01084                 if (a_value->content.rgb) {
01085                         status = cr_rgb_set_from_rgb
01086                                 (rgb_color, a_value->content.rgb);
01087                 }
01088         }
01089 
01090         return status;
01091 }
01092 
01093 static enum CRStatus
01094 set_prop_border_x_from_value (CRStyle * a_style, CRTerm * a_value,
01095                               enum CRDirection a_dir)
01096 {
01097         CRTerm *cur_term = NULL;
01098 
01099         enum CRStatus status = CR_OK;
01100 
01101         g_return_val_if_fail (a_style && a_value, CR_BAD_PARAM_ERROR);
01102 
01103         for (cur_term = a_value; cur_term; cur_term = cur_term->next) {
01104                 status = set_prop_border_x_width_from_value (a_style,
01105                                                              cur_term, a_dir);
01106 
01107                 if (status != CR_OK) {
01108                         status = set_prop_border_x_style_from_value
01109                                 (a_style, cur_term, a_dir);
01110                 }
01111 
01112                 if (status != CR_OK) {
01113                         status = set_prop_border_x_color_from_value
01114                                 (a_style, cur_term, a_dir);
01115                 }
01116         }
01117 
01118         return CR_OK;
01119 }
01120 
01121 static enum CRStatus
01122 set_prop_border_from_value (CRStyle * a_style, CRTerm * a_value)
01123 {
01124         enum CRDirection direction = 0;
01125 
01126         g_return_val_if_fail (a_style && a_value, CR_BAD_PARAM_ERROR);
01127 
01128         for (direction = 0; direction < NB_DIRS; direction++) {
01129                 set_prop_border_x_from_value (a_style, a_value, direction);
01130         }
01131 
01132         return CR_OK;
01133 }
01134 
01135 static enum CRStatus
01136 set_prop_padding_from_value (CRStyle * a_style, CRTerm * a_value)
01137 {
01138         CRTerm *cur_term = NULL;
01139         enum CRDirection direction = 0;
01140         enum CRStatus status = CR_OK;
01141 
01142         g_return_val_if_fail (a_style && a_value, CR_BAD_PARAM_ERROR);
01143 
01144         cur_term = a_value;
01145         while (cur_term && cur_term->type != TERM_NUMBER) {
01146                 cur_term = cur_term->next;
01147         }
01148 
01149         if (!cur_term)
01150                 return CR_OK;
01151 
01152         for (direction = 0; direction < NB_DIRS; direction++) {
01153                 set_prop_padding_x_from_value (a_style, cur_term, direction);
01154         }
01155         cur_term = cur_term->next;
01156 
01157         while (cur_term && cur_term->type != TERM_NUMBER) {
01158                 cur_term = cur_term->next;
01159         }
01160         if (!cur_term)
01161                 return CR_OK;
01162 
01163         set_prop_padding_x_from_value (a_style, cur_term, DIR_RIGHT);
01164         set_prop_padding_x_from_value (a_style, cur_term, DIR_LEFT);
01165 
01166         while (cur_term && cur_term->type != TERM_NUMBER) {
01167                 cur_term = cur_term->next;
01168         }
01169         if (!cur_term)
01170                 return CR_OK;
01171 
01172         set_prop_padding_x_from_value (a_style, cur_term, DIR_BOTTOM);
01173 
01174         while (cur_term && cur_term->type != TERM_NUMBER) {
01175                 cur_term = cur_term->next;
01176         }
01177         if (!cur_term)
01178                 return CR_OK;
01179 
01180         status = set_prop_padding_x_from_value (a_style, cur_term, DIR_LEFT);
01181 
01182         return status;
01183 }
01184 
01185 static enum CRStatus
01186 set_prop_margin_from_value (CRStyle * a_style, CRTerm * a_value)
01187 {
01188         CRTerm *cur_term = NULL;
01189         enum CRDirection direction = 0;
01190         enum CRStatus status = CR_OK;
01191 
01192         g_return_val_if_fail (a_style && a_value, CR_BAD_PARAM_ERROR);
01193 
01194         cur_term = a_value;
01195         while (cur_term && cur_term->type != TERM_NUMBER) {
01196                 cur_term = cur_term->next;
01197         }
01198 
01199         if (!cur_term)
01200                 return CR_OK;
01201 
01202         for (direction = 0; direction < NB_DIRS; direction++) {
01203                 set_prop_margin_x_from_value (a_style, cur_term, direction);
01204         }
01205         cur_term = cur_term->next;
01206 
01207         while (cur_term && cur_term->type != TERM_NUMBER) {
01208                 cur_term = cur_term->next;
01209         }
01210         if (!cur_term)
01211                 return CR_OK;
01212 
01213         set_prop_margin_x_from_value (a_style, cur_term, DIR_RIGHT);
01214         set_prop_margin_x_from_value (a_style, cur_term, DIR_LEFT);
01215 
01216         while (cur_term && cur_term->type != TERM_NUMBER) {
01217                 cur_term = cur_term->next;
01218         }
01219         if (!cur_term)
01220                 return CR_OK;
01221 
01222         set_prop_margin_x_from_value (a_style, cur_term, DIR_BOTTOM);
01223 
01224         while (cur_term && cur_term->type != TERM_NUMBER) {
01225                 cur_term = cur_term->next;
01226         }
01227         if (!cur_term)
01228                 return CR_OK;
01229 
01230         status = set_prop_margin_x_from_value (a_style, cur_term, DIR_LEFT);
01231 
01232         return status;
01233 }
01234 
01235 static enum CRStatus
01236 set_prop_font_family_from_value (CRStyle * a_style, CRTerm * a_value)
01237 {
01238         CRTerm *cur_term = NULL;
01239         CRFontFamily *font_family = NULL,
01240                 *cur_ff = NULL,
01241                 *cur_ff2 = NULL;
01242 
01243         g_return_val_if_fail (a_style && a_value, CR_BAD_PARAM_ERROR);
01244 
01245         for (cur_term = a_value; cur_term; cur_term = cur_term->next) {
01246                 switch (cur_term->type) {
01247                 case TERM_IDENT:
01248                         {
01249                                 enum CRFontFamilyType font_type;
01250 
01251                                 if (cur_term->content.str
01252                                     && cur_term->content.str->str
01253                                     && !strcmp (cur_term->content.str->str,
01254                                                 "sans-serif")) {
01255                                         font_type = FONT_FAMILY_SANS_SERIF;
01256                                 } else if (cur_term->content.str
01257                                            && cur_term->content.str->str
01258                                            && !strcmp (cur_term->content.str->
01259                                                        str, "serif")) {
01260                                         font_type = FONT_FAMILY_SERIF;
01261                                 } else if (cur_term->content.str
01262                                            && cur_term->content.str->str
01263                                            && !strcmp (cur_term->content.str->
01264                                                        str, "cursive")) {
01265                                         font_type = FONT_FAMILY_CURSIVE;
01266                                 } else if (cur_term->content.str
01267                                            && cur_term->content.str->str
01268                                            && !strcmp (cur_term->content.str->
01269                                                        str, "fantasy")) {
01270                                         font_type = FONT_FAMILY_FANTASY;
01271                                 } else if (cur_term->content.str
01272                                            && cur_term->content.str->str
01273                                            && !strcmp (cur_term->content.str->
01274                                                        str, "monospace")) {
01275                                         font_type = FONT_FAMILY_MONOSPACE;
01276                                 } else {
01277                                         /*
01278                                          *unknown property value.
01279                                          *ignore it.
01280                                          */
01281                                         continue;
01282                                 }
01283 
01284                                 cur_ff = cr_font_family_new (font_type, NULL);
01285                         }
01286                         break;
01287 
01288                 case TERM_STRING:
01289                         {
01290                                 if (cur_term->content.str
01291                                     && cur_term->content.str->str) {
01292                                         cur_ff = cr_font_family_new
01293                                                 (FONT_FAMILY_NON_GENERIC,
01294                                                  cur_term->content.str->str);
01295                                 }
01296                         }
01297                         break;
01298 
01299                 default:
01300                         break;
01301                 }
01302 
01303                 cur_ff2 = cr_font_family_append (font_family, cur_ff);
01304                 if (cur_ff2) {
01305                         font_family = cur_ff2;
01306                 }
01307         }
01308 
01309         if (font_family) {
01310                 if (a_style->font_family) {
01311                         cr_font_family_destroy (a_style->font_family);
01312                         a_style->font_family = font_family;
01313                 }
01314         }
01315 
01316         return CR_OK;
01317 }
01318 
01319 static enum CRStatus
01320 init_style_font_size_field (CRStyle * a_style)
01321 {
01322         g_return_val_if_fail (a_style, CR_BAD_PARAM_ERROR);
01323 
01324         if (!a_style->font_size) {
01325                 a_style->font_size = cr_font_size_new ();
01326                 if (!a_style->font_size) {
01327                         return CR_INSTANCIATION_FAILED_ERROR;
01328                 }
01329         } else {
01330                 cr_font_size_clear (a_style->font_size);
01331         }
01332 
01333         return CR_OK;
01334 }
01335 
01336 static enum CRStatus
01337 set_prop_font_size_from_value (CRStyle * a_style, CRTerm * a_value)
01338 {
01339         enum CRStatus status = CR_OK;
01340 
01341         g_return_val_if_fail (a_style && a_value, CR_BAD_PARAM_ERROR);
01342 
01343         switch (a_value->type) {
01344         case TERM_IDENT:
01345                 if (a_value->content.str
01346                     && a_value->content.str->str
01347                     && !strcmp (a_value->content.str->str, "xx-small")) {
01348                         status = init_style_font_size_field (a_style);
01349                         g_return_val_if_fail (status == CR_OK, status);
01350 
01351                         a_style->font_size->type =
01352                                 PREDEFINED_ABSOLUTE_FONT_SIZE;
01353                         a_style->font_size->value.predefined =
01354                                 FONT_SIZE_XX_SMALL;
01355 
01356                 } else if (a_value->content.str
01357                            && a_value->content.str->str
01358                            && !strcmp (a_value->content.str->str, "x-small"))
01359                 {
01360                         status = init_style_font_size_field (a_style);
01361                         g_return_val_if_fail (status == CR_OK, status);
01362 
01363                         a_style->font_size->type =
01364                                 PREDEFINED_ABSOLUTE_FONT_SIZE;
01365                         a_style->font_size->value.predefined =
01366                                 FONT_SIZE_X_SMALL;
01367                 } else if (a_value->content.str
01368                            && a_value->content.str->str
01369                            && !strcmp (a_value->content.str->str, "small")) {
01370                         status = init_style_font_size_field (a_style);
01371                         g_return_val_if_fail (status == CR_OK, status);
01372 
01373                         a_style->font_size->type =
01374                                 PREDEFINED_ABSOLUTE_FONT_SIZE;
01375                         a_style->font_size->value.predefined =
01376                                 FONT_SIZE_SMALL;
01377                 } else if (a_value->content.str
01378                            && a_value->content.str->str
01379                            && !strcmp (a_value->content.str->str, "medium")) {
01380                         status = init_style_font_size_field (a_style);
01381                         g_return_val_if_fail (status == CR_OK, status);
01382 
01383                         a_style->font_size->type =
01384                                 PREDEFINED_ABSOLUTE_FONT_SIZE;
01385                         a_style->font_size->value.predefined =
01386                                 FONT_SIZE_MEDIUM;
01387                 } else if (a_value->content.str
01388                            && a_value->content.str->str
01389                            && !strcmp (a_value->content.str->str, "large")) {
01390                         status = init_style_font_size_field (a_style);
01391                         g_return_val_if_fail (status == CR_OK, status);
01392 
01393                         a_style->font_size->type =
01394                                 PREDEFINED_ABSOLUTE_FONT_SIZE;
01395                         a_style->font_size->value.predefined =
01396                                 FONT_SIZE_LARGE;
01397                 } else if (a_value->content.str
01398                            && a_value->content.str->str
01399                            && !strcmp (a_value->content.str->str, "x-large"))
01400                 {
01401                         status = init_style_font_size_field (a_style);
01402                         g_return_val_if_fail (status == CR_OK, status);
01403 
01404                         a_style->font_size->type =
01405                                 PREDEFINED_ABSOLUTE_FONT_SIZE;
01406                         a_style->font_size->value.predefined =
01407                                 FONT_SIZE_X_LARGE;
01408                 } else if (a_value->content.str
01409                            && a_value->content.str->str
01410                            && !strcmp (a_value->content.str->str, "xx-large"))
01411                 {
01412                         status = init_style_font_size_field (a_style);
01413                         g_return_val_if_fail (status == CR_OK, status);
01414 
01415                         a_style->font_size->type =
01416                                 PREDEFINED_ABSOLUTE_FONT_SIZE;
01417                         a_style->font_size->value.predefined =
01418                                 FONT_SIZE_XX_LARGE;
01419                 } else if (a_value->content.str
01420                            && a_value->content.str->str
01421                            && !strcmp (a_value->content.str->str, "larger")) {
01422                         status = init_style_font_size_field (a_style);
01423                         g_return_val_if_fail (status == CR_OK, status);
01424 
01425                         a_style->font_size->type = RELATIVE_FONT_SIZE;
01426                         a_style->font_size->value.relative = FONT_SIZE_LARGER;
01427                 } else if (a_value->content.str
01428                            && a_value->content.str->str
01429                            && !strcmp (a_value->content.str->str, "smaller"))
01430                 {
01431                         status = init_style_font_size_field (a_style);
01432                         g_return_val_if_fail (status == CR_OK, status);
01433 
01434                         a_style->font_size->type = RELATIVE_FONT_SIZE;
01435                         a_style->font_size->value.relative =
01436                                 FONT_SIZE_SMALLER;
01437                 } else if (a_value->content.str
01438                            && a_value->content.str->str
01439                            && !strcmp (a_value->content.str->str, "inherit"))
01440                 {
01441                         status = init_style_font_size_field (a_style);
01442                         g_return_val_if_fail (status == CR_OK, status);
01443 
01444                         if (a_style->parent_style
01445                             && a_style->parent_style->font_style) {
01446                                 cr_font_size_copy
01447                                         (a_style->font_size,
01448                                          a_style->parent_style->font_size);
01449                         }
01450                 } else {
01451                         return CR_UNKNOWN_PROP_VAL_ERROR;
01452                 }
01453                 break;
01454 
01455         case TERM_NUMBER:
01456                 if (a_value->content.num) {
01457                         status = init_style_font_size_field (a_style);
01458                         g_return_val_if_fail (status == CR_OK, status);
01459 
01460                         a_style->font_size->type = ABSOLUTE_FONT_SIZE;
01461                         a_style->font_size->value.absolute =
01462                                 cr_num_dup (a_value->content.num);
01463                 }
01464                 break;
01465 
01466         default:
01467                 return CR_UNKNOWN_PROP_VAL_ERROR;
01468         }
01469 
01470         return CR_OK;
01471 }
01472 
01473 static enum CRStatus
01474 set_prop_font_style_from_value (CRStyle * a_style, CRTerm * a_value)
01475 {
01476         enum CRStatus status = CR_OK;
01477 
01478         g_return_val_if_fail (a_style && a_value, CR_BAD_PARAM_ERROR);
01479 
01480         switch (a_value->type) {
01481         case TERM_IDENT:
01482                 if (a_value->content.str && a_value->content.str->str) {
01483                         if (!strcmp (a_value->content.str->str, "normal")) {
01484                                 a_style->font_style = FONT_STYLE_NORMAL;
01485                         } else if (!strcmp
01486                                    (a_value->content.str->str, "italic")) {
01487                                 a_style->font_style = FONT_STYLE_ITALIC;
01488                         } else if (!strcmp
01489                                    (a_value->content.str->str, "oblique")) {
01490                                 a_style->font_style = FONT_STYLE_OBLIQUE;
01491                         } else if (!strcmp
01492                                    (a_value->content.str->str, "inherit")) {
01493                                 if (!a_style->font_style)
01494                                         a_style->font_style =
01495                                                 FONT_STYLE_NORMAL;
01496                                 else
01497                                         a_style->font_style =
01498                                                 a_style->parent_style->
01499                                                 font_style;
01500                         } else {
01501                                 status = CR_UNKNOWN_PROP_VAL_ERROR;
01502                         }
01503                 }
01504                 break;
01505 
01506         default:
01507                 status = CR_UNKNOWN_PROP_VAL_ERROR;
01508                 break;
01509         }
01510 
01511         return status;
01512 }
01513 
01514 static enum CRStatus
01515 set_prop_font_weight_from_value (CRStyle * a_style, CRTerm * a_value)
01516 {
01517         enum CRStatus status = CR_OK;
01518 
01519         g_return_val_if_fail (a_style && a_value, CR_BAD_PARAM_ERROR);
01520 
01521         switch (a_value->type) {
01522         case TERM_IDENT:
01523                 if (a_value->content.str && a_value->content.str->str) {
01524                         if (!strcmp (a_value->content.str->str, "normal")) {
01525                                 a_style->font_weight = FONT_WEIGHT_NORMAL;
01526                         } else if (!strcmp (a_value->content.str->str,
01527                                             "bold")) {
01528                                 a_style->font_weight = FONT_WEIGHT_BOLD;
01529                         } else if (!strcmp (a_value->content.str->str,
01530                                             "bolder")) {
01531                                 a_style->font_weight = FONT_WEIGHT_BOLDER;
01532                         } else if (!strcmp (a_value->content.str->str,
01533                                             "lighter")) {
01534                                 a_style->font_weight = FONT_WEIGHT_LIGHTER;
01535                         } else {
01536                                 status = CR_UNKNOWN_PROP_VAL_ERROR;
01537                         }
01538 
01539                 }
01540                 break;
01541 
01542         case TERM_NUMBER:
01543                 if (a_value->content.num
01544                     && (a_value->content.num->type == NUM_GENERIC
01545                         || a_value->content.num->type == NUM_AUTO)) {
01546                         if (a_value->content.num->val <= 150) {
01547                                 a_style->font_weight = FONT_WEIGHT_100;
01548                         } else if (a_value->content.num->val <= 250) {
01549                                 a_style->font_weight = FONT_WEIGHT_200;
01550                         } else if (a_value->content.num->val <= 350) {
01551                                 a_style->font_weight = FONT_WEIGHT_300;
01552                         } else if (a_value->content.num->val <= 450) {
01553                                 a_style->font_weight = FONT_WEIGHT_400;
01554                         } else if (a_value->content.num->val <= 550) {
01555                                 a_style->font_weight = FONT_WEIGHT_500;
01556                         } else if (a_value->content.num->val <= 650) {
01557                                 a_style->font_weight = FONT_WEIGHT_600;
01558                         } else if (a_value->content.num->val <= 750) {
01559                                 a_style->font_weight = FONT_WEIGHT_700;
01560                         } else if (a_value->content.num->val <= 850) {
01561                                 a_style->font_weight = FONT_WEIGHT_800;
01562                         } else {
01563                                 a_style->font_weight = FONT_WEIGHT_900;
01564                         }
01565                 }
01566                 break;
01567 
01568         default:
01569                 status = CR_UNKNOWN_PROP_VAL_ERROR;
01570                 break;
01571         }
01572 
01573         return status;
01574 }
01575 
01576 /******************
01577  *Public methods
01578  ******************/
01579 
01580 /**
01581  *Default constructor of #CRStyle.
01582  */
01583 CRStyle *
01584 cr_style_new (void)
01585 {
01586         CRStyle *result = NULL;
01587 
01588         result = g_try_malloc (sizeof (CRStyle));
01589         if (!result) {
01590                 cr_utils_trace_info ("Out of memory");
01591                 return NULL;
01592         }
01593         memset (result, 0, sizeof (CRStyle));
01594         gv_prop_hash_ref_count++;
01595 
01596         /*set the style properties to their default values */
01597         cr_style_set_props_to_defaults (result);
01598 
01599         return result;
01600 }
01601 
01602 /**
01603  *Sets the style properties to their default values
01604  *according to the css2 spec.
01605  *@param a_this the current instance of #CRStyle.
01606  *@return CR_OK upon successfull completion, an error code otherwise.
01607  */
01608 enum CRStatus
01609 cr_style_set_props_to_defaults (CRStyle * a_this)
01610 {
01611         glong i = 0;
01612 
01613         g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
01614 
01615         for (i = 0; i < NB_NUM_PROPS; i++) {
01616                 switch (i) {
01617                 case NUM_PROP_WIDTH:
01618                 case NUM_PROP_TOP:
01619                 case NUM_PROP_RIGHT:
01620                 case NUM_PROP_BOTTOM:
01621                 case NUM_PROP_LEFT:
01622                         cr_num_set (&a_this->num_props[i].sv, 0, NUM_AUTO);
01623                         break;
01624 
01625                 case NUM_PROP_PADDING_TOP:
01626                 case NUM_PROP_PADDING_RIGHT:
01627                 case NUM_PROP_PADDING_BOTTOM:
01628                 case NUM_PROP_PADDING_LEFT:
01629                 case NUM_PROP_BORDER_TOP:
01630                 case NUM_PROP_BORDER_RIGHT:
01631                 case NUM_PROP_BORDER_BOTTOM:
01632                 case NUM_PROP_BORDER_LEFT:
01633                 case NUM_PROP_MARGIN_TOP:
01634                 case NUM_PROP_MARGIN_RIGHT:
01635                 case NUM_PROP_MARGIN_BOTTOM:
01636                 case NUM_PROP_MARGIN_LEFT:
01637                         cr_num_set (&a_this->num_props[i].sv,
01638                                     0, NUM_LENGTH_PX);
01639                         break;
01640 
01641                 default:
01642                         cr_utils_trace_info ("Unknown property");
01643                         break;
01644                 }
01645         }
01646 
01647         for (i = 0; i < NB_RGB_PROPS; i++) {
01648 
01649                 switch (i) {
01650                         /*default foreground color is black */
01651                 case RGB_PROP_COLOR:
01652                         cr_rgb_set (&a_this->rgb_props[i].sv, 0, 0, 0, FALSE);
01653                         break;
01654 
01655                         /*default background color is white */
01656                 case RGB_PROP_BACKGROUND_COLOR:
01657                         cr_rgb_set (&a_this->rgb_props[i].sv,
01658                                     255, 255, 255, FALSE);
01659                         break;
01660 
01661                 default:
01662                         cr_rgb_set (&a_this->rgb_props[i].sv, 0, 0, 0, FALSE);
01663                         break;
01664                 }
01665         }
01666 
01667         for (i = 0; i < NB_BORDER_STYLE_PROPS; i++) {
01668                 a_this->border_style_props[i] = BORDER_STYLE_NONE;
01669         }
01670 
01671         a_this->display = DISPLAY_BLOCK;
01672         a_this->position = POSITION_STATIC;
01673         a_this->float_type = FLOAT_NONE;
01674         a_this->parent_style = NULL;
01675         a_this->font_style = FONT_STYLE_NORMAL;
01676         a_this->font_variant = FONT_VARIANT_NORMAL;
01677         a_this->font_weight = FONT_WEIGHT_NORMAL;
01678         a_this->font_stretch = FONT_STRETCH_NORMAL;
01679         return CR_OK;
01680 }
01681 
01682 /**
01683  *Walks through a css2 property declaration, and populated the
01684  *according field(s) in the #CRStyle structure.
01685  *If the properties or their value(s) are/is not known, 
01686  *sets the corresponding field(s) of #CRStyle to its/their default 
01687  *value(s)
01688  *@param a_this the instance of #CRStyle to set.
01689  *@param a_decl the declaration from which the #CRStyle fields are set.
01690  *@return CR_OK upon successfull completion, an error code otherwise.
01691  */
01692 enum CRStatus
01693 cr_style_set_style_from_decl (CRStyle * a_this, CRDeclaration * a_decl)
01694 {
01695         CRTerm *value = NULL;
01696         enum CRStatus status = CR_OK;
01697 
01698         enum CRPropertyID prop_id = PROP_ID_NOT_KNOWN;
01699 
01700         g_return_val_if_fail (a_this && a_decl
01701                               && a_decl
01702                               && a_decl->property
01703                               && a_decl->property->str, CR_BAD_PARAM_ERROR);
01704 
01705         prop_id = cr_style_get_prop_id (a_decl->property->str);
01706 
01707         value = a_decl->value;
01708         switch (prop_id) {
01709         case PROP_ID_PADDING_TOP:
01710                 status = set_prop_padding_x_from_value
01711                         (a_this, value, DIR_TOP);
01712                 break;
01713 
01714         case PROP_ID_PADDING_RIGHT:
01715                 status = set_prop_padding_x_from_value
01716                         (a_this, value, DIR_RIGHT);
01717                 break;
01718         case PROP_ID_PADDING_BOTTOM:
01719                 status = set_prop_padding_x_from_value
01720                         (a_this, value, DIR_BOTTOM);
01721                 break;
01722 
01723         case PROP_ID_PADDING_LEFT:
01724                 status = set_prop_padding_x_from_value
01725                         (a_this, value, DIR_LEFT);
01726                 break;
01727 
01728         case PROP_ID_PADDING:
01729                 status = set_prop_padding_from_value (a_this, value);
01730                 break;
01731 
01732         case PROP_ID_BORDER_TOP_WIDTH:
01733                 status = set_prop_border_x_width_from_value (a_this, value,
01734                                                              DIR_TOP);
01735                 break;
01736 
01737         case PROP_ID_BORDER_RIGHT_WIDTH:
01738                 status = set_prop_border_x_width_from_value (a_this, value,
01739                                                              DIR_RIGHT);
01740                 break;
01741 
01742         case PROP_ID_BORDER_BOTTOM_WIDTH:
01743                 status = set_prop_border_x_width_from_value (a_this, value,
01744                                                              DIR_BOTTOM);
01745                 break;
01746 
01747         case PROP_ID_BORDER_LEFT_WIDTH:
01748                 status = set_prop_border_x_width_from_value (a_this, value,
01749                                                              DIR_LEFT);
01750                 break;
01751 
01752         case PROP_ID_BORDER_TOP_STYLE:
01753                 status = set_prop_border_x_style_from_value (a_this, value,
01754                                                              DIR_TOP);
01755                 break;
01756 
01757         case PROP_ID_BORDER_RIGHT_STYLE:
01758                 status = set_prop_border_x_style_from_value (a_this, value,
01759                                                              DIR_RIGHT);
01760                 break;
01761 
01762         case PROP_ID_BORDER_BOTTOM_STYLE:
01763                 status = set_prop_border_x_style_from_value (a_this, value,
01764                                                              DIR_BOTTOM);
01765                 break;
01766 
01767         case PROP_ID_BORDER_LEFT_STYLE:
01768                 status = set_prop_border_x_style_from_value (a_this, value,
01769                                                              DIR_LEFT);
01770                 break;
01771 
01772         case PROP_ID_BORDER_TOP_COLOR:
01773                 status = set_prop_border_x_color_from_value (a_this, value,
01774                                                              DIR_TOP);
01775                 break;
01776 
01777         case PROP_ID_BORDER_RIGHT_COLOR:
01778                 status = set_prop_border_x_color_from_value (a_this, value,
01779                                                              DIR_RIGHT);
01780                 break;
01781 
01782         case PROP_ID_BORDER_BOTTOM_COLOR:
01783                 status = set_prop_border_x_color_from_value (a_this, value,
01784                                                              DIR_BOTTOM);
01785                 break;
01786 
01787         case PROP_ID_BORDER_LEFT_COLOR:
01788                 status = set_prop_border_x_color_from_value (a_this, value,
01789                                                              DIR_BOTTOM);
01790                 break;
01791 
01792         case PROP_ID_BORDER_TOP:
01793                 status = set_prop_border_x_from_value (a_this, value,
01794                                                        DIR_TOP);
01795                 break;
01796 
01797         case PROP_ID_BORDER_RIGHT:
01798                 status = set_prop_border_x_from_value (a_this, value,
01799                                                        DIR_RIGHT);
01800                 break;
01801 
01802         case PROP_ID_BORDER_BOTTOM:
01803                 status = set_prop_border_x_from_value (a_this, value,
01804                                                        DIR_BOTTOM);
01805                 break;
01806 
01807         case PROP_ID_BORDER_LEFT:
01808                 status = set_prop_border_x_from_value (a_this, value,
01809                                                        DIR_LEFT);
01810                 break;
01811 
01812         case PROP_ID_MARGIN_TOP:
01813                 status = set_prop_margin_x_from_value (a_this, value,
01814                                                        DIR_TOP);
01815                 break;
01816 
01817         case PROP_ID_BORDER:
01818                 status = set_prop_border_from_value (a_this, value);
01819                 break;
01820 
01821         case PROP_ID_MARGIN_RIGHT:
01822                 status = set_prop_margin_x_from_value (a_this, value,
01823                                                        DIR_RIGHT);
01824                 break;
01825 
01826         case PROP_ID_MARGIN_BOTTOM:
01827                 status = set_prop_margin_x_from_value (a_this, value,
01828                                                        DIR_BOTTOM);
01829                 break;
01830 
01831         case PROP_ID_MARGIN_LEFT:
01832                 status = set_prop_margin_x_from_value (a_this, value,
01833                                                        DIR_LEFT);
01834                 break;
01835 
01836         case PROP_ID_MARGIN:
01837                 status = set_prop_margin_from_value (a_this, value);
01838                 break;
01839 
01840         case PROP_ID_DISPLAY:
01841                 status = set_prop_display_from_value (a_this, value);
01842                 break;
01843 
01844         case PROP_ID_POSITION:
01845                 status = set_prop_position_from_value (a_this, value);
01846                 break;
01847 
01848         case PROP_ID_TOP:
01849                 status = set_prop_x_from_value (a_this, value, DIR_TOP);
01850                 break;
01851 
01852         case PROP_ID_RIGHT:
01853                 status = set_prop_x_from_value (a_this, value, DIR_RIGHT);
01854                 break;
01855 
01856         case PROP_ID_BOTTOM:
01857                 status = set_prop_x_from_value (a_this, value, DIR_BOTTOM);
01858                 break;
01859 
01860         case PROP_ID_LEFT:
01861                 status = set_prop_x_from_value (a_this, value, DIR_LEFT);
01862                 break;
01863 
01864         case PROP_ID_FLOAT:
01865                 status = set_prop_float (a_this, value);
01866                 break;
01867 
01868         case PROP_ID_WIDTH:
01869                 status = set_prop_width (a_this, value);
01870                 break;
01871 
01872         case PROP_ID_COLOR:
01873                 status = set_prop_color (a_this, value);
01874                 break;
01875 
01876         case PROP_ID_BACKGROUND_COLOR:
01877                 status = set_prop_background_color (a_this, value);
01878                 break;
01879 
01880         case PROP_ID_FONT_FAMILY:
01881                 status = set_prop_font_family_from_value (a_this, value);
01882                 break;
01883 
01884         case PROP_ID_FONT_SIZE:
01885                 status = set_prop_font_size_from_value (a_this, value);
01886                 break;
01887 
01888         case PROP_ID_FONT_STYLE:
01889                 status = set_prop_font_style_from_value (a_this, value);
01890                 break;
01891 
01892         case PROP_ID_FONT_WEIGHT:
01893                 status = set_prop_font_weight_from_value (a_this, value);
01894                 break;
01895 
01896         default:
01897                 return CR_UNKNOWN_TYPE_ERROR;
01898 
01899         }
01900 
01901         return status;
01902 }
01903 
01904 /**
01905  *Increases the reference count
01906  *of the current instance of #CRStyle.
01907  *@param a_this the current instance of #CRStyle.
01908  *@return CR_OK upon successfull completion, an error code
01909  *otherwise.
01910  */
01911 enum CRStatus
01912 cr_style_ref (CRStyle * a_this)
01913 {
01914         g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
01915 
01916         a_this->ref_count++;
01917         return CR_OK;
01918 }
01919 
01920 /**
01921  *Decreases the reference count of
01922  *the current instance of #CRStyle.
01923  *If the reference count reaches 0, the
01924  *instance of #CRStyle is destoyed.
01925  *@param a_this the current instance of #CRStyle.
01926  *@return TRUE if the instance has been destroyed, FALSE
01927  *otherwise.
01928  */
01929 gboolean
01930 cr_style_unref (CRStyle * a_this)
01931 {
01932         g_return_val_if_fail (a_this, FALSE);
01933 
01934         if (a_this->ref_count)
01935                 a_this->ref_count--;
01936 
01937         if (!a_this->ref_count) {
01938                 cr_style_destroy (a_this);
01939                 return TRUE;
01940         }
01941 
01942         return FALSE;
01943 }
01944 
01945 /**
01946  *Duplicates the current instance of #CRStyle .
01947  *The newly created instance of #CRStyle must be
01948  *freed using cr_style_destroy ().
01949  *@param a_this the current instance of #CRStyle.
01950  *@return the newly duplicated instance of #CRStyle.
01951  */
01952 CRStyle *
01953 cr_style_dup (CRStyle * a_this)
01954 {
01955         CRStyle *result = NULL;
01956 
01957         g_return_val_if_fail (a_this, NULL);
01958 
01959         result = cr_style_new ();
01960         if (!result) {
01961                 cr_utils_trace_info ("Out of memory");
01962                 return NULL;
01963         }
01964         cr_style_copy (result, a_this);
01965         return result;
01966 }
01967 
01968 /**
01969  *Copies a style data structure into another.
01970  *TODO: this is actually broken because it's based
01971  *on memcpy although some data stuctures of CRStyle should
01972  *be properly duplicated.
01973  *@param a_dest the destination style datastructure
01974  *@param a_src the source style datastructure.
01975  *@return CR_OK upon succesfull completion, an error code otherwise
01976  */
01977 enum CRStatus
01978 cr_style_copy (CRStyle * a_dest, CRStyle * a_src)
01979 {
01980         g_return_val_if_fail (a_dest && a_src, CR_BAD_PARAM_ERROR);
01981 
01982         memcpy (a_dest, a_src, sizeof (CRStyle));
01983         return CR_OK;
01984 }
01985 
01986 /**
01987  *dump a CRNumpPropVal in a string.
01988  *@param a_prop_val the numerical property value to dump
01989  *@param a_str the string to dump the numerical propertie into.
01990  *Note that the string value is appended to a_str.
01991  *@param a_nb_indent the number white chars of indentation.
01992  */
01993 enum CRStatus
01994 cr_style_num_prop_val_to_string (CRNumPropVal * a_prop_val,
01995                                  GString * a_str, guint a_nb_indent)
01996 {
01997         enum CRStatus status = CR_OK;
01998         guchar *tmp_str = NULL;
01999         GString *str = NULL;
02000 
02001         g_return_val_if_fail (a_prop_val && a_str, CR_BAD_PARAM_ERROR);
02002 
02003         str = g_string_new (NULL);
02004         cr_utils_dump_n_chars2 (' ', str, a_nb_indent);
02005         g_string_append_printf (str, "%s", "NumPropVal {");
02006         tmp_str = cr_num_to_string (&a_prop_val->sv);
02007         if (!tmp_str) {
02008                 status = CR_ERROR;
02009                 goto cleanup;
02010         }
02011         g_string_append_printf (str, "sv: %s ", tmp_str);
02012         g_free (tmp_str);
02013         tmp_str = NULL;
02014         tmp_str = cr_num_to_string (&a_prop_val->cv);
02015         if (!tmp_str) {
02016                 status = CR_ERROR;
02017                 goto cleanup;
02018         }
02019         g_string_append_printf (str, "av: %s ", tmp_str);
02020         g_free (tmp_str);
02021         tmp_str = NULL;
02022         g_string_append_printf (str, "%s", "}");
02023         g_string_append_printf (a_str, "%s", str->str);
02024         status = CR_OK;
02025       cleanup:
02026 
02027         if (tmp_str) {
02028                 g_free (tmp_str);
02029                 tmp_str = NULL;
02030         }
02031         if (str) {
02032                 g_string_free (str, TRUE);
02033         }
02034         return status;
02035 }
02036 
02037 enum CRStatus
02038 cr_style_rgb_prop_val_to_string (CRRgbPropVal * a_prop_val,
02039                                  GString * a_str, guint a_nb_indent)
02040 {
02041         enum CRStatus status = CR_OK;
02042         guchar *tmp_str = NULL;
02043         GString *str = NULL;
02044 
02045         g_return_val_if_fail (a_prop_val && a_str, CR_BAD_PARAM_ERROR);
02046 
02047         str = g_string_new (NULL);
02048 
02049         cr_utils_dump_n_chars2 (' ', str, a_nb_indent);
02050         g_string_append_printf (str, "RGBPropVal {");
02051         tmp_str = cr_rgb_to_string (&a_prop_val->sv);
02052         if (!tmp_str) {
02053                 status = CR_ERROR;
02054                 goto cleanup;
02055         }
02056         g_string_append_printf (str, "sv: %s ", tmp_str);
02057         g_free (tmp_str);
02058         tmp_str = NULL;
02059         tmp_str = cr_rgb_to_string (&a_prop_val->cv);
02060         if (!tmp_str) {
02061                 status = CR_ERROR;
02062                 goto cleanup;
02063         }
02064         g_string_append_printf (str, "cv: %s ", tmp_str);
02065         g_free (tmp_str);
02066         tmp_str = NULL;
02067         tmp_str = cr_rgb_to_string (&a_prop_val->av);
02068         if (!tmp_str) {
02069                 status = CR_ERROR;
02070                 goto cleanup;
02071         }
02072         g_string_append_printf (str, "av: %s ", tmp_str);
02073         g_free (tmp_str);
02074         tmp_str = NULL;
02075 
02076         g_string_append_printf (str, "}");
02077         g_string_append_printf (a_str, "%s", str->str);
02078         status = CR_OK;
02079       cleanup:
02080 
02081         if (tmp_str) {
02082                 g_free (tmp_str);
02083                 tmp_str = NULL;
02084         }
02085         if (str) {
02086                 g_string_free (str, TRUE);
02087         }
02088         return status;
02089 }
02090 
02091 enum CRStatus
02092 cr_style_border_style_to_string (enum CRBorderStyle a_prop,
02093                                  GString * a_str, guint a_nb_indent)
02094 {
02095         gchar *str = NULL;
02096 
02097         g_return_val_if_fail (a_str, CR_BAD_PARAM_ERROR);
02098 
02099         switch (a_prop) {
02100         case BORDER_STYLE_NONE:
02101                 str = (gchar *) "border-style-none";
02102                 break;
02103         case BORDER_STYLE_HIDDEN:
02104                 str = (gchar *) "border-style-hidden";
02105                 break;
02106         case BORDER_STYLE_DOTTED:
02107                 str = (gchar *) "border-style-dotted";
02108                 break;
02109         case BORDER_STYLE_DASHED:
02110                 str = (gchar *) "border-style-dashed";
02111                 break;
02112         case BORDER_STYLE_SOLID:
02113                 str = (gchar *) "border-style-solid";
02114                 break;
02115         case BORDER_STYLE_DOUBLE:
02116                 str = (gchar *) "border-style-double";
02117                 break;
02118         case BORDER_STYLE_GROOVE:
02119                 str = (gchar *) "border-style-groove";
02120                 break;
02121         case BORDER_STYLE_RIDGE:
02122                 str = (gchar *) "border-style-ridge";
02123                 break;
02124         case BORDER_STYLE_INSET:
02125                 str = (gchar *) "border-style-inset";
02126                 break;
02127         case BORDER_STYLE_OUTSET:
02128                 str = (gchar *) "border-style-outset";
02129                 break;
02130         default:
02131                 str = (gchar *) "unknown border style";
02132                 break;
02133         }
02134         cr_utils_dump_n_chars2 (' ', a_str, a_nb_indent);
02135         g_string_append_printf (a_str, "%s", str);
02136         return CR_OK;
02137 }
02138 
02139 enum CRStatus
02140 cr_style_display_type_to_string (enum CRDisplayType a_code,
02141                                  GString * a_str, guint a_nb_indent)
02142 {
02143         gchar *str = NULL;
02144 
02145         g_return_val_if_fail (a_str, CR_BAD_PARAM_ERROR);
02146 
02147         switch (a_code) {
02148         case DISPLAY_NONE:
02149                 str = (gchar *) "display-none";
02150                 break;
02151         case DISPLAY_INLINE:
02152                 str = (gchar *) "display-inline";
02153                 break;
02154         case DISPLAY_BLOCK:
02155                 str = (gchar *) "display-block";
02156                 break;
02157         case DISPLAY_LIST_ITEM:
02158                 str = (gchar *) "display-list-item";
02159                 break;
02160         case DISPLAY_RUN_IN:
02161                 str = (gchar *) "display-run-in";
02162                 break;
02163         case DISPLAY_COMPACT:
02164                 str = (gchar *) "display-compact";
02165                 break;
02166         case DISPLAY_MARKER:
02167                 str = (gchar *) "display-marker";
02168                 break;
02169         case DISPLAY_TABLE:
02170                 str = (gchar *) "display-table";
02171                 break;
02172         case DISPLAY_INLINE_TABLE:
02173                 str = (gchar *) "display-inline-table";
02174                 break;
02175         case DISPLAY_TABLE_ROW_GROUP:
02176                 str = (gchar *) "display-table-row-group";
02177                 break;
02178         case DISPLAY_TABLE_HEADER_GROUP:
02179                 str = (gchar *) "display-table-header-group";
02180                 break;
02181         case DISPLAY_TABLE_FOOTER_GROUP:
02182                 str = (gchar *) "display-table-footer-group";
02183                 break;
02184         case DISPLAY_TABLE_ROW:
02185                 str = (gchar *) "display-table-row";
02186                 break;
02187         case DISPLAY_TABLE_COLUMN_GROUP:
02188                 str = (gchar *) "display-table-column-group";
02189                 break;
02190         case DISPLAY_TABLE_COLUMN:
02191                 str = (gchar *) "display-table-column";
02192                 break;
02193         case DISPLAY_TABLE_CELL:
02194                 str = (gchar *) "display-table-cell";
02195                 break;
02196         case DISPLAY_TABLE_CAPTION:
02197                 str = (gchar *) "display-table-caption";
02198                 break;
02199         case DISPLAY_INHERIT:
02200                 str = (gchar *) "display-inherit";
02201                 break;
02202         default:
02203                 str = (gchar *) "unknown display property";
02204                 break;
02205         }
02206         cr_utils_dump_n_chars2 (' ', a_str, a_nb_indent);
02207         g_string_append_printf (a_str, str);
02208         return CR_OK;
02209 
02210 }
02211 
02212 enum CRStatus
02213 cr_style_position_type_to_string (enum CRPositionType a_code,
02214                                   GString * a_str, guint a_nb_indent)
02215 {
02216         gchar *str = NULL;
02217 
02218         g_return_val_if_fail (a_str, CR_BAD_PARAM_ERROR);
02219 
02220         switch (a_code) {
02221         case POSITION_STATIC:
02222                 str = (gchar *) "position-static";
02223                 break;
02224         case POSITION_RELATIVE:
02225                 str = (gchar *) "position-relative";
02226                 break;
02227         case POSITION_ABSOLUTE:
02228                 str = (gchar *) "position-absolute";
02229                 break;
02230         case POSITION_FIXED:
02231                 str = (gchar *) "position-fixed";
02232                 break;
02233         case POSITION_INHERIT:
02234                 str = (gchar *) "position-inherit";
02235                 break;
02236         default:
02237                 str = (gchar *) "unknown static property";
02238         }
02239         cr_utils_dump_n_chars2 (' ', a_str, a_nb_indent);
02240         g_string_append_printf (a_str, "%s", str);
02241         return CR_OK;
02242 }
02243 
02244 enum CRStatus
02245 cr_style_float_type_to_string (enum CRFloatType a_code,
02246                                GString * a_str, guint a_nb_indent)
02247 {
02248         gchar *str = NULL;
02249 
02250         g_return_val_if_fail (a_str, CR_BAD_PARAM_ERROR);
02251 
02252         switch (a_code) {
02253         case FLOAT_NONE:
02254                 str = (gchar *) "float-none";
02255                 break;
02256         case FLOAT_LEFT:
02257                 str = (gchar *) "float-left";
02258                 break;
02259         case FLOAT_RIGHT:
02260                 str = (gchar *) "float-right";
02261                 break;
02262         case FLOAT_INHERIT:
02263                 str = (gchar *) "float-inherit";
02264                 break;
02265         default:
02266                 str = (gchar *) "unknown float property value";
02267                 break;
02268         }
02269         return CR_OK;
02270 }
02271 
02272 /**
02273  *Serializes in instance of #CRStyle into
02274  *a string
02275  *@param a_this the instance of #CRStyle to serialize
02276  *@param a_str the string to serialise the style into.
02277  *if *a_str is NULL, a new GString is instanciated, otherwise
02278  *the style serialisation is appended to the existed *a_str
02279  *@param the number of white space char to use for indentation.
02280  *@return CR_OK upon successful completion, an error code otherwise.
02281  */
02282 enum CRStatus
02283 cr_style_to_string (CRStyle * a_this, GString ** a_str, guint a_nb_indent)
02284 {
02285         const gint INTERNAL_INDENT = 2;
02286         gint indent = a_nb_indent + INTERNAL_INDENT;
02287         gchar *tmp_str = NULL;
02288         GString *str = NULL;
02289         gint i = 0;
02290 
02291         g_return_val_if_fail (a_this && a_str, CR_BAD_PARAM_ERROR);
02292 
02293         if (!*a_str) {
02294                 str = g_string_new (NULL);
02295         } else {
02296                 str = *a_str;
02297         }
02298         cr_utils_dump_n_chars2 (' ', str, a_nb_indent);
02299         g_string_append_printf (str, "style {\n");
02300 
02301         /*loop over the num_props and to_string() them */
02302         for (i = NUM_PROP_TOP; i < NB_NUM_PROPS; i++) {
02303                 /*
02304                  *to_string() the name of the num_prop
02305                  *(using num_prop_code_to_string)
02306                  *before outputing it value
02307                  */
02308                 cr_utils_dump_n_chars2 (' ', str, indent);
02309                 tmp_str = (gchar *) num_prop_code_to_string (i);
02310                 if (tmp_str) {
02311                         g_string_append_printf (str, "%s: ", tmp_str);
02312                 } else {
02313                         g_string_append_printf (str, "%s", "NULL");
02314                 }
02315                 tmp_str = NULL;
02316                 cr_style_num_prop_val_to_string (&a_this->num_props[i], str,
02317                                                  a_nb_indent +
02318                                                  INTERNAL_INDENT);
02319                 g_string_append_printf (str, "\n");
02320         }
02321         /*loop over the rgb_props and to_string() them all */
02322         for (i = RGB_PROP_BORDER_TOP_COLOR; i < NB_RGB_PROPS; i++) {
02323                 tmp_str = (gchar *) rgb_prop_code_to_string (i);
02324                 cr_utils_dump_n_chars2 (' ', str, indent);
02325                 if (tmp_str) {
02326                         g_string_append_printf (str, "%s: ", tmp_str);
02327                 } else {
02328                         g_string_append_printf (str, "%s", "NULL: ");
02329                 }
02330                 tmp_str = NULL;
02331                 cr_style_rgb_prop_val_to_string (&a_this->rgb_props[i], str,
02332                                                  a_nb_indent +
02333                                                  INTERNAL_INDENT);
02334                 g_string_append_printf (str, "\n");
02335         }
02336         /*loop over the border_style_props and to_string() them */
02337         for (i = BORDER_STYLE_PROP_TOP; i < NB_BORDER_STYLE_PROPS; i++) {
02338                 tmp_str = (gchar *) border_style_prop_code_to_string (i);
02339                 cr_utils_dump_n_chars2 (' ', str, indent);
02340                 if (tmp_str) {
02341                         g_string_append_printf (str, "%s: ", tmp_str);
02342                 } else {
02343                         g_string_append_printf (str, "NULL: ");
02344                 }
02345                 tmp_str = NULL;
02346                 cr_style_border_style_to_string (a_this->
02347                                                  border_style_props[i], str,
02348                                                  0);
02349                 g_string_append_printf (str, "\n");
02350         }
02351         cr_utils_dump_n_chars2 (' ', str, indent);
02352         g_string_append_printf (str, "display: ");
02353         cr_style_display_type_to_string (a_this->display, str, 0);
02354         g_string_append_printf (str, "\n");
02355 
02356         cr_utils_dump_n_chars2 (' ', str, indent);
02357         g_string_append_printf (str, "position: ");
02358         cr_style_position_type_to_string (a_this->position, str, 0);
02359         g_string_append_printf (str, "\n");
02360 
02361         cr_utils_dump_n_chars2 (' ', str, indent);
02362         g_string_append_printf (str, "float-type: ");
02363         cr_style_float_type_to_string (a_this->float_type, str, 0);
02364         g_string_append_printf (str, "\n");
02365 
02366         cr_utils_dump_n_chars2 (' ', str, indent);
02367         g_string_append_printf (str, "font-family: ");
02368         tmp_str = cr_font_family_to_string (a_this->font_family, TRUE);
02369         if (tmp_str) {
02370                 g_string_append_printf (str, "%s", tmp_str);
02371                 g_free (tmp_str);
02372                 tmp_str = NULL;
02373         } else {
02374                 g_string_append_printf (str, "NULL");
02375         }
02376         g_string_append_printf (str, "\n");
02377 
02378         cr_utils_dump_n_chars2 (' ', str, indent);
02379         tmp_str = cr_font_size_to_string (a_this->font_size);
02380         if (tmp_str) {
02381                 g_string_append_printf (str, "font-size: %s", tmp_str);
02382         } else {
02383                 g_string_append_printf (str, "font-size: NULL");
02384         }
02385         tmp_str = NULL;
02386         g_string_append_printf (str, "\n");
02387 
02388         cr_utils_dump_n_chars2 (' ', str, indent);
02389         tmp_str = cr_font_size_adjust_to_string (a_this->font_size_adjust);
02390         if (tmp_str) {
02391                 g_string_append_printf (str, "font-size-adjust: %s", tmp_str);
02392         } else {
02393                 g_string_append_printf (str, "font-size-adjust: NULL");
02394         }
02395         tmp_str = NULL;
02396         g_string_append_printf (str, "\n");
02397 
02398         cr_utils_dump_n_chars2 (' ', str, indent);
02399         tmp_str = (gchar *) cr_font_style_to_string (a_this->font_style);
02400         if (tmp_str) {
02401                 g_string_append_printf (str, "font-size: %s", tmp_str);
02402         } else {
02403                 g_string_append_printf (str, "font-size: NULL");
02404         }
02405         tmp_str = NULL;
02406         g_string_append_printf (str, "\n");
02407 
02408         cr_utils_dump_n_chars2 (' ', str, indent);
02409         tmp_str = (gchar *) cr_font_variant_to_string (a_this->font_variant);
02410         if (tmp_str) {
02411                 g_string_append_printf (str, "font-variant: %s", tmp_str);
02412         } else {
02413                 g_string_append_printf (str, "font-variant: NULL");
02414         }
02415         tmp_str = NULL;
02416         g_string_append_printf (str, "\n");
02417 
02418         cr_utils_dump_n_chars2 (' ', str, indent);
02419         tmp_str = (gchar *) cr_font_weight_to_string (a_this->font_weight);
02420         if (tmp_str) {
02421                 g_string_append_printf (str, "font-weight: %s", tmp_str);
02422         } else {
02423                 g_string_append_printf (str, "font-weight: NULL");
02424         }
02425         tmp_str = NULL;
02426         g_string_append_printf (str, "\n");
02427 
02428         cr_utils_dump_n_chars2 (' ', str, indent);
02429         tmp_str = (gchar *) cr_font_stretch_to_string (a_this->font_stretch);
02430         if (tmp_str) {
02431                 g_string_append_printf (str, "font-stretch: %s", tmp_str);
02432         } else {
02433                 g_string_append_printf (str, "font-stretch: NULL");
02434         }
02435         tmp_str = NULL;
02436         g_string_append_printf (str, "\n");
02437 
02438         cr_utils_dump_n_chars2 (' ', str, a_nb_indent);
02439         g_string_append_printf (str, "}");
02440 
02441         return CR_OK;
02442 }
02443 
02444 /**
02445  *Destructor of the #CRStyle class.
02446  *@param a_this the instance to destroy.
02447  */
02448 void
02449 cr_style_destroy (CRStyle * a_this)
02450 {
02451         g_return_if_fail (a_this);
02452 
02453         g_free (a_this);
02454 }

Generated on Sat Mar 20 02:38:44 2004 for Libcroco by doxygen 1.3.5