1 /* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */
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 */
25 #include "cr-additional-sel.h"
26 #include "string.h"
28 /**
29 *Default constructor of #CRAdditionalSel.
30 *@return the newly build instance of #CRAdditionalSel.
31 */
32 CRAdditionalSel *
33 cr_additional_sel_new (void)
34 {
35 CRAdditionalSel *result = NULL;
37 result = g_try_malloc (sizeof (CRAdditionalSel));
39 if (result == NULL) {
40 cr_utils_trace_debug ("Out of memory");
41 return NULL;
42 }
44 memset (result, 0, sizeof (CRAdditionalSel));
46 return result;
47 }
49 /**
50 *Constructor of #CRAdditionalSel.
51 *@param a_sel_type the type of the newly built instance
52 *of #CRAdditionalSel.
53 *@return the newly built instance of #CRAdditionalSel.
54 */
55 CRAdditionalSel *
56 cr_additional_sel_new_with_type (enum AddSelectorType a_sel_type)
57 {
58 CRAdditionalSel *result = NULL;
60 result = cr_additional_sel_new ();
62 g_return_val_if_fail (result, NULL);
64 result->type = a_sel_type;
66 return result;
67 }
69 /**
70 *Sets a new class name to a
71 *CLASS additional selector.
72 *@param a_this the "this pointer" of the current instance
73 *of #CRAdditionalSel .
74 *@param a_class_name the new class name to set.
75 *
76 */
77 void
78 cr_additional_sel_set_class_name (CRAdditionalSel * a_this,
79 CRString * a_class_name)
80 {
81 g_return_if_fail (a_this && a_this->type == CLASS_ADD_SELECTOR);
83 if (a_this->content.class_name) {
84 cr_string_destroy (a_this->content.class_name);
85 }
87 a_this->content.class_name = a_class_name;
88 }
90 /**
91 *Sets a new id name to an
92 *ID additional selector.
93 *@param a_this the "this pointer" of the current instance
94 *of #CRAdditionalSel .
95 *@param a_id the new id to set.
96 */
97 void
98 cr_additional_sel_set_id_name (CRAdditionalSel * a_this, CRString * a_id)
99 {
100 g_return_if_fail (a_this && a_this->type == ID_ADD_SELECTOR);
102 if (a_this->content.id_name) {
103 cr_string_destroy (a_this->content.id_name);
104 }
106 a_this->content.id_name = a_id;
107 }
109 /**
110 *Sets a new pseudo to a
111 *PSEUDO additional selector.
112 *@param a_this the "this pointer" of the current instance
113 *of #CRAdditionalSel .
114 *@param a_pseudo the new pseudo to set.
115 */
116 void
117 cr_additional_sel_set_pseudo (CRAdditionalSel * a_this, CRPseudo * a_pseudo)
118 {
119 g_return_if_fail (a_this
120 && a_this->type == PSEUDO_CLASS_ADD_SELECTOR);
122 if (a_this->content.pseudo) {
123 cr_pseudo_destroy (a_this->content.pseudo);
124 }
126 a_this->content.pseudo = a_pseudo;
127 }
129 /**
130 *Sets a new instance of #CRAttrSel to
131 *a ATTRIBUTE additional selector.
132 *@param a_this the "this pointer" of the current instance
133 *of #CRAdditionalSel .
134 *@param a_sel the new instance of #CRAttrSel to set.
135 */
136 void
137 cr_additional_sel_set_attr_sel (CRAdditionalSel * a_this, CRAttrSel * a_sel)
138 {
139 g_return_if_fail (a_this && a_this->type == ATTRIBUTE_ADD_SELECTOR);
141 if (a_this->content.attr_sel) {
142 cr_attr_sel_destroy (a_this->content.attr_sel);
143 }
145 a_this->content.attr_sel = a_sel;
146 }
148 /**
149 *Appends a new instance of #CRAdditional to the
150 *current list of #CRAdditional.
151 *@param a_this the "this pointer" of the current instance
152 *of #CRAdditionalSel .
153 *@param a_sel the new instance to #CRAdditional to append.
154 *@return the new list of CRAdditionalSel or NULL if an error arises.
155 */
156 CRAdditionalSel *
157 cr_additional_sel_append (CRAdditionalSel * a_this, CRAdditionalSel * a_sel)
158 {
159 CRAdditionalSel *cur_sel = NULL;
161 g_return_val_if_fail (a_sel, NULL);
163 if (a_this == NULL) {
164 return a_sel;
165 }
167 if (a_sel == NULL)
168 return NULL;
170 for (cur_sel = a_this;
171 cur_sel && cur_sel->next; cur_sel = cur_sel->next) ;
173 g_return_val_if_fail (cur_sel != NULL, NULL);
175 cur_sel->next = a_sel;
176 a_sel->prev = cur_sel;
178 return a_this;
179 }
181 /**
182 *Preppends a new instance of #CRAdditional to the
183 *current list of #CRAdditional.
184 *@param a_this the "this pointer" of the current instance
185 *of #CRAdditionalSel .
186 *@param a_sel the new instance to #CRAdditional to preappend.
187 *@return the new list of CRAdditionalSel or NULL if an error arises.
188 */
189 CRAdditionalSel *
190 cr_additional_sel_prepend (CRAdditionalSel * a_this, CRAdditionalSel * a_sel)
191 {
192 g_return_val_if_fail (a_sel, NULL);
194 if (a_this == NULL) {
195 return a_sel;
196 }
198 a_sel->next = a_this;
199 a_this->prev = a_sel;
201 return a_sel;
202 }
204 guchar *
205 cr_additional_sel_to_string (CRAdditionalSel * a_this)
206 {
207 guchar *result = NULL;
208 GString *str_buf = NULL;
209 CRAdditionalSel *cur = NULL;
211 g_return_val_if_fail (a_this, NULL);
213 str_buf = g_string_new (NULL);
215 for (cur = a_this; cur; cur = cur->next) {
216 switch (cur->type) {
217 case CLASS_ADD_SELECTOR:
218 {
219 guchar *name = NULL;
221 if (cur->content.class_name) {
222 name = g_strndup
223 (cur->content.class_name->stryng->str,
224 cur->content.class_name->stryng->len);
226 if (name) {
227 g_string_append_printf
228 (str_buf, ".%s",
229 name);
230 g_free (name);
231 name = NULL;
232 }
233 }
234 }
235 break;
237 case ID_ADD_SELECTOR:
238 {
239 guchar *name = NULL;
241 if (cur->content.class_name) {
242 name = g_strndup
243 (cur->content.id_name->stryng->str,
244 cur->content.id_name->stryng->len);
246 if (name) {
247 g_string_append_printf
248 (str_buf, "#%s",
249 name);
250 g_free (name);
251 name = NULL;
252 }
253 }
254 }
256 break;
258 case PSEUDO_CLASS_ADD_SELECTOR:
259 {
260 if (cur->content.pseudo) {
261 guchar *tmp_str = NULL;
263 tmp_str = cr_pseudo_to_string
264 (cur->content.pseudo);
265 if (tmp_str) {
266 g_string_append_printf
267 (str_buf, ":%s",
268 tmp_str);
269 g_free (tmp_str);
270 tmp_str = NULL;
271 }
272 }
273 }
274 break;
276 case ATTRIBUTE_ADD_SELECTOR:
277 if (cur->content.attr_sel) {
278 guchar *tmp_str = NULL;
280 g_string_append_c (str_buf, '[');
281 tmp_str = cr_attr_sel_to_string
282 (cur->content.attr_sel);
283 if (tmp_str) {
284 g_string_append_printf
285 (str_buf, "%s]", tmp_str);
286 g_free (tmp_str);
287 tmp_str = NULL;
288 }
289 }
290 break;
292 default:
293 break;
294 }
295 }
297 if (str_buf) {
298 result = str_buf->str;
299 g_string_free (str_buf, FALSE);
300 str_buf = NULL;
301 }
303 return result;
304 }
306 guchar *
307 cr_additional_sel_one_to_string (CRAdditionalSel *a_this)
308 {
309 guchar *result = NULL;
310 GString *str_buf = NULL;
312 g_return_val_if_fail (a_this, NULL) ;
314 str_buf = g_string_new (NULL) ;
316 switch (a_this->type) {
317 case CLASS_ADD_SELECTOR:
318 {
319 guchar *name = NULL;
321 if (a_this->content.class_name) {
322 name = g_strndup
323 (a_this->content.class_name->stryng->str,
324 a_this->content.class_name->stryng->len);
326 if (name) {
327 g_string_append_printf
328 (str_buf, ".%s",
329 name);
330 g_free (name);
331 name = NULL;
332 }
333 }
334 }
335 break;
337 case ID_ADD_SELECTOR:
338 {
339 guchar *name = NULL;
341 if (a_this->content.class_name) {
342 name = g_strndup
343 (a_this->content.id_name->stryng->str,
344 a_this->content.id_name->stryng->len);
346 if (name) {
347 g_string_append_printf
348 (str_buf, "#%s",
349 name);
350 g_free (name);
351 name = NULL;
352 }
353 }
354 }
356 break;
358 case PSEUDO_CLASS_ADD_SELECTOR:
359 {
360 if (a_this->content.pseudo) {
361 guchar *tmp_str = NULL;
363 tmp_str = cr_pseudo_to_string
364 (a_this->content.pseudo);
365 if (tmp_str) {
366 g_string_append_printf
367 (str_buf, ":%s",
368 tmp_str);
369 g_free (tmp_str);
370 tmp_str = NULL;
371 }
372 }
373 }
374 break;
376 case ATTRIBUTE_ADD_SELECTOR:
377 if (a_this->content.attr_sel) {
378 guchar *tmp_str = NULL;
380 g_string_append_printf (str_buf, "[");
381 tmp_str = cr_attr_sel_to_string
382 (a_this->content.attr_sel);
383 if (tmp_str) {
384 g_string_append_printf
385 (str_buf, "%s]", tmp_str);
386 g_free (tmp_str);
387 tmp_str = NULL;
388 }
389 }
390 break;
392 default:
393 break;
394 }
396 if (str_buf) {
397 result = str_buf->str;
398 g_string_free (str_buf, FALSE);
399 str_buf = NULL;
400 }
402 return result;
403 }
405 /**
406 *Dumps the current instance of #CRAdditionalSel to a file
407 *@param a_this the "this pointer" of the current instance of
408 *#CRAdditionalSel.
409 *@param a_fp the destination file.
410 */
411 void
412 cr_additional_sel_dump (CRAdditionalSel * a_this, FILE * a_fp)
413 {
414 guchar *tmp_str = NULL;
416 g_return_if_fail (a_fp);
418 if (a_this) {
419 tmp_str = cr_additional_sel_to_string (a_this);
420 if (tmp_str) {
421 fprintf (a_fp, "%s", tmp_str);
422 g_free (tmp_str);
423 tmp_str = NULL;
424 }
425 }
426 }
428 /**
429 *Destroys an instance of #CRAdditional.
430 *@param a_this the "this pointer" of the current instance
431 *of #CRAdditionalSel .
432 */
433 void
434 cr_additional_sel_destroy (CRAdditionalSel * a_this)
435 {
436 g_return_if_fail (a_this);
438 switch (a_this->type) {
439 case CLASS_ADD_SELECTOR:
440 cr_string_destroy (a_this->content.class_name);
441 a_this->content.class_name = NULL;
442 break;
444 case PSEUDO_CLASS_ADD_SELECTOR:
445 cr_pseudo_destroy (a_this->content.pseudo);
446 a_this->content.pseudo = NULL;
447 break;
449 case ID_ADD_SELECTOR:
450 cr_string_destroy (a_this->content.id_name);
451 a_this->content.id_name = NULL;
452 break;
454 case ATTRIBUTE_ADD_SELECTOR:
455 cr_attr_sel_destroy (a_this->content.attr_sel);
456 a_this->content.attr_sel = NULL;
457 break;
459 default:
460 break;
461 }
463 if (a_this->next) {
464 cr_additional_sel_destroy (a_this->next);
465 }
467 g_free (a_this);
468 }