(root)/
gettext-0.22.4/
libtextstyle/
lib/
libcroco/
cr-cascade.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) 2002-2003 Dodji Seketeli <dodji@seketeli.org>
      16   *
      17   * This program is free software; you can redistribute it and/or
      18   * modify it under the terms of version 2.1 of the 
      19   * 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  
      34  /*
      35   *$Id$
      36   */
      37  
      38  #include <config.h>
      39  #include <string.h>
      40  #include "cr-cascade.h"
      41  
      42  #define PRIVATE(a_this) ((a_this)->priv)
      43  
      44  struct _CRCascadePriv {
      45   /**
      46  	 *the 3 style sheets of the cascade:
      47  	 *author, user, and useragent sheet.
      48  	 *Intended to be addressed by
      49  	 *sheets[ORIGIN_AUTHOR] or sheets[ORIGIN_USER]
      50  	 *of sheets[ORIGIN_UA] ;
      51  	 */
      52          CRStyleSheet *sheets[3];
      53          guint ref_count;
      54  };
      55  
      56  /**
      57   * cr_cascade_new:
      58   *@a_author_sheet: the author origin style sheet.  May be NULL.
      59   *@a_user_sheet: the user origin style sheet.  May be NULL.
      60   *@a_ua_sheet: the user agent origin style sheet.  May be NULL.
      61   *
      62   *Constructor of the #CRCascade class.
      63   *Note that all three parameters of this
      64   *method are ref counted and their refcount is increased.
      65   *Their refcount will be decreased at the destruction of
      66   *the instance of #CRCascade.
      67   *So the caller should not call their destructor. The caller
      68   *should call their ref/unref method instead if it wants
      69   *
      70   *Returns the newly built instance of CRCascade or NULL if
      71   *an error arose during constrution.
      72   */
      73  CRCascade *
      74  cr_cascade_new (CRStyleSheet * a_author_sheet,
      75                  CRStyleSheet * a_user_sheet, CRStyleSheet * a_ua_sheet)
      76  {
      77          CRCascade *result = NULL;
      78  
      79          result = g_try_malloc (sizeof (CRCascade));
      80          if (!result) {
      81                  cr_utils_trace_info ("Out of memory");
      82                  return NULL;
      83          }
      84          memset (result, 0, sizeof (CRCascade));
      85  
      86          PRIVATE (result) = g_try_malloc (sizeof (CRCascadePriv));
      87          if (!PRIVATE (result)) {
      88                  cr_utils_trace_info ("Out of memory");
      89                  g_free (result);
      90                  return NULL;
      91          }
      92          memset (PRIVATE (result), 0, sizeof (CRCascadePriv));
      93  
      94          if (a_author_sheet) {
      95                  cr_cascade_set_sheet (result, a_author_sheet, ORIGIN_AUTHOR);
      96          }
      97          if (a_user_sheet) {
      98                  cr_cascade_set_sheet (result, a_user_sheet, ORIGIN_USER);
      99          }
     100          if (a_ua_sheet) {
     101                  cr_cascade_set_sheet (result, a_ua_sheet, ORIGIN_UA);
     102          }
     103  
     104          return result;
     105  }
     106  
     107  /**
     108   * cr_cascade_get_sheet:
     109   *@a_this: the current instance of #CRCascade.
     110   *@a_origin: the origin of the style sheet as
     111   *defined in the css2 spec in chapter 6.4.
     112   *Gets a given origin sheet.
     113   *
     114   *Gets a sheet, part of the cascade.
     115   *Note that the returned stylesheet
     116   *is refcounted so if the caller wants
     117   *to manage it's lifecycle, it must use
     118   *cr_stylesheet_ref()/cr_stylesheet_unref() instead
     119   *of the cr_stylesheet_destroy() method.
     120   *Returns the style sheet, or NULL if it does not
     121   *exist.
     122   */
     123  CRStyleSheet *
     124  cr_cascade_get_sheet (CRCascade * a_this, enum CRStyleOrigin a_origin)
     125  {
     126          g_return_val_if_fail (a_this
     127                                && a_origin >= ORIGIN_UA
     128                                && a_origin < NB_ORIGINS, NULL);
     129  
     130          return PRIVATE (a_this)->sheets[a_origin];
     131  }
     132  
     133  /**
     134   * cr_cascade_set_sheet:
     135   *@a_this: the current instance of #CRCascade.
     136   *@a_sheet: the stylesheet to set.
     137   *@a_origin: the origin of the stylesheet.
     138   *
     139   *Sets a stylesheet in the cascade
     140   *
     141   *Returns CR_OK upon successfull completion, an error
     142   *code otherwise.
     143   */
     144  enum CRStatus
     145  cr_cascade_set_sheet (CRCascade * a_this,
     146                        CRStyleSheet * a_sheet, enum CRStyleOrigin a_origin)
     147  {
     148          g_return_val_if_fail (a_this
     149                                && a_sheet
     150                                && a_origin >= ORIGIN_UA
     151                                && a_origin < NB_ORIGINS, CR_BAD_PARAM_ERROR);
     152  
     153          if (PRIVATE (a_this)->sheets[a_origin])
     154                  cr_stylesheet_unref (PRIVATE (a_this)->sheets[a_origin]);
     155          PRIVATE (a_this)->sheets[a_origin] = a_sheet;
     156          cr_stylesheet_ref (a_sheet);
     157          a_sheet->origin = a_origin;
     158          return CR_OK;
     159  }
     160  
     161  /**
     162   *cr_cascade_ref:
     163   *@a_this: the current instance of #CRCascade
     164   *
     165   *Increases the reference counter of the current instance
     166   *of #CRCascade.
     167   */
     168  void
     169  cr_cascade_ref (CRCascade * a_this)
     170  {
     171          g_return_if_fail (a_this && PRIVATE (a_this));
     172  
     173          PRIVATE (a_this)->ref_count++;
     174  }
     175  
     176  /**
     177   * cr_cascade_unref:
     178   *@a_this: the current instance of 
     179   *#CRCascade.
     180   *
     181   *Decrements the reference counter associated
     182   *to this instance of #CRCascade. If the reference
     183   *counter reaches zero, the instance is destroyed 
     184   *using cr_cascade_destroy()
     185   */
     186  void
     187  cr_cascade_unref (CRCascade * a_this)
     188  {
     189          g_return_if_fail (a_this && PRIVATE (a_this));
     190  
     191          if (PRIVATE (a_this)->ref_count)
     192                  PRIVATE (a_this)->ref_count--;
     193          if (!PRIVATE (a_this)->ref_count) {
     194                  cr_cascade_destroy (a_this);
     195          }
     196  }
     197  
     198  /**
     199   * cr_cascade_destroy:
     200   * @a_this: the current instance of #CRCascade
     201   *
     202   * Destructor of #CRCascade.
     203   */
     204  void
     205  cr_cascade_destroy (CRCascade * a_this)
     206  {
     207          g_return_if_fail (a_this);
     208  
     209          if (PRIVATE (a_this)) {
     210                  gulong i = 0;
     211  
     212                  for (i = 0; PRIVATE (a_this)->sheets && i < NB_ORIGINS; i++) {
     213                          if (PRIVATE (a_this)->sheets[i]) {
     214                                  if (cr_stylesheet_unref
     215                                      (PRIVATE (a_this)->sheets[i])
     216                                      == TRUE) {
     217                                          PRIVATE (a_this)->sheets[i] = NULL;
     218                                  }
     219                          }
     220                  }
     221                  g_free (PRIVATE (a_this));
     222                  PRIVATE (a_this) = NULL;
     223          }
     224          g_free (a_this);
     225  }