• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 *
cr_cascade_new(CRStyleSheet * a_author_sheet,CRStyleSheet * a_user_sheet,CRStyleSheet * a_ua_sheet)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 *
cr_cascade_get_sheet(CRCascade * a_this,enum CRStyleOrigin a_origin)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
cr_cascade_set_sheet(CRCascade * a_this,CRStyleSheet * a_sheet,enum CRStyleOrigin a_origin)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
cr_cascade_ref(CRCascade * a_this)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
cr_cascade_unref(CRCascade * a_this)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
cr_cascade_destroy(CRCascade * a_this)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 }
226