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