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 <config.h> 25#include <string.h> 26#include "cr-utils.h" 27#include "cr-om-parser.h" 28 29/** 30 *@CROMParser: 31 * 32 *The definition of the CSS Object Model Parser. 33 *This parser uses (and sits) the SAC api of libcroco defined 34 *in cr-parser.h and cr-doc-handler.h 35 */ 36 37struct _CROMParserPriv { 38 CRParser *parser; 39}; 40 41#define PRIVATE(a_this) ((a_this)->priv) 42 43/* 44 *Forward declaration of a type defined later 45 *in this file. 46 */ 47struct _ParsingContext; 48typedef struct _ParsingContext ParsingContext; 49 50static ParsingContext *new_parsing_context (void); 51 52static void destroy_context (ParsingContext * a_ctxt); 53 54static void unrecoverable_error (CRDocHandler * a_this); 55 56static void error (CRDocHandler * a_this); 57 58static void property (CRDocHandler * a_this, 59 CRString * a_name, 60 CRTerm * a_expression, 61 gboolean a_important); 62 63static void end_selector (CRDocHandler * a_this, 64 CRSelector * a_selector_list); 65 66static void start_selector (CRDocHandler * a_this, 67 CRSelector * a_selector_list); 68 69static void start_font_face (CRDocHandler * a_this, 70 CRParsingLocation *a_location); 71 72static void end_font_face (CRDocHandler * a_this); 73 74static void end_document (CRDocHandler * a_this); 75 76static void start_document (CRDocHandler * a_this); 77 78static void charset (CRDocHandler * a_this, 79 CRString * a_charset, 80 CRParsingLocation *a_location); 81 82static void start_page (CRDocHandler * a_this, CRString * a_page, 83 CRString * a_pseudo_page, 84 CRParsingLocation *a_location); 85 86static void end_page (CRDocHandler * a_this, CRString * a_page, 87 CRString * a_pseudo_page); 88 89static void start_media (CRDocHandler * a_this, 90 GList * a_media_list, 91 CRParsingLocation *a_location); 92 93static void end_media (CRDocHandler * a_this, 94 GList * a_media_list); 95 96static void import_style (CRDocHandler * a_this, 97 GList * a_media_list, 98 CRString * a_uri, 99 CRString * a_uri_default_ns, 100 CRParsingLocation *a_location); 101 102struct _ParsingContext { 103 CRStyleSheet *stylesheet; 104 CRStatement *cur_stmt; 105 CRStatement *cur_media_stmt; 106}; 107 108/******************************************** 109 *Private methods 110 ********************************************/ 111 112static ParsingContext * 113new_parsing_context (void) 114{ 115 ParsingContext *result = NULL; 116 117 result = g_try_malloc (sizeof (ParsingContext)); 118 if (!result) { 119 cr_utils_trace_info ("Out of Memory"); 120 return NULL; 121 } 122 memset (result, 0, sizeof (ParsingContext)); 123 return result; 124} 125 126static void 127destroy_context (ParsingContext * a_ctxt) 128{ 129 g_return_if_fail (a_ctxt); 130 131 if (a_ctxt->stylesheet) { 132 cr_stylesheet_destroy (a_ctxt->stylesheet); 133 a_ctxt->stylesheet = NULL; 134 } 135 if (a_ctxt->cur_stmt) { 136 cr_statement_destroy (a_ctxt->cur_stmt); 137 a_ctxt->cur_stmt = NULL; 138 } 139 g_free (a_ctxt); 140} 141 142static enum CRStatus 143cr_om_parser_init_default_sac_handler (CROMParser * a_this) 144{ 145 CRDocHandler *sac_handler = NULL; 146 gboolean free_hdlr_if_error = FALSE; 147 enum CRStatus status = CR_OK; 148 149 g_return_val_if_fail (a_this && PRIVATE (a_this) 150 && PRIVATE (a_this)->parser, 151 CR_BAD_PARAM_ERROR); 152 153 status = cr_parser_get_sac_handler (PRIVATE (a_this)->parser, 154 &sac_handler); 155 g_return_val_if_fail (status == CR_OK, status); 156 157 if (!sac_handler) { 158 sac_handler = cr_doc_handler_new (); 159 free_hdlr_if_error = TRUE; 160 } 161 162 /* 163 *initialyze here the sac handler. 164 */ 165 sac_handler->start_document = start_document; 166 sac_handler->end_document = end_document; 167 sac_handler->start_selector = start_selector; 168 sac_handler->end_selector = end_selector; 169 sac_handler->property = property; 170 sac_handler->start_font_face = start_font_face; 171 sac_handler->end_font_face = end_font_face; 172 sac_handler->error = error; 173 sac_handler->unrecoverable_error = unrecoverable_error; 174 sac_handler->charset = charset; 175 sac_handler->start_page = start_page; 176 sac_handler->end_page = end_page; 177 sac_handler->start_media = start_media; 178 sac_handler->end_media = end_media; 179 sac_handler->import_style = import_style; 180 181 status = cr_parser_set_sac_handler (PRIVATE (a_this)->parser, 182 sac_handler); 183 if (status == CR_OK) { 184 return CR_OK; 185 } 186 187 if (sac_handler && free_hdlr_if_error == TRUE) { 188 cr_doc_handler_destroy (sac_handler); 189 sac_handler = NULL; 190 } 191 192 return status; 193 194} 195 196static void 197start_document (CRDocHandler * a_this) 198{ 199 ParsingContext *ctxt = NULL; 200 CRStyleSheet *stylesheet = NULL; 201 202 g_return_if_fail (a_this); 203 204 ctxt = new_parsing_context (); 205 g_return_if_fail (ctxt); 206 207 stylesheet = cr_stylesheet_new (NULL); 208 ctxt->stylesheet = stylesheet; 209 cr_doc_handler_set_ctxt (a_this, ctxt); 210} 211 212static void 213start_font_face (CRDocHandler * a_this, 214 CRParsingLocation *a_location) 215{ 216 enum CRStatus status = CR_OK; 217 ParsingContext *ctxt = NULL; 218 ParsingContext **ctxtptr = NULL; 219 220 g_return_if_fail (a_this); 221 222 g_return_if_fail (a_this); 223 ctxtptr = &ctxt; 224 status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr); 225 g_return_if_fail (status == CR_OK && ctxt); 226 g_return_if_fail (ctxt->cur_stmt == NULL); 227 228 ctxt->cur_stmt = 229 cr_statement_new_at_font_face_rule (ctxt->stylesheet, NULL); 230 231 g_return_if_fail (ctxt->cur_stmt); 232} 233 234static void 235end_font_face (CRDocHandler * a_this) 236{ 237 enum CRStatus status = CR_OK; 238 ParsingContext *ctxt = NULL; 239 ParsingContext **ctxtptr = NULL; 240 CRStatement *stmts = NULL; 241 242 g_return_if_fail (a_this); 243 244 g_return_if_fail (a_this); 245 ctxtptr = &ctxt; 246 status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr); 247 g_return_if_fail (status == CR_OK && ctxt); 248 g_return_if_fail 249 (ctxt->cur_stmt 250 && ctxt->cur_stmt->type == AT_FONT_FACE_RULE_STMT 251 && ctxt->stylesheet); 252 253 stmts = cr_statement_append (ctxt->stylesheet->statements, 254 ctxt->cur_stmt); 255 if (!stmts) 256 goto error; 257 258 ctxt->stylesheet->statements = stmts; 259 stmts = NULL; 260 ctxt->cur_stmt = NULL; 261 262 return; 263 264 error: 265 266 if (ctxt->cur_stmt) { 267 cr_statement_destroy (ctxt->cur_stmt); 268 ctxt->cur_stmt = NULL; 269 } 270 271 if (!stmts) { 272 cr_statement_destroy (stmts); 273 stmts = NULL; 274 } 275} 276 277static void 278end_document (CRDocHandler * a_this) 279{ 280 enum CRStatus status = CR_OK; 281 ParsingContext *ctxt = NULL; 282 ParsingContext **ctxtptr = NULL; 283 284 g_return_if_fail (a_this); 285 ctxtptr = &ctxt; 286 status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr); 287 g_return_if_fail (status == CR_OK && ctxt); 288 289 if (!ctxt->stylesheet || ctxt->cur_stmt) 290 goto error; 291 292 status = cr_doc_handler_set_result (a_this, ctxt->stylesheet); 293 g_return_if_fail (status == CR_OK); 294 295 ctxt->stylesheet = NULL; 296 destroy_context (ctxt); 297 cr_doc_handler_set_ctxt (a_this, NULL); 298 299 return; 300 301 error: 302 if (ctxt) { 303 destroy_context (ctxt); 304 } 305} 306 307static void 308charset (CRDocHandler * a_this, CRString * a_charset, 309 CRParsingLocation *a_location) 310{ 311 enum CRStatus status = CR_OK; 312 CRStatement *stmt = NULL, 313 *stmt2 = NULL; 314 CRString *charset = NULL; 315 316 ParsingContext *ctxt = NULL; 317 ParsingContext **ctxtptr = NULL; 318 319 g_return_if_fail (a_this); 320 ctxtptr = &ctxt; 321 status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr); 322 g_return_if_fail (status == CR_OK && ctxt); 323 g_return_if_fail (ctxt->stylesheet); 324 325 charset = cr_string_dup (a_charset) ; 326 stmt = cr_statement_new_at_charset_rule (ctxt->stylesheet, charset); 327 g_return_if_fail (stmt); 328 stmt2 = cr_statement_append (ctxt->stylesheet->statements, stmt); 329 if (!stmt2) { 330 if (stmt) { 331 cr_statement_destroy (stmt); 332 stmt = NULL; 333 } 334 if (charset) { 335 cr_string_destroy (charset); 336 } 337 return; 338 } 339 ctxt->stylesheet->statements = stmt2; 340 stmt2 = NULL; 341} 342 343static void 344start_page (CRDocHandler * a_this, 345 CRString * a_page, 346 CRString * a_pseudo, 347 CRParsingLocation *a_location) 348{ 349 enum CRStatus status = CR_OK; 350 ParsingContext *ctxt = NULL; 351 ParsingContext **ctxtptr = NULL; 352 353 g_return_if_fail (a_this); 354 ctxtptr = &ctxt; 355 status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr); 356 g_return_if_fail (status == CR_OK && ctxt); 357 g_return_if_fail (ctxt->cur_stmt == NULL); 358 359 ctxt->cur_stmt = cr_statement_new_at_page_rule 360 (ctxt->stylesheet, NULL, NULL, NULL); 361 if (a_page) { 362 ctxt->cur_stmt->kind.page_rule->name = 363 cr_string_dup (a_page) ; 364 365 if (!ctxt->cur_stmt->kind.page_rule->name) { 366 goto error; 367 } 368 } 369 if (a_pseudo) { 370 ctxt->cur_stmt->kind.page_rule->pseudo = 371 cr_string_dup (a_pseudo) ; 372 if (!ctxt->cur_stmt->kind.page_rule->pseudo) { 373 goto error; 374 } 375 } 376 return; 377 378 error: 379 if (ctxt->cur_stmt) { 380 cr_statement_destroy (ctxt->cur_stmt); 381 ctxt->cur_stmt = NULL; 382 } 383} 384 385static void 386end_page (CRDocHandler * a_this, 387 CRString * a_page, 388 CRString * a_pseudo_page) 389{ 390 enum CRStatus status = CR_OK; 391 ParsingContext *ctxt = NULL; 392 ParsingContext **ctxtptr = NULL; 393 CRStatement *stmt = NULL; 394 395 g_return_if_fail (a_this); 396 ctxtptr = &ctxt; 397 status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr); 398 g_return_if_fail (status == CR_OK && ctxt); 399 g_return_if_fail (ctxt->cur_stmt 400 && ctxt->cur_stmt->type == AT_PAGE_RULE_STMT 401 && ctxt->stylesheet); 402 403 stmt = cr_statement_append (ctxt->stylesheet->statements, 404 ctxt->cur_stmt); 405 406 if (stmt) { 407 ctxt->stylesheet->statements = stmt; 408 stmt = NULL; 409 ctxt->cur_stmt = NULL; 410 } 411 412 if (ctxt->cur_stmt) { 413 cr_statement_destroy (ctxt->cur_stmt); 414 ctxt->cur_stmt = NULL; 415 } 416 a_page = NULL; /*keep compiler happy */ 417 a_pseudo_page = NULL; /*keep compiler happy */ 418} 419 420static void 421start_media (CRDocHandler * a_this, 422 GList * a_media_list, 423 CRParsingLocation *a_location) 424{ 425 enum CRStatus status = CR_OK; 426 ParsingContext *ctxt = NULL; 427 ParsingContext **ctxtptr = NULL; 428 GList *media_list = NULL; 429 430 g_return_if_fail (a_this); 431 ctxtptr = &ctxt; 432 status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr); 433 g_return_if_fail (status == CR_OK && ctxt); 434 435 g_return_if_fail (ctxt 436 && ctxt->cur_stmt == NULL 437 && ctxt->cur_media_stmt == NULL 438 && ctxt->stylesheet); 439 if (a_media_list) { 440 /*duplicate the media_list */ 441 media_list = cr_utils_dup_glist_of_cr_string 442 (a_media_list); 443 } 444 ctxt->cur_media_stmt = 445 cr_statement_new_at_media_rule 446 (ctxt->stylesheet, NULL, media_list); 447 448} 449 450static void 451end_media (CRDocHandler * a_this, GList * a_media_list) 452{ 453 enum CRStatus status = CR_OK; 454 ParsingContext *ctxt = NULL; 455 ParsingContext **ctxtptr = NULL; 456 CRStatement *stmts = NULL; 457 458 g_return_if_fail (a_this); 459 ctxtptr = &ctxt; 460 status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr); 461 g_return_if_fail (status == CR_OK && ctxt); 462 g_return_if_fail (ctxt 463 && ctxt->cur_media_stmt 464 && ctxt->cur_media_stmt->type == AT_MEDIA_RULE_STMT 465 && ctxt->stylesheet); 466 467 stmts = cr_statement_append (ctxt->stylesheet->statements, 468 ctxt->cur_media_stmt); 469 if (!stmts) { 470 cr_statement_destroy (ctxt->cur_media_stmt); 471 ctxt->cur_media_stmt = NULL; 472 } 473 474 ctxt->stylesheet->statements = stmts; 475 stmts = NULL; 476 477 ctxt->cur_stmt = NULL ; 478 ctxt->cur_media_stmt = NULL ; 479 a_media_list = NULL; 480} 481 482static void 483import_style (CRDocHandler * a_this, 484 GList * a_media_list, 485 CRString * a_uri, 486 CRString * a_uri_default_ns, 487 CRParsingLocation *a_location) 488{ 489 enum CRStatus status = CR_OK; 490 CRString *uri = NULL; 491 CRStatement *stmt = NULL, 492 *stmt2 = NULL; 493 ParsingContext *ctxt = NULL; 494 ParsingContext **ctxtptr = NULL; 495 GList *media_list = NULL ; 496 497 g_return_if_fail (a_this); 498 ctxtptr = &ctxt; 499 status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr); 500 g_return_if_fail (status == CR_OK && ctxt); 501 g_return_if_fail (ctxt->stylesheet); 502 503 uri = cr_string_dup (a_uri) ; 504 if (a_media_list) 505 media_list = cr_utils_dup_glist_of_cr_string (a_media_list) ; 506 stmt = cr_statement_new_at_import_rule 507 (ctxt->stylesheet, uri, media_list, NULL); 508 if (!stmt) 509 goto error; 510 511 if (ctxt->cur_stmt) { 512 stmt2 = cr_statement_append (ctxt->cur_stmt, stmt); 513 if (!stmt2) 514 goto error; 515 ctxt->cur_stmt = stmt2; 516 stmt2 = NULL; 517 stmt = NULL; 518 } else { 519 stmt2 = cr_statement_append (ctxt->stylesheet->statements, 520 stmt); 521 if (!stmt2) 522 goto error; 523 ctxt->stylesheet->statements = stmt2; 524 stmt2 = NULL; 525 stmt = NULL; 526 } 527 528 return; 529 530 error: 531 if (uri) { 532 cr_string_destroy (uri); 533 } 534 535 if (stmt) { 536 cr_statement_destroy (stmt); 537 stmt = NULL; 538 } 539 a_uri_default_ns = NULL; /*keep compiler happy */ 540} 541 542static void 543start_selector (CRDocHandler * a_this, CRSelector * a_selector_list) 544{ 545 enum CRStatus status = CR_OK ; 546 ParsingContext *ctxt = NULL; 547 ParsingContext **ctxtptr = NULL; 548 549 g_return_if_fail (a_this); 550 ctxtptr = &ctxt; 551 status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr); 552 g_return_if_fail (status == CR_OK && ctxt); 553 if (ctxt->cur_stmt) { 554 /*hmm, this should be NULL so free it */ 555 cr_statement_destroy (ctxt->cur_stmt); 556 ctxt->cur_stmt = NULL; 557 } 558 559 ctxt->cur_stmt = cr_statement_new_ruleset 560 (ctxt->stylesheet, a_selector_list, NULL, NULL); 561} 562 563static void 564end_selector (CRDocHandler * a_this, CRSelector * a_selector_list) 565{ 566 enum CRStatus status = CR_OK; 567 ParsingContext *ctxt = NULL; 568 ParsingContext **ctxtptr = NULL; 569 570 g_return_if_fail (a_this); 571 ctxtptr = &ctxt; 572 status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr); 573 g_return_if_fail (status == CR_OK && ctxt); 574 g_return_if_fail (ctxt->cur_stmt && ctxt->stylesheet); 575 576 if (ctxt->cur_stmt) { 577 CRStatement *stmts = NULL; 578 579 if (ctxt->cur_media_stmt) { 580 CRAtMediaRule *media_rule = NULL; 581 582 media_rule = ctxt->cur_media_stmt->kind.media_rule; 583 584 stmts = cr_statement_append 585 (media_rule->rulesets, ctxt->cur_stmt); 586 587 if (!stmts) { 588 cr_utils_trace_info 589 ("Could not append a new statement"); 590 cr_statement_destroy (media_rule->rulesets); 591 ctxt->cur_media_stmt-> 592 kind.media_rule->rulesets = NULL; 593 return; 594 } 595 media_rule->rulesets = stmts; 596 ctxt->cur_stmt = NULL; 597 } else { 598 stmts = cr_statement_append 599 (ctxt->stylesheet->statements, 600 ctxt->cur_stmt); 601 if (!stmts) { 602 cr_utils_trace_info 603 ("Could not append a new statement"); 604 cr_statement_destroy (ctxt->cur_stmt); 605 ctxt->cur_stmt = NULL; 606 return; 607 } 608 ctxt->stylesheet->statements = stmts; 609 ctxt->cur_stmt = NULL; 610 } 611 612 } 613 a_selector_list = NULL; /*keep compiler happy */ 614} 615 616static void 617property (CRDocHandler * a_this, 618 CRString * a_name, 619 CRTerm * a_expression, 620 gboolean a_important) 621{ 622 enum CRStatus status = CR_OK; 623 ParsingContext *ctxt = NULL; 624 ParsingContext **ctxtptr = NULL; 625 CRDeclaration *decl = NULL, 626 *decl2 = NULL; 627 CRString *str = NULL; 628 629 g_return_if_fail (a_this); 630 ctxtptr = &ctxt; 631 status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr); 632 g_return_if_fail (status == CR_OK && ctxt); 633 634 /* 635 *make sure a current ruleset statement has been allocated 636 *already. 637 */ 638 g_return_if_fail 639 (ctxt->cur_stmt 640 && 641 (ctxt->cur_stmt->type == RULESET_STMT 642 || ctxt->cur_stmt->type == AT_FONT_FACE_RULE_STMT 643 || ctxt->cur_stmt->type == AT_PAGE_RULE_STMT)); 644 645 if (a_name) { 646 str = cr_string_dup (a_name); 647 g_return_if_fail (str); 648 } 649 650 /*instanciates a new declaration */ 651 decl = cr_declaration_new (ctxt->cur_stmt, str, a_expression); 652 g_return_if_fail (decl); 653 str = NULL; 654 decl->important = a_important; 655 /* 656 *add the new declaration to the current statement 657 *being build. 658 */ 659 switch (ctxt->cur_stmt->type) { 660 case RULESET_STMT: 661 decl2 = cr_declaration_append 662 (ctxt->cur_stmt->kind.ruleset->decl_list, decl); 663 if (!decl2) { 664 cr_declaration_destroy (decl); 665 cr_utils_trace_info 666 ("Could not append decl to ruleset"); 667 goto error; 668 } 669 ctxt->cur_stmt->kind.ruleset->decl_list = decl2; 670 decl = NULL; 671 decl2 = NULL; 672 break; 673 674 case AT_FONT_FACE_RULE_STMT: 675 decl2 = cr_declaration_append 676 (ctxt->cur_stmt->kind.font_face_rule->decl_list, 677 decl); 678 if (!decl2) { 679 cr_declaration_destroy (decl); 680 cr_utils_trace_info 681 ("Could not append decl to ruleset"); 682 goto error; 683 } 684 ctxt->cur_stmt->kind.font_face_rule->decl_list = decl2; 685 decl = NULL; 686 decl2 = NULL; 687 break; 688 case AT_PAGE_RULE_STMT: 689 decl2 = cr_declaration_append 690 (ctxt->cur_stmt->kind.page_rule->decl_list, decl); 691 if (!decl2) { 692 cr_declaration_destroy (decl); 693 cr_utils_trace_info 694 ("Could not append decl to ruleset"); 695 goto error; 696 } 697 ctxt->cur_stmt->kind.page_rule->decl_list = decl2; 698 decl = NULL; 699 decl2 = NULL; 700 break; 701 702 default: 703 goto error; 704 break; 705 } 706 707 return; 708 709 error: 710 if (str) { 711 g_free (str); 712 str = NULL; 713 } 714 715 if (decl) { 716 cr_declaration_destroy (decl); 717 decl = NULL; 718 } 719} 720 721static void 722error (CRDocHandler * a_this) 723{ 724 enum CRStatus status = CR_OK; 725 ParsingContext *ctxt = NULL; 726 ParsingContext **ctxtptr = NULL; 727 728 g_return_if_fail (a_this); 729 ctxtptr = &ctxt; 730 status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr); 731 g_return_if_fail (status == CR_OK && ctxt); 732 733 if (ctxt->cur_stmt) { 734 cr_statement_destroy (ctxt->cur_stmt); 735 ctxt->cur_stmt = NULL; 736 } 737} 738 739static void 740unrecoverable_error (CRDocHandler * a_this) 741{ 742 enum CRStatus status = CR_OK; 743 ParsingContext *ctxt = NULL; 744 ParsingContext **ctxtptr = NULL; 745 746 ctxtptr = &ctxt; 747 status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr); 748 g_return_if_fail (status == CR_OK); 749 750 if (ctxt) { 751 if (ctxt->stylesheet) { 752 status = cr_doc_handler_set_result 753 (a_this, ctxt->stylesheet); 754 g_return_if_fail (status == CR_OK); 755 } 756 g_free (ctxt); 757 cr_doc_handler_set_ctxt (a_this, NULL); 758 } 759} 760 761/******************************************** 762 *Public methods 763 ********************************************/ 764 765/** 766 * cr_om_parser_new: 767 *@a_input: the input stream. 768 * 769 *Constructor of the CROMParser. 770 *Returns the newly built instance of #CROMParser. 771 */ 772CROMParser * 773cr_om_parser_new (CRInput * a_input) 774{ 775 CROMParser *result = NULL; 776 enum CRStatus status = CR_OK; 777 778 result = g_try_malloc (sizeof (CROMParser)); 779 780 if (!result) { 781 cr_utils_trace_info ("Out of memory"); 782 return NULL; 783 } 784 785 memset (result, 0, sizeof (CROMParser)); 786 PRIVATE (result) = g_try_malloc (sizeof (CROMParserPriv)); 787 788 if (!PRIVATE (result)) { 789 cr_utils_trace_info ("Out of memory"); 790 goto error; 791 } 792 793 memset (PRIVATE (result), 0, sizeof (CROMParserPriv)); 794 795 PRIVATE (result)->parser = cr_parser_new_from_input (a_input); 796 797 if (!PRIVATE (result)->parser) { 798 cr_utils_trace_info ("parsing instanciation failed"); 799 goto error; 800 } 801 802 status = cr_om_parser_init_default_sac_handler (result); 803 804 if (status != CR_OK) { 805 goto error; 806 } 807 808 return result; 809 810 error: 811 812 if (result) { 813 cr_om_parser_destroy (result); 814 } 815 816 return NULL; 817} 818 819/** 820 * cr_om_parser_parse_buf: 821 *@a_this: the current instance of #CROMParser. 822 *@a_buf: the in memory buffer to parse. 823 *@a_len: the length of the in memory buffer in number of bytes. 824 *@a_enc: the encoding of the in memory buffer. 825 *@a_result: out parameter the resulting style sheet 826 * 827 *Parses the content of an in memory buffer. 828 * 829 *Returns CR_OK upon successfull completion, an error code otherwise. 830 */ 831enum CRStatus 832cr_om_parser_parse_buf (CROMParser * a_this, 833 const guchar * a_buf, 834 gulong a_len, 835 enum CREncoding a_enc, CRStyleSheet ** a_result) 836{ 837 838 enum CRStatus status = CR_OK; 839 840 g_return_val_if_fail (a_this && a_result, CR_BAD_PARAM_ERROR); 841 842 if (!PRIVATE (a_this)->parser) { 843 PRIVATE (a_this)->parser = cr_parser_new (NULL); 844 } 845 846 status = cr_parser_parse_buf (PRIVATE (a_this)->parser, 847 a_buf, a_len, a_enc); 848 849 if (status == CR_OK) { 850 CRStyleSheet *result = NULL; 851 CRStyleSheet **resultptr = NULL; 852 CRDocHandler *sac_handler = NULL; 853 854 cr_parser_get_sac_handler (PRIVATE (a_this)->parser, 855 &sac_handler); 856 g_return_val_if_fail (sac_handler, CR_ERROR); 857 resultptr = &result; 858 status = cr_doc_handler_get_result (sac_handler, 859 (gpointer *) resultptr); 860 g_return_val_if_fail (status == CR_OK, status); 861 862 if (result) 863 *a_result = result; 864 } 865 866 return status; 867} 868 869/** 870 * cr_om_parser_simply_parse_buf: 871 *@a_buf: the css2 in memory buffer. 872 *@a_len: the length of the in memory buffer. 873 *@a_enc: the encoding of the in memory buffer. 874 *@a_result: out parameter. The resulting css2 style sheet. 875 * 876 *The simpler way to parse an in memory css2 buffer. 877 * 878 *Returns CR_OK upon successfull completion, an error code otherwise. 879 */ 880enum CRStatus 881cr_om_parser_simply_parse_buf (const guchar * a_buf, 882 gulong a_len, 883 enum CREncoding a_enc, 884 CRStyleSheet ** a_result) 885{ 886 CROMParser *parser = NULL; 887 enum CRStatus status = CR_OK; 888 889 parser = cr_om_parser_new (NULL); 890 if (!parser) { 891 cr_utils_trace_info ("Could not create om parser"); 892 cr_utils_trace_info ("System possibly out of memory"); 893 return CR_ERROR; 894 } 895 896 status = cr_om_parser_parse_buf (parser, a_buf, a_len, 897 a_enc, a_result); 898 899 if (parser) { 900 cr_om_parser_destroy (parser); 901 parser = NULL; 902 } 903 904 return status; 905} 906 907/** 908 * cr_om_parser_parse_file: 909 *@a_this: the current instance of the cssom parser. 910 *@a_file_uri: the uri of the file. 911 *(only local file paths are suppported so far) 912 *@a_enc: the encoding of the file. 913 *@a_result: out parameter. A pointer 914 *the build css object model. 915 * 916 *Parses a css2 stylesheet contained 917 *in a file. 918 * 919 * Returns CR_OK upon succesful completion, an error code otherwise. 920 */ 921enum CRStatus 922cr_om_parser_parse_file (CROMParser * a_this, 923 const guchar * a_file_uri, 924 enum CREncoding a_enc, CRStyleSheet ** a_result) 925{ 926 enum CRStatus status = CR_OK; 927 928 g_return_val_if_fail (a_this && a_file_uri && a_result, 929 CR_BAD_PARAM_ERROR); 930 931 if (!PRIVATE (a_this)->parser) { 932 PRIVATE (a_this)->parser = cr_parser_new_from_file 933 (a_file_uri, a_enc); 934 } 935 936 status = cr_parser_parse_file (PRIVATE (a_this)->parser, 937 a_file_uri, a_enc); 938 939 if (status == CR_OK) { 940 CRStyleSheet *result = NULL; 941 CRStyleSheet **resultptr = NULL; 942 CRDocHandler *sac_handler = NULL; 943 944 cr_parser_get_sac_handler (PRIVATE (a_this)->parser, 945 &sac_handler); 946 g_return_val_if_fail (sac_handler, CR_ERROR); 947 resultptr = &result; 948 status = cr_doc_handler_get_result 949 (sac_handler, (gpointer *) resultptr); 950 g_return_val_if_fail (status == CR_OK, status); 951 if (result) 952 *a_result = result; 953 } 954 955 return status; 956} 957 958/** 959 * cr_om_parser_simply_parse_file: 960 *@a_file_path: the css2 local file path. 961 *@a_enc: the file encoding. 962 *@a_result: out parameter. The returned css stylesheet. 963 *Must be freed by the caller using cr_stylesheet_destroy. 964 * 965 *The simpler method to parse a css2 file. 966 * 967 *Returns CR_OK upon successfull completion, an error code otherwise. 968 *Note that this method uses cr_om_parser_parse_file() so both methods 969 *have the same return values. 970 */ 971enum CRStatus 972cr_om_parser_simply_parse_file (const guchar * a_file_path, 973 enum CREncoding a_enc, 974 CRStyleSheet ** a_result) 975{ 976 CROMParser *parser = NULL; 977 enum CRStatus status = CR_OK; 978 979 parser = cr_om_parser_new (NULL); 980 if (!parser) { 981 cr_utils_trace_info ("Could not allocate om parser"); 982 cr_utils_trace_info ("System may be out of memory"); 983 return CR_ERROR; 984 } 985 986 status = cr_om_parser_parse_file (parser, a_file_path, 987 a_enc, a_result); 988 if (parser) { 989 cr_om_parser_destroy (parser); 990 parser = NULL; 991 } 992 993 return status; 994} 995 996/** 997 * cr_om_parser_parse_paths_to_cascade: 998 *@a_this: the current instance of #CROMParser 999 *@a_author_path: the path to the author stylesheet 1000 *@a_user_path: the path to the user stylesheet 1001 *@a_ua_path: the path to the User Agent stylesheet 1002 *@a_encoding: the encoding of the sheets. 1003 *@a_result: out parameter. The resulting cascade if the parsing 1004 *was okay 1005 * 1006 *Parses three sheets located by their paths and build a cascade 1007 * 1008 *Returns CR_OK upon successful completion, an error code otherwise 1009 */ 1010enum CRStatus 1011cr_om_parser_parse_paths_to_cascade (CROMParser * a_this, 1012 const guchar * a_author_path, 1013 const guchar * a_user_path, 1014 const guchar * a_ua_path, 1015 enum CREncoding a_encoding, 1016 CRCascade ** a_result) 1017{ 1018 enum CRStatus status = CR_OK; 1019 1020 /*0->author sheet, 1->user sheet, 2->UA sheet */ 1021 CRStyleSheet *sheets[3]; 1022 guchar *paths[3]; 1023 CRCascade *result = NULL; 1024 gint i = 0; 1025 1026 g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR); 1027 1028 memset (sheets, 0, sizeof (CRStyleSheet*) * 3); 1029 paths[0] = (guchar *) a_author_path; 1030 paths[1] = (guchar *) a_user_path; 1031 paths[2] = (guchar *) a_ua_path; 1032 1033 for (i = 0; i < 3; i++) { 1034 status = cr_om_parser_parse_file (a_this, paths[i], 1035 a_encoding, &sheets[i]); 1036 if (status != CR_OK) { 1037 if (sheets[i]) { 1038 cr_stylesheet_unref (sheets[i]); 1039 sheets[i] = NULL; 1040 } 1041 continue; 1042 } 1043 } 1044 result = cr_cascade_new (sheets[0], sheets[1], sheets[2]); 1045 if (!result) { 1046 for (i = 0; i < 3; i++) { 1047 cr_stylesheet_unref (sheets[i]); 1048 sheets[i] = 0; 1049 } 1050 return CR_ERROR; 1051 } 1052 *a_result = result; 1053 return CR_OK; 1054} 1055 1056/** 1057 * cr_om_parser_simply_parse_paths_to_cascade: 1058 *@a_author_path: the path to the author stylesheet 1059 *@a_user_path: the path to the user stylesheet 1060 *@a_ua_path: the path to the User Agent stylesheet 1061 *@a_encoding: the encoding of the sheets. 1062 *@a_result: out parameter. The resulting cascade if the parsing 1063 *was okay 1064 * 1065 *Parses three sheets located by their paths and build a cascade 1066 * 1067 *Returns CR_OK upon successful completion, an error code otherwise 1068 */ 1069enum CRStatus 1070cr_om_parser_simply_parse_paths_to_cascade (const guchar * a_author_path, 1071 const guchar * a_user_path, 1072 const guchar * a_ua_path, 1073 enum CREncoding a_encoding, 1074 CRCascade ** a_result) 1075{ 1076 enum CRStatus status = CR_OK; 1077 CROMParser *parser = NULL; 1078 1079 parser = cr_om_parser_new (NULL); 1080 if (!parser) { 1081 cr_utils_trace_info ("could not allocated om parser"); 1082 cr_utils_trace_info ("System may be out of memory"); 1083 return CR_ERROR; 1084 } 1085 status = cr_om_parser_parse_paths_to_cascade (parser, 1086 a_author_path, 1087 a_user_path, 1088 a_ua_path, 1089 a_encoding, a_result); 1090 if (parser) { 1091 cr_om_parser_destroy (parser); 1092 parser = NULL; 1093 } 1094 return status; 1095} 1096 1097/** 1098 * cr_om_parser_destroy: 1099 *@a_this: the current instance of #CROMParser. 1100 * 1101 *Destructor of the #CROMParser. 1102 */ 1103void 1104cr_om_parser_destroy (CROMParser * a_this) 1105{ 1106 g_return_if_fail (a_this && PRIVATE (a_this)); 1107 1108 if (PRIVATE (a_this)->parser) { 1109 cr_parser_destroy (PRIVATE (a_this)->parser); 1110 PRIVATE (a_this)->parser = NULL; 1111 } 1112 1113 if (PRIVATE (a_this)) { 1114 g_free (PRIVATE (a_this)); 1115 PRIVATE (a_this) = NULL; 1116 } 1117 1118 if (a_this) { 1119 g_free (a_this); 1120 a_this = NULL; 1121 } 1122} 1123