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 25#include <config.h> 26#include "cr-additional-sel.h" 27#include "string.h" 28 29/** 30 * CRAdditionalSel: 31 * 32 * #CRAdditionalSel abstracts an additionnal selector. 33 * An additional selector is the selector part 34 * that comes after the combination of type selectors. 35 * It can be either "a class selector (the .class part), 36 * a pseudo class selector, an attribute selector 37 * or an id selector. 38 */ 39 40/** 41 * cr_additional_sel_new: 42 * 43 * Default constructor of #CRAdditionalSel. 44 * Returns the newly build instance of #CRAdditionalSel. 45 */ 46CRAdditionalSel * 47cr_additional_sel_new (void) 48{ 49 CRAdditionalSel *result = NULL; 50 51 result = g_try_malloc (sizeof (CRAdditionalSel)); 52 53 if (result == NULL) { 54 cr_utils_trace_debug ("Out of memory"); 55 return NULL; 56 } 57 58 memset (result, 0, sizeof (CRAdditionalSel)); 59 60 return result; 61} 62 63/** 64 * cr_additional_sel_new_with_type: 65 * @a_sel_type: the type of the newly built instance 66 * of #CRAdditionalSel. 67 * 68 * Constructor of #CRAdditionalSel. 69 * Returns the newly built instance of #CRAdditionalSel. 70 */ 71CRAdditionalSel * 72cr_additional_sel_new_with_type (enum AddSelectorType a_sel_type) 73{ 74 CRAdditionalSel *result = NULL; 75 76 result = cr_additional_sel_new (); 77 78 g_return_val_if_fail (result, NULL); 79 80 result->type = a_sel_type; 81 82 return result; 83} 84 85/** 86 * cr_additional_sel_set_class_name: 87 * @a_this: the "this pointer" of the current instance 88 * of #CRAdditionalSel . 89 * @a_class_name: the new class name to set. 90 * 91 * Sets a new class name to a 92 * CLASS additional selector. 93 */ 94void 95cr_additional_sel_set_class_name (CRAdditionalSel * a_this, 96 CRString * a_class_name) 97{ 98 g_return_if_fail (a_this && a_this->type == CLASS_ADD_SELECTOR); 99 100 if (a_this->content.class_name) { 101 cr_string_destroy (a_this->content.class_name); 102 } 103 104 a_this->content.class_name = a_class_name; 105} 106 107/** 108 * cr_additional_sel_set_id_name: 109 * @a_this: the "this pointer" of the current instance 110 * of #CRAdditionalSel . 111 * @a_id: the new id to set. 112 * 113 * Sets a new id name to an 114 * ID additional selector. 115 */ 116void 117cr_additional_sel_set_id_name (CRAdditionalSel * a_this, CRString * a_id) 118{ 119 g_return_if_fail (a_this && a_this->type == ID_ADD_SELECTOR); 120 121 if (a_this->content.id_name) { 122 cr_string_destroy (a_this->content.id_name); 123 } 124 125 a_this->content.id_name = a_id; 126} 127 128/** 129 * cr_additional_sel_set_pseudo: 130 * @a_this: the "this pointer" of the current instance 131 * of #CRAdditionalSel . 132 * @a_pseudo: the new pseudo to set. 133 * 134 * Sets a new pseudo to a 135 * PSEUDO additional selector. 136 */ 137void 138cr_additional_sel_set_pseudo (CRAdditionalSel * a_this, CRPseudo * a_pseudo) 139{ 140 g_return_if_fail (a_this 141 && a_this->type == PSEUDO_CLASS_ADD_SELECTOR); 142 143 if (a_this->content.pseudo) { 144 cr_pseudo_destroy (a_this->content.pseudo); 145 } 146 147 a_this->content.pseudo = a_pseudo; 148} 149 150/** 151 * cr_additional_sel_set_attr_sel: 152 * @a_this: the "this pointer" of the current instance 153 * of #CRAdditionalSel . 154 * @a_sel: the new instance of #CRAttrSel to set. 155 * 156 * Sets a new instance of #CRAttrSel to 157 * a ATTRIBUTE additional selector. 158 */ 159void 160cr_additional_sel_set_attr_sel (CRAdditionalSel * a_this, CRAttrSel * a_sel) 161{ 162 g_return_if_fail (a_this && a_this->type == ATTRIBUTE_ADD_SELECTOR); 163 164 if (a_this->content.attr_sel) { 165 cr_attr_sel_destroy (a_this->content.attr_sel); 166 } 167 168 a_this->content.attr_sel = a_sel; 169} 170 171/** 172 * cr_additional_sel_append: 173 * @a_this: the "this pointer" of the current instance 174 * of #CRAdditionalSel . 175 * @a_sel: the new instance to #CRAdditional to append. 176 * 177 * Appends a new instance of #CRAdditional to the 178 * current list of #CRAdditional. 179 * 180 * Returns the new list of CRAdditionalSel or NULL if an error arises. 181 */ 182CRAdditionalSel * 183cr_additional_sel_append (CRAdditionalSel * a_this, CRAdditionalSel * a_sel) 184{ 185 CRAdditionalSel *cur_sel = NULL; 186 187 g_return_val_if_fail (a_sel, NULL); 188 189 if (a_this == NULL) { 190 return a_sel; 191 } 192 193 if (a_sel == NULL) 194 return NULL; 195 196 for (cur_sel = a_this; 197 cur_sel && cur_sel->next; cur_sel = cur_sel->next) ; 198 199 g_return_val_if_fail (cur_sel != NULL, NULL); 200 201 cur_sel->next = a_sel; 202 a_sel->prev = cur_sel; 203 204 return a_this; 205} 206 207/** 208 * cr_additional_sel_prepend: 209 * @a_this: the "this pointer" of the current instance 210 * of #CRAdditionalSel . 211 * @a_sel: the new instance to #CRAdditional to preappend. 212 * 213 * Preppends a new instance of #CRAdditional to the 214 * current list of #CRAdditional. 215 * 216 * Returns the new list of CRAdditionalSel or NULL if an error arises. 217 */ 218CRAdditionalSel * 219cr_additional_sel_prepend (CRAdditionalSel * a_this, CRAdditionalSel * a_sel) 220{ 221 g_return_val_if_fail (a_sel, NULL); 222 223 if (a_this == NULL) { 224 return a_sel; 225 } 226 227 a_sel->next = a_this; 228 a_this->prev = a_sel; 229 230 return a_sel; 231} 232 233guchar * 234cr_additional_sel_to_string (CRAdditionalSel * a_this) 235{ 236 guchar *result = NULL; 237 GString *str_buf = NULL; 238 CRAdditionalSel *cur = NULL; 239 240 g_return_val_if_fail (a_this, NULL); 241 242 str_buf = g_string_new (NULL); 243 244 for (cur = a_this; cur; cur = cur->next) { 245 switch (cur->type) { 246 case CLASS_ADD_SELECTOR: 247 { 248 guchar *name = NULL; 249 250 if (cur->content.class_name) { 251 name = g_strndup 252 (cur->content.class_name->stryng->str, 253 cur->content.class_name->stryng->len); 254 255 if (name) { 256 g_string_append_printf 257 (str_buf, ".%s", 258 name); 259 g_free (name); 260 name = NULL; 261 } 262 } 263 } 264 break; 265 266 case ID_ADD_SELECTOR: 267 { 268 guchar *name = NULL; 269 270 if (cur->content.class_name) { 271 name = g_strndup 272 (cur->content.id_name->stryng->str, 273 cur->content.id_name->stryng->len); 274 275 if (name) { 276 g_string_append_printf 277 (str_buf, "#%s", 278 name); 279 g_free (name); 280 name = NULL; 281 } 282 } 283 } 284 285 break; 286 287 case PSEUDO_CLASS_ADD_SELECTOR: 288 { 289 if (cur->content.pseudo) { 290 guchar *tmp_str = NULL; 291 292 tmp_str = cr_pseudo_to_string 293 (cur->content.pseudo); 294 if (tmp_str) { 295 g_string_append_printf 296 (str_buf, ":%s", 297 tmp_str); 298 g_free (tmp_str); 299 tmp_str = NULL; 300 } 301 } 302 } 303 break; 304 305 case ATTRIBUTE_ADD_SELECTOR: 306 if (cur->content.attr_sel) { 307 guchar *tmp_str = NULL; 308 309 g_string_append_c (str_buf, '['); 310 tmp_str = cr_attr_sel_to_string 311 (cur->content.attr_sel); 312 if (tmp_str) { 313 g_string_append_printf 314 (str_buf, "%s]", tmp_str); 315 g_free (tmp_str); 316 tmp_str = NULL; 317 } 318 } 319 break; 320 321 default: 322 break; 323 } 324 } 325 326 if (str_buf) { 327 result = str_buf->str; 328 g_string_free (str_buf, FALSE); 329 str_buf = NULL; 330 } 331 332 return result; 333} 334 335guchar * 336cr_additional_sel_one_to_string (CRAdditionalSel *a_this) 337{ 338 guchar *result = NULL; 339 GString *str_buf = NULL; 340 341 g_return_val_if_fail (a_this, NULL) ; 342 343 str_buf = g_string_new (NULL) ; 344 345 switch (a_this->type) { 346 case CLASS_ADD_SELECTOR: 347 { 348 guchar *name = NULL; 349 350 if (a_this->content.class_name) { 351 name = g_strndup 352 (a_this->content.class_name->stryng->str, 353 a_this->content.class_name->stryng->len); 354 355 if (name) { 356 g_string_append_printf 357 (str_buf, ".%s", 358 name); 359 g_free (name); 360 name = NULL; 361 } 362 } 363 } 364 break; 365 366 case ID_ADD_SELECTOR: 367 { 368 guchar *name = NULL; 369 370 if (a_this->content.class_name) { 371 name = g_strndup 372 (a_this->content.id_name->stryng->str, 373 a_this->content.id_name->stryng->len); 374 375 if (name) { 376 g_string_append_printf 377 (str_buf, "#%s", 378 name); 379 g_free (name); 380 name = NULL; 381 } 382 } 383 } 384 385 break; 386 387 case PSEUDO_CLASS_ADD_SELECTOR: 388 { 389 if (a_this->content.pseudo) { 390 guchar *tmp_str = NULL; 391 392 tmp_str = cr_pseudo_to_string 393 (a_this->content.pseudo); 394 if (tmp_str) { 395 g_string_append_printf 396 (str_buf, ":%s", 397 tmp_str); 398 g_free (tmp_str); 399 tmp_str = NULL; 400 } 401 } 402 } 403 break; 404 405 case ATTRIBUTE_ADD_SELECTOR: 406 if (a_this->content.attr_sel) { 407 guchar *tmp_str = NULL; 408 409 g_string_append_printf (str_buf, "["); 410 tmp_str = cr_attr_sel_to_string 411 (a_this->content.attr_sel); 412 if (tmp_str) { 413 g_string_append_printf 414 (str_buf, "%s]", tmp_str); 415 g_free (tmp_str); 416 tmp_str = NULL; 417 } 418 } 419 break; 420 421 default: 422 break; 423 } 424 425 if (str_buf) { 426 result = str_buf->str; 427 g_string_free (str_buf, FALSE); 428 str_buf = NULL; 429 } 430 431 return result; 432} 433 434/** 435 * cr_additional_sel_dump: 436 * @a_this: the "this pointer" of the current instance of 437 * #CRAdditionalSel. 438 * @a_fp: the destination file. 439 * 440 * Dumps the current instance of #CRAdditionalSel to a file 441 */ 442void 443cr_additional_sel_dump (CRAdditionalSel * a_this, FILE * a_fp) 444{ 445 guchar *tmp_str = NULL; 446 447 g_return_if_fail (a_fp); 448 449 if (a_this) { 450 tmp_str = cr_additional_sel_to_string (a_this); 451 if (tmp_str) { 452 fprintf (a_fp, "%s", tmp_str); 453 g_free (tmp_str); 454 tmp_str = NULL; 455 } 456 } 457} 458 459/** 460 * cr_additional_sel_destroy: 461 * @a_this: the "this pointer" of the current instance 462 * of #CRAdditionalSel . 463 * 464 * Destroys an instance of #CRAdditional. 465 */ 466void 467cr_additional_sel_destroy (CRAdditionalSel * a_this) 468{ 469 g_return_if_fail (a_this); 470 471 switch (a_this->type) { 472 case CLASS_ADD_SELECTOR: 473 cr_string_destroy (a_this->content.class_name); 474 a_this->content.class_name = NULL; 475 break; 476 477 case PSEUDO_CLASS_ADD_SELECTOR: 478 cr_pseudo_destroy (a_this->content.pseudo); 479 a_this->content.pseudo = NULL; 480 break; 481 482 case ID_ADD_SELECTOR: 483 cr_string_destroy (a_this->content.id_name); 484 a_this->content.id_name = NULL; 485 break; 486 487 case ATTRIBUTE_ADD_SELECTOR: 488 cr_attr_sel_destroy (a_this->content.attr_sel); 489 a_this->content.attr_sel = NULL; 490 break; 491 492 default: 493 break; 494 } 495 496 if (a_this->next) { 497 cr_additional_sel_destroy (a_this->next); 498 } 499 500 g_free (a_this); 501} 502