Libcroco
cr-simple-sel.c
Go to the documentation of this file.
1 /* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */
2 
3 /*
4  * This file is part of The Croco Library
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of version 2.1 of the GNU Lesser General Public
8  * License as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
18  * USA
19  *
20  * Author: Dodji Seketeli
21  * See COPYRIGHTS file for copyright information.
22  */
23 
24 #include <string.h>
25 #include <glib.h>
26 #include "cr-simple-sel.h"
27 
28 /**
29  * cr_simple_sel_new:
30  *
31  *The constructor of #CRSimpleSel.
32  *
33  *Returns the new instance of #CRSimpleSel.
34  */
37 {
38  CRSimpleSel *result = NULL;
39 
40  result = g_try_malloc (sizeof (CRSimpleSel));
41  if (!result) {
42  cr_utils_trace_info ("Out of memory");
43  return NULL;
44  }
45  memset (result, 0, sizeof (CRSimpleSel));
46 
47  return result;
48 }
49 
50 /**
51  * cr_simple_sel_append_simple_sel:
52  *
53  *Appends a simpe selector to the current list of simple selector.
54  *
55  *@a_this: the this pointer of the current instance of #CRSimpleSel.
56  *@a_sel: the simple selector to append.
57  *
58  *Returns: the new list upon successfull completion, an error code otherwise.
59  */
62 {
63  CRSimpleSel *cur = NULL;
64 
65  g_return_val_if_fail (a_sel, NULL);
66 
67  if (a_this == NULL)
68  return a_sel;
69 
70  for (cur = a_this; cur->next; cur = cur->next) ;
71 
72  cur->next = a_sel;
73  a_sel->prev = cur;
74 
75  return a_this;
76 }
77 
78 /**
79  * cr_simple_sel_prepend_simple_sel:
80  *
81  *@a_this: the this pointer of the current instance of #CRSimpleSel.
82  *@a_sel: the simple selector to prepend.
83  *
84  *Prepends a simple selector to the current list of simple selectors.
85  *
86  *Returns the new list upon successfull completion, an error code otherwise.
87  */
90 {
91  g_return_val_if_fail (a_sel, NULL);
92 
93  if (a_this == NULL)
94  return a_sel;
95 
96  a_sel->next = a_this;
97  a_this->prev = a_sel;
98 
99  return a_sel;
100 }
101 
102 guchar *
104 {
105  GString *str_buf = NULL;
106  guchar *result = NULL;
107 
108  CRSimpleSel const *cur = NULL;
109 
110  g_return_val_if_fail (a_this, NULL);
111 
112  str_buf = g_string_new (NULL);
113  for (cur = a_this; cur; cur = cur->next) {
114  if (cur->name) {
115  guchar *str = (guchar *) g_strndup (cur->name->stryng->str,
116  cur->name->stryng->len);
117 
118  if (str) {
119  switch (cur->combinator) {
120  case COMB_WS:
121  g_string_append (str_buf, " ");
122  break;
123 
124  case COMB_PLUS:
125  g_string_append (str_buf, "+");
126  break;
127 
128  case COMB_GT:
129  g_string_append (str_buf, ">");
130  break;
131 
132  default:
133  break;
134  }
135 
136  g_string_append (str_buf, (const gchar *) str);
137  g_free (str);
138  str = NULL;
139  }
140  }
141 
142  if (cur->add_sel) {
143  guchar *tmp_str = NULL;
144 
145  tmp_str = cr_additional_sel_to_string (cur->add_sel);
146  if (tmp_str) {
147  g_string_append (str_buf, (const gchar *) tmp_str);
148  g_free (tmp_str);
149  tmp_str = NULL;
150  }
151  }
152  }
153 
154  if (str_buf) {
155  result = (guchar *) str_buf->str;
156  g_string_free (str_buf, FALSE);
157  str_buf = NULL;
158  }
159 
160  return result;
161 }
162 
163 
164 guchar *
166 {
167  GString *str_buf = NULL;
168  guchar *result = NULL;
169 
170  g_return_val_if_fail (a_this, NULL);
171 
172  str_buf = g_string_new (NULL);
173  if (a_this->name) {
174  guchar *str = (guchar *) g_strndup (a_this->name->stryng->str,
175  a_this->name->stryng->len);
176 
177  if (str) {
178  g_string_append_printf (str_buf, "%s", str);
179  g_free (str);
180  str = NULL;
181  }
182  }
183 
184  if (a_this->add_sel) {
185  guchar *tmp_str = NULL;
186 
187  tmp_str = cr_additional_sel_to_string (a_this->add_sel);
188  if (tmp_str) {
189  g_string_append_printf
190  (str_buf, "%s", tmp_str);
191  g_free (tmp_str);
192  tmp_str = NULL;
193  }
194  }
195 
196  if (str_buf) {
197  result = (guchar *) str_buf->str;
198  g_string_free (str_buf, FALSE);
199  str_buf = NULL;
200  }
201 
202  return result;
203 }
204 
205 /**
206  * cr_simple_sel_dump:
207  *@a_this: the current instance of #CRSimpleSel.
208  *@a_fp: the destination file pointer.
209  *
210  *Dumps the selector to a file.
211  *TODO: add the support of unicode in the dump.
212  *
213  *Returns CR_OK upon successfull completion, an error code
214  *otherwise.
215  */
216 enum CRStatus
217 cr_simple_sel_dump (CRSimpleSel const * a_this, FILE * a_fp)
218 {
219  guchar *tmp_str = NULL;
220 
221  g_return_val_if_fail (a_fp, CR_BAD_PARAM_ERROR);
222 
223  if (a_this) {
224  tmp_str = cr_simple_sel_to_string (a_this);
225  if (tmp_str) {
226  fprintf (a_fp, "%s", tmp_str);
227  g_free (tmp_str);
228  tmp_str = NULL;
229  }
230  }
231 
232  return CR_OK;
233 }
234 
235 /**
236  * cr_simple_sel_compute_specificity:
237  *
238  *@a_this: the current instance of #CRSimpleSel
239  *
240  *Computes the selector (combinator separated list of simple selectors)
241  *as defined in the css2 spec in chapter 6.4.3
242  *
243  *Returns CR_OK upon successfull completion, an error code otherwise.
244  */
245 enum CRStatus
247 {
248  CRAdditionalSel const *cur_add_sel = NULL;
249  CRSimpleSel const *cur_sel = NULL;
250  gulong a = 0,
251  b = 0,
252  c = 0;
253 
254  g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
255 
256  for (cur_sel = a_this; cur_sel; cur_sel = cur_sel->next) {
257  if (cur_sel->type_mask & TYPE_SELECTOR) {
258  c++; /*hmmh, is this a new language ? */
259  } else if (!cur_sel->name
260  || !cur_sel->name->stryng
261  || !cur_sel->name->stryng->str) {
262  if (cur_sel->add_sel->type ==
264  /*
265  *this is a pseudo element, and
266  *the spec says, "ignore pseudo elements".
267  */
268  continue;
269  }
270  }
271 
272  for (cur_add_sel = cur_sel->add_sel;
273  cur_add_sel; cur_add_sel = cur_add_sel->next) {
274  switch (cur_add_sel->type) {
275  case ID_ADD_SELECTOR:
276  a++;
277  break;
278 
279  case NO_ADD_SELECTOR:
280  continue;
281 
282  default:
283  b++;
284  break;
285  }
286  }
287  }
288 
289  /*we suppose a, b and c have 1 to 3 digits */
290  a_this->specificity = a * 1000000 + b * 1000 + c;
291 
292  return CR_OK;
293 }
294 
295 /**
296  * cr_simple_sel_destroy:
297  *
298  *@a_this: the this pointer of the current instance of #CRSimpleSel.
299  *
300  *The destructor of the current instance of
301  *#CRSimpleSel.
302  */
303 void
305 {
306  g_return_if_fail (a_this);
307 
308  if (a_this->name) {
309  cr_string_destroy (a_this->name);
310  a_this->name = NULL;
311  }
312 
313  if (a_this->add_sel) {
315  a_this->add_sel = NULL;
316  }
317 
318  if (a_this->next) {
319  cr_simple_sel_destroy (a_this->next);
320  }
321 
322  if (a_this) {
323  g_free (a_this);
324  }
325 }
_CRSimpleSel::name
CRString * name
Definition: cr-simple-sel.h:78
TYPE_SELECTOR
@ TYPE_SELECTOR
Definition: cr-simple-sel.h:52
_CRAdditionalSel
Definition: cr-additional-sel.h:56
_CRSimpleSel::specificity
gulong specificity
Definition: cr-simple-sel.h:100
_CRSimpleSel::combinator
enum Combinator combinator
The combinator that separates this simple selector from the previous one.
Definition: cr-simple-sel.h:84
cr_simple_sel_destroy
void cr_simple_sel_destroy(CRSimpleSel *a_this)
cr_simple_sel_destroy:
Definition: cr-simple-sel.c:304
PSEUDO_CLASS_ADD_SELECTOR
@ PSEUDO_CLASS_ADD_SELECTOR
Definition: cr-additional-sel.h:41
cr_simple_sel_dump
enum CRStatus cr_simple_sel_dump(CRSimpleSel const *a_this, FILE *a_fp)
cr_simple_sel_dump: @a_this: the current instance of CRSimpleSel.
Definition: cr-simple-sel.c:217
cr-simple-sel.h
cr_simple_sel_append_simple_sel
CRSimpleSel * cr_simple_sel_append_simple_sel(CRSimpleSel *a_this, CRSimpleSel *a_sel)
cr_simple_sel_append_simple_sel:
Definition: cr-simple-sel.c:61
CR_BAD_PARAM_ERROR
@ CR_BAD_PARAM_ERROR
Definition: cr-utils.h:45
cr_simple_sel_to_string
guchar * cr_simple_sel_to_string(CRSimpleSel const *a_this)
Definition: cr-simple-sel.c:103
cr_simple_sel_compute_specificity
enum CRStatus cr_simple_sel_compute_specificity(CRSimpleSel *a_this)
cr_simple_sel_compute_specificity:
Definition: cr-simple-sel.c:246
cr_additional_sel_to_string
guchar * cr_additional_sel_to_string(CRAdditionalSel const *a_this)
Definition: cr-additional-sel.c:233
COMB_GT
@ COMB_GT
Definition: cr-simple-sel.h:45
cr_string_destroy
void cr_string_destroy(CRString *a_this)
Definition: cr-string.c:159
CR_OK
@ CR_OK
Definition: cr-utils.h:44
_CRSimpleSel::prev
CRSimpleSel * prev
Definition: cr-simple-sel.h:103
cr_additional_sel_destroy
void cr_additional_sel_destroy(CRAdditionalSel *a_this)
cr_additional_sel_destroy: @a_this: the "this pointer" of the current instance of CRAdditionalSel .
Definition: cr-additional-sel.c:466
_CRSimpleSel::next
CRSimpleSel * next
Definition: cr-simple-sel.h:102
cr_simple_sel_new
CRSimpleSel * cr_simple_sel_new(void)
cr_simple_sel_new:
Definition: cr-simple-sel.c:36
COMB_PLUS
@ COMB_PLUS
Definition: cr-simple-sel.h:44
NO_ADD_SELECTOR
@ NO_ADD_SELECTOR
Definition: cr-additional-sel.h:39
_CRSimpleSel
The abstraction of a css2 simple selection list as defined by the right part of the "selector" produc...
Definition: cr-simple-sel.h:74
_CRSimpleSel::add_sel
CRAdditionalSel * add_sel
The additional selector list of the current simple selector.
Definition: cr-simple-sel.h:94
cr_simple_sel_prepend_simple_sel
CRSimpleSel * cr_simple_sel_prepend_simple_sel(CRSimpleSel *a_this, CRSimpleSel *a_sel)
cr_simple_sel_prepend_simple_sel:
Definition: cr-simple-sel.c:89
_CRAdditionalSel::next
CRAdditionalSel * next
Definition: cr-additional-sel.h:61
cr_simple_sel_one_to_string
guchar * cr_simple_sel_one_to_string(CRSimpleSel const *a_this)
Definition: cr-simple-sel.c:165
CRStatus
CRStatus
The status type returned by the methods of the croco library.
Definition: cr-utils.h:43
cr_utils_trace_info
#define cr_utils_trace_info(a_msg)
Traces an info message.
Definition: cr-utils.h:127
_CRAdditionalSel::type
enum AddSelectorType type
Definition: cr-additional-sel.h:58
_CRSimpleSel::type_mask
enum SimpleSelectorType type_mask
Definition: cr-simple-sel.h:76
ID_ADD_SELECTOR
@ ID_ADD_SELECTOR
Definition: cr-additional-sel.h:42
COMB_WS
@ COMB_WS
Definition: cr-simple-sel.h:43