1 /* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */
3 /*
4 * This file is part of The Croco Library
5 *
6 * Copyright (C) 2002-2003 Dodji Seketeli <dodji@seketeli.org>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of version 2.1 of the
10 * GNU Lesser General Public
11 * License as published by the Free Software Foundation.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the
19 * GNU Lesser General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
22 * USA
23 */
25 /*
26 *$Id: cr-cascade.c,v 1.6 2004/03/07 13:22:47 dodji Exp $
27 */
29 #include <string.h>
30 #include "cr-cascade.h"
32 #define PRIVATE(a_this) ((a_this)->priv)
34 struct _CRCascadePriv {
35 /**
36 *the 3 style sheets of the cascade:
37 *author, user, and useragent sheet.
38 *Intended to be addressed by
39 *sheets[ORIGIN_AUTHOR] or sheets[ORIGIN_USER]
40 *of sheets[ORIGIN_UA] ;
41 */
42 CRStyleSheet *sheets[3];
43 guint ref_count;
44 };
46 /**
47 *Constructor of the #CRCascade class.
48 *Note that all three parameters of this
49 *method are ref counted and their refcount is increased.
50 *Their refcount will be decreased at the destruction of
51 *the instance of #CRCascade.
52 *So the caller should not call their destructor. The caller
53 *should call their ref/unref method instead if it wants
54 *@param a_author_sheet the autor origin style sheet
55 *@param a_user_sheet the user origin style sheet.
56 *@param a_ua_sheet the user agent origin style sheet.
57 *@return the newly built instance of CRCascade or NULL if
58 *an error arose during constrution.
59 */
60 CRCascade *
61 cr_cascade_new (CRStyleSheet * a_author_sheet,
62 CRStyleSheet * a_user_sheet, CRStyleSheet * a_ua_sheet)
63 {
64 CRCascade *result = (CRCascade *)g_try_malloc (sizeof (CRCascade));
65 if (!result) {
66 cr_utils_trace_info ("Out of memory");
67 return NULL;
68 }
69 memset (result, 0, sizeof (CRCascade));
71 PRIVATE (result) = (CRCascadePriv *)g_try_malloc (sizeof (CRCascadePriv));
72 if (!PRIVATE (result)) {
73 cr_utils_trace_info ("Out of memory");
74 return NULL;
75 }
76 memset (PRIVATE (result), 0, sizeof (CRCascadePriv));
78 if (a_author_sheet) {
79 cr_cascade_set_sheet (result, a_author_sheet, ORIGIN_AUTHOR);
80 }
81 if (a_user_sheet) {
82 cr_cascade_set_sheet (result, a_user_sheet, ORIGIN_USER);
83 }
84 if (a_ua_sheet) {
85 cr_cascade_set_sheet (result, a_ua_sheet, ORIGIN_UA);
86 }
88 return result;
89 }
91 /**
92 *Gets a given origin sheet.
93 *Note that the returned stylesheet
94 *is refcounted so if the caller wants
95 *to manage its lifecycle, it must use
96 *cr_stylesheet_ref()/cr_stylesheet_unref() instead
97 *of the cr_stylesheet_destroy() method.
98 *@param a_this the current instance of #CRCascade.
99 *@param a_origin the origin of the style sheet as
100 *defined in the css2 spec in chapter 6.4.
101 *@return the style sheet, or NULL if it does not
102 *exist.
103 */
104 CRStyleSheet *
105 cr_cascade_get_sheet (CRCascade * a_this, enum CRStyleOrigin a_origin)
106 {
107 g_return_val_if_fail (a_this
108 && (unsigned)a_origin < NB_ORIGINS, NULL);
110 return PRIVATE (a_this)->sheets[a_origin];
111 }
113 /**
114 *Sets a stylesheet in the cascade
115 *@param a_this the current instance of #CRCascade.
116 *@param a_sheet the stylesheet to set.
117 *@param a_origin the origin of the stylesheet.
118 *@return CR_OK upon successfull completion, an error
119 *code otherwise.
120 */
121 enum CRStatus
122 cr_cascade_set_sheet (CRCascade * a_this,
123 CRStyleSheet * a_sheet, enum CRStyleOrigin a_origin)
124 {
125 g_return_val_if_fail (a_this
126 && a_sheet
127 && (unsigned)a_origin < NB_ORIGINS, CR_BAD_PARAM_ERROR);
129 if (PRIVATE (a_this)->sheets[a_origin])
130 cr_stylesheet_unref (PRIVATE (a_this)->sheets[a_origin]);
131 PRIVATE (a_this)->sheets[a_origin] = a_sheet;
132 cr_stylesheet_ref (a_sheet);
133 a_sheet->origin = a_origin;
134 return CR_OK;
135 }
137 /**
138 *Increases the reference counter of the current instance
139 *of #CRCascade.
140 *@param a_this the current instance of #CRCascade
141 *
142 */
143 void
144 cr_cascade_ref (CRCascade * a_this)
145 {
146 g_return_if_fail (a_this && PRIVATE (a_this));
148 PRIVATE (a_this)->ref_count++;
149 }
151 /**
152 *Decrements the reference counter associated
153 *to this instance of #CRCascade. If the reference
154 *counter reaches zero, the instance is destroyed
155 *using cr_cascade_destroy()
156 *@param a_this the current instance of
157 *#CRCascade.
158 */
159 void
160 cr_cascade_unref (CRCascade * a_this)
161 {
162 g_return_if_fail (a_this && PRIVATE (a_this));
164 if (PRIVATE (a_this)->ref_count)
165 PRIVATE (a_this)->ref_count--;
166 if (!PRIVATE (a_this)->ref_count) {
167 cr_cascade_destroy (a_this);
168 }
169 }
171 /**
172 *Destructor of #CRCascade.
173 */
174 void
175 cr_cascade_destroy (CRCascade * a_this)
176 {
177 g_return_if_fail (a_this);
179 if (PRIVATE (a_this)) {
180 gulong i = 0;
182 for (i = 0; PRIVATE (a_this)->sheets && i < NB_ORIGINS; i++) {
183 if (PRIVATE (a_this)->sheets[i]) {
184 if (cr_stylesheet_unref
185 (PRIVATE (a_this)->sheets[i])
186 == TRUE) {
187 PRIVATE (a_this)->sheets[i] = NULL;
188 }
189 }
190 }
191 g_free (PRIVATE (a_this));
192 PRIVATE (a_this) = NULL;
193 }
194 g_free (a_this);
195 }