Libcroco
cr-cascade.c
Go to the documentation of this file.
00001 /* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */
00002 
00003 /*
00004  * This file is part of The Croco Library
00005  *
00006  * Copyright (C) 2002-2003 Dodji Seketeli <dodji@seketeli.org>
00007  *
00008  * This program is free software; you can redistribute it and/or
00009  * modify it under the terms of version 2.1 of the 
00010  * GNU Lesser General Public
00011  * License as published by the Free Software Foundation.
00012  *
00013  * This program is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  * GNU General Public License for more details.
00017  *
00018  * You should have received a copy of the 
00019  * GNU Lesser General Public License
00020  * along with this program; if not, write to the Free Software
00021  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
00022  * USA
00023  */
00024 
00025 /*
00026  *$Id$
00027  */
00028 
00029 #include <string.h>
00030 #include "cr-cascade.h"
00031 
00032 #define PRIVATE(a_this) ((a_this)->priv)
00033 
00034 struct _CRCascadePriv {
00035  /**
00036          *the 3 style sheets of the cascade:
00037          *author, user, and useragent sheet.
00038          *Intended to be addressed by
00039          *sheets[ORIGIN_AUTHOR] or sheets[ORIGIN_USER]
00040          *of sheets[ORIGIN_UA] ;
00041          */
00042         CRStyleSheet *sheets[3];
00043         guint ref_count;
00044 };
00045 
00046 /**
00047  * cr_cascade_new:
00048  *@a_author_sheet: the author origin style sheet.  May be NULL.
00049  *@a_user_sheet: the user origin style sheet.  May be NULL.
00050  *@a_ua_sheet: the user agent origin style sheet.  May be NULL.
00051  *
00052  *Constructor of the #CRCascade class.
00053  *Note that all three parameters of this
00054  *method are ref counted and their refcount is increased.
00055  *Their refcount will be decreased at the destruction of
00056  *the instance of #CRCascade.
00057  *So the caller should not call their destructor. The caller
00058  *should call their ref/unref method instead if it wants
00059  *
00060  *Returns the newly built instance of CRCascade or NULL if
00061  *an error arose during constrution.
00062  */
00063 CRCascade *
00064 cr_cascade_new (CRStyleSheet * a_author_sheet,
00065                 CRStyleSheet * a_user_sheet, CRStyleSheet * a_ua_sheet)
00066 {
00067         CRCascade *result = NULL;
00068 
00069         result = g_try_malloc (sizeof (CRCascade));
00070         if (!result) {
00071                 cr_utils_trace_info ("Out of memory");
00072                 return NULL;
00073         }
00074         memset (result, 0, sizeof (CRCascade));
00075 
00076         PRIVATE (result) = g_try_malloc (sizeof (CRCascadePriv));
00077         if (!PRIVATE (result)) {
00078                 cr_utils_trace_info ("Out of memory");
00079                 g_free (result);
00080                 return NULL;
00081         }
00082         memset (PRIVATE (result), 0, sizeof (CRCascadePriv));
00083 
00084         if (a_author_sheet) {
00085                 cr_cascade_set_sheet (result, a_author_sheet, ORIGIN_AUTHOR);
00086         }
00087         if (a_user_sheet) {
00088                 cr_cascade_set_sheet (result, a_user_sheet, ORIGIN_USER);
00089         }
00090         if (a_ua_sheet) {
00091                 cr_cascade_set_sheet (result, a_ua_sheet, ORIGIN_UA);
00092         }
00093 
00094         return result;
00095 }
00096 
00097 /**
00098  * cr_cascade_get_sheet:
00099  *@a_this: the current instance of #CRCascade.
00100  *@a_origin: the origin of the style sheet as
00101  *defined in the css2 spec in chapter 6.4.
00102  *Gets a given origin sheet.
00103  *
00104  *Gets a sheet, part of the cascade.
00105  *Note that the returned stylesheet
00106  *is refcounted so if the caller wants
00107  *to manage it's lifecycle, it must use
00108  *cr_stylesheet_ref()/cr_stylesheet_unref() instead
00109  *of the cr_stylesheet_destroy() method.
00110  *Returns the style sheet, or NULL if it does not
00111  *exist.
00112  */
00113 CRStyleSheet *
00114 cr_cascade_get_sheet (CRCascade * a_this, enum CRStyleOrigin a_origin)
00115 {
00116         g_return_val_if_fail (a_this
00117                               && a_origin >= ORIGIN_UA
00118                               && a_origin < NB_ORIGINS, NULL);
00119 
00120         return PRIVATE (a_this)->sheets[a_origin];
00121 }
00122 
00123 /**
00124  * cr_cascade_set_sheet:
00125  *@a_this: the current instance of #CRCascade.
00126  *@a_sheet: the stylesheet to set.
00127  *@a_origin: the origin of the stylesheet.
00128  *
00129  *Sets a stylesheet in the cascade
00130  *
00131  *Returns CR_OK upon successfull completion, an error
00132  *code otherwise.
00133  */
00134 enum CRStatus
00135 cr_cascade_set_sheet (CRCascade * a_this,
00136                       CRStyleSheet * a_sheet, enum CRStyleOrigin a_origin)
00137 {
00138         g_return_val_if_fail (a_this
00139                               && a_sheet
00140                               && a_origin >= ORIGIN_UA
00141                               && a_origin < NB_ORIGINS, CR_BAD_PARAM_ERROR);
00142 
00143         if (PRIVATE (a_this)->sheets[a_origin])
00144                 cr_stylesheet_unref (PRIVATE (a_this)->sheets[a_origin]);
00145         PRIVATE (a_this)->sheets[a_origin] = a_sheet;
00146         cr_stylesheet_ref (a_sheet);
00147         a_sheet->origin = a_origin;
00148         return CR_OK;
00149 }
00150 
00151 /**
00152  *cr_cascade_ref:
00153  *@a_this: the current instance of #CRCascade
00154  *
00155  *Increases the reference counter of the current instance
00156  *of #CRCascade.
00157  */
00158 void
00159 cr_cascade_ref (CRCascade * a_this)
00160 {
00161         g_return_if_fail (a_this && PRIVATE (a_this));
00162 
00163         PRIVATE (a_this)->ref_count++;
00164 }
00165 
00166 /**
00167  * cr_cascade_unref:
00168  *@a_this: the current instance of 
00169  *#CRCascade.
00170  *
00171  *Decrements the reference counter associated
00172  *to this instance of #CRCascade. If the reference
00173  *counter reaches zero, the instance is destroyed 
00174  *using cr_cascade_destroy()
00175  */
00176 void
00177 cr_cascade_unref (CRCascade * a_this)
00178 {
00179         g_return_if_fail (a_this && PRIVATE (a_this));
00180 
00181         if (PRIVATE (a_this)->ref_count)
00182                 PRIVATE (a_this)->ref_count--;
00183         if (!PRIVATE (a_this)->ref_count) {
00184                 cr_cascade_destroy (a_this);
00185         }
00186 }
00187 
00188 /**
00189  * cr_cascade_destroy:
00190  * @a_this: the current instance of #CRCascade
00191  *
00192  * Destructor of #CRCascade.
00193  */
00194 void
00195 cr_cascade_destroy (CRCascade * a_this)
00196 {
00197         g_return_if_fail (a_this);
00198 
00199         if (PRIVATE (a_this)) {
00200                 gulong i = 0;
00201 
00202                 for (i = 0; PRIVATE (a_this)->sheets && i < NB_ORIGINS; i++) {
00203                         if (PRIVATE (a_this)->sheets[i]) {
00204                                 if (cr_stylesheet_unref
00205                                     (PRIVATE (a_this)->sheets[i])
00206                                     == TRUE) {
00207                                         PRIVATE (a_this)->sheets[i] = NULL;
00208                                 }
00209                         }
00210                 }
00211                 g_free (PRIVATE (a_this));
00212                 PRIVATE (a_this) = NULL;
00213         }
00214         g_free (a_this);
00215 }