Libcroco
|
00001 /* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */ 00002 00003 /* 00004 * This file is part of The Croco Library 00005 * 00006 * This program is free software; you can redistribute it and/or 00007 * modify it under the terms of version 2.1 of the GNU Lesser General Public 00008 * License as published by the Free Software Foundation. 00009 * 00010 * This program is distributed in the hope that it will be useful, 00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 * GNU General Public License for more details. 00014 * 00015 * You should have received a copy of the GNU Lesser General Public License 00016 * along with this program; if not, write to the Free Software 00017 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 00018 * USA 00019 * 00020 * Author: Dodji Seketeli 00021 * See COPYRIGHTS file for copyright information. 00022 */ 00023 00024 #include <string.h> 00025 #include "cr-utils.h" 00026 #include "cr-om-parser.h" 00027 00028 /** 00029 *@CROMParser: 00030 * 00031 *The definition of the CSS Object Model Parser. 00032 *This parser uses (and sits) the SAC api of libcroco defined 00033 *in cr-parser.h and cr-doc-handler.h 00034 */ 00035 00036 struct _CROMParserPriv { 00037 CRParser *parser; 00038 }; 00039 00040 #define PRIVATE(a_this) ((a_this)->priv) 00041 00042 /* 00043 *Forward declaration of a type defined later 00044 *in this file. 00045 */ 00046 struct _ParsingContext; 00047 typedef struct _ParsingContext ParsingContext; 00048 00049 static ParsingContext *new_parsing_context (void); 00050 00051 static void destroy_context (ParsingContext * a_ctxt); 00052 00053 static void unrecoverable_error (CRDocHandler * a_this); 00054 00055 static void error (CRDocHandler * a_this); 00056 00057 static void property (CRDocHandler * a_this, 00058 CRString * a_name, 00059 CRTerm * a_expression, 00060 gboolean a_important); 00061 00062 static void end_selector (CRDocHandler * a_this, 00063 CRSelector * a_selector_list); 00064 00065 static void start_selector (CRDocHandler * a_this, 00066 CRSelector * a_selector_list); 00067 00068 static void start_font_face (CRDocHandler * a_this, 00069 CRParsingLocation *a_location); 00070 00071 static void end_font_face (CRDocHandler * a_this); 00072 00073 static void end_document (CRDocHandler * a_this); 00074 00075 static void start_document (CRDocHandler * a_this); 00076 00077 static void charset (CRDocHandler * a_this, 00078 CRString * a_charset, 00079 CRParsingLocation *a_location); 00080 00081 static void start_page (CRDocHandler * a_this, CRString * a_page, 00082 CRString * a_pseudo_page, 00083 CRParsingLocation *a_location); 00084 00085 static void end_page (CRDocHandler * a_this, CRString * a_page, 00086 CRString * a_pseudo_page); 00087 00088 static void start_media (CRDocHandler * a_this, 00089 GList * a_media_list, 00090 CRParsingLocation *a_location); 00091 00092 static void end_media (CRDocHandler * a_this, 00093 GList * a_media_list); 00094 00095 static void import_style (CRDocHandler * a_this, 00096 GList * a_media_list, 00097 CRString * a_uri, 00098 CRString * a_uri_default_ns, 00099 CRParsingLocation *a_location); 00100 00101 struct _ParsingContext { 00102 CRStyleSheet *stylesheet; 00103 CRStatement *cur_stmt; 00104 CRStatement *cur_media_stmt; 00105 }; 00106 00107 /******************************************** 00108 *Private methods 00109 ********************************************/ 00110 00111 static ParsingContext * 00112 new_parsing_context (void) 00113 { 00114 ParsingContext *result = NULL; 00115 00116 result = g_try_malloc (sizeof (ParsingContext)); 00117 if (!result) { 00118 cr_utils_trace_info ("Out of Memory"); 00119 return NULL; 00120 } 00121 memset (result, 0, sizeof (ParsingContext)); 00122 return result; 00123 } 00124 00125 static void 00126 destroy_context (ParsingContext * a_ctxt) 00127 { 00128 g_return_if_fail (a_ctxt); 00129 00130 if (a_ctxt->stylesheet) { 00131 cr_stylesheet_destroy (a_ctxt->stylesheet); 00132 a_ctxt->stylesheet = NULL; 00133 } 00134 if (a_ctxt->cur_stmt) { 00135 cr_statement_destroy (a_ctxt->cur_stmt); 00136 a_ctxt->cur_stmt = NULL; 00137 } 00138 g_free (a_ctxt); 00139 } 00140 00141 static enum CRStatus 00142 cr_om_parser_init_default_sac_handler (CROMParser * a_this) 00143 { 00144 CRDocHandler *sac_handler = NULL; 00145 gboolean created_handler = FALSE; 00146 enum CRStatus status = CR_OK; 00147 00148 g_return_val_if_fail (a_this && PRIVATE (a_this) 00149 && PRIVATE (a_this)->parser, 00150 CR_BAD_PARAM_ERROR); 00151 00152 status = cr_parser_get_sac_handler (PRIVATE (a_this)->parser, 00153 &sac_handler); 00154 g_return_val_if_fail (status == CR_OK, status); 00155 00156 if (!sac_handler) { 00157 sac_handler = cr_doc_handler_new (); 00158 created_handler = TRUE; 00159 } 00160 00161 /* 00162 *initialyze here the sac handler. 00163 */ 00164 sac_handler->start_document = start_document; 00165 sac_handler->end_document = end_document; 00166 sac_handler->start_selector = start_selector; 00167 sac_handler->end_selector = end_selector; 00168 sac_handler->property = property; 00169 sac_handler->start_font_face = start_font_face; 00170 sac_handler->end_font_face = end_font_face; 00171 sac_handler->error = error; 00172 sac_handler->unrecoverable_error = unrecoverable_error; 00173 sac_handler->charset = charset; 00174 sac_handler->start_page = start_page; 00175 sac_handler->end_page = end_page; 00176 sac_handler->start_media = start_media; 00177 sac_handler->end_media = end_media; 00178 sac_handler->import_style = import_style; 00179 00180 if (created_handler) { 00181 status = cr_parser_set_sac_handler (PRIVATE (a_this)->parser, 00182 sac_handler); 00183 cr_doc_handler_unref (sac_handler); 00184 } 00185 00186 return status; 00187 00188 } 00189 00190 static void 00191 start_document (CRDocHandler * a_this) 00192 { 00193 ParsingContext *ctxt = NULL; 00194 CRStyleSheet *stylesheet = NULL; 00195 00196 g_return_if_fail (a_this); 00197 00198 ctxt = new_parsing_context (); 00199 g_return_if_fail (ctxt); 00200 00201 stylesheet = cr_stylesheet_new (NULL); 00202 ctxt->stylesheet = stylesheet; 00203 cr_doc_handler_set_ctxt (a_this, ctxt); 00204 } 00205 00206 static void 00207 start_font_face (CRDocHandler * a_this, 00208 CRParsingLocation *a_location) 00209 { 00210 enum CRStatus status = CR_OK; 00211 ParsingContext *ctxt = NULL; 00212 ParsingContext **ctxtptr = NULL; 00213 00214 g_return_if_fail (a_this); 00215 00216 g_return_if_fail (a_this); 00217 ctxtptr = &ctxt; 00218 status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr); 00219 g_return_if_fail (status == CR_OK && ctxt); 00220 g_return_if_fail (ctxt->cur_stmt == NULL); 00221 00222 ctxt->cur_stmt = 00223 cr_statement_new_at_font_face_rule (ctxt->stylesheet, NULL); 00224 00225 g_return_if_fail (ctxt->cur_stmt); 00226 } 00227 00228 static void 00229 end_font_face (CRDocHandler * a_this) 00230 { 00231 enum CRStatus status = CR_OK; 00232 ParsingContext *ctxt = NULL; 00233 ParsingContext **ctxtptr = NULL; 00234 CRStatement *stmts = NULL; 00235 00236 g_return_if_fail (a_this); 00237 00238 g_return_if_fail (a_this); 00239 ctxtptr = &ctxt; 00240 status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr); 00241 g_return_if_fail (status == CR_OK && ctxt); 00242 g_return_if_fail 00243 (ctxt->cur_stmt 00244 && ctxt->cur_stmt->type == AT_FONT_FACE_RULE_STMT 00245 && ctxt->stylesheet); 00246 00247 stmts = cr_statement_append (ctxt->stylesheet->statements, 00248 ctxt->cur_stmt); 00249 if (!stmts) 00250 goto error; 00251 00252 ctxt->stylesheet->statements = stmts; 00253 stmts = NULL; 00254 ctxt->cur_stmt = NULL; 00255 00256 return; 00257 00258 error: 00259 00260 if (ctxt->cur_stmt) { 00261 cr_statement_destroy (ctxt->cur_stmt); 00262 ctxt->cur_stmt = NULL; 00263 } 00264 00265 if (!stmts) { 00266 cr_statement_destroy (stmts); 00267 stmts = NULL; 00268 } 00269 } 00270 00271 static void 00272 end_document (CRDocHandler * a_this) 00273 { 00274 enum CRStatus status = CR_OK; 00275 ParsingContext *ctxt = NULL; 00276 ParsingContext **ctxtptr = NULL; 00277 00278 g_return_if_fail (a_this); 00279 ctxtptr = &ctxt; 00280 status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr); 00281 g_return_if_fail (status == CR_OK && ctxt); 00282 00283 if (!ctxt->stylesheet || ctxt->cur_stmt) 00284 goto error; 00285 00286 status = cr_doc_handler_set_result (a_this, ctxt->stylesheet); 00287 g_return_if_fail (status == CR_OK); 00288 00289 ctxt->stylesheet = NULL; 00290 destroy_context (ctxt); 00291 cr_doc_handler_set_ctxt (a_this, NULL); 00292 00293 return; 00294 00295 error: 00296 if (ctxt) { 00297 destroy_context (ctxt); 00298 } 00299 } 00300 00301 static void 00302 charset (CRDocHandler * a_this, CRString * a_charset, 00303 CRParsingLocation *a_location) 00304 { 00305 enum CRStatus status = CR_OK; 00306 CRStatement *stmt = NULL, 00307 *stmt2 = NULL; 00308 CRString *charset = NULL; 00309 00310 ParsingContext *ctxt = NULL; 00311 ParsingContext **ctxtptr = NULL; 00312 00313 g_return_if_fail (a_this); 00314 ctxtptr = &ctxt; 00315 status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr); 00316 g_return_if_fail (status == CR_OK && ctxt); 00317 g_return_if_fail (ctxt->stylesheet); 00318 00319 charset = cr_string_dup (a_charset) ; 00320 stmt = cr_statement_new_at_charset_rule (ctxt->stylesheet, charset); 00321 g_return_if_fail (stmt); 00322 stmt2 = cr_statement_append (ctxt->stylesheet->statements, stmt); 00323 if (!stmt2) { 00324 if (stmt) { 00325 cr_statement_destroy (stmt); 00326 stmt = NULL; 00327 } 00328 if (charset) { 00329 cr_string_destroy (charset); 00330 } 00331 return; 00332 } 00333 ctxt->stylesheet->statements = stmt2; 00334 stmt2 = NULL; 00335 } 00336 00337 static void 00338 start_page (CRDocHandler * a_this, 00339 CRString * a_page, 00340 CRString * a_pseudo, 00341 CRParsingLocation *a_location) 00342 { 00343 enum CRStatus status = CR_OK; 00344 ParsingContext *ctxt = NULL; 00345 ParsingContext **ctxtptr = NULL; 00346 00347 g_return_if_fail (a_this); 00348 ctxtptr = &ctxt; 00349 status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr); 00350 g_return_if_fail (status == CR_OK && ctxt); 00351 g_return_if_fail (ctxt->cur_stmt == NULL); 00352 00353 ctxt->cur_stmt = cr_statement_new_at_page_rule 00354 (ctxt->stylesheet, NULL, NULL, NULL); 00355 if (a_page) { 00356 ctxt->cur_stmt->kind.page_rule->name = 00357 cr_string_dup (a_page) ; 00358 00359 if (!ctxt->cur_stmt->kind.page_rule->name) { 00360 goto error; 00361 } 00362 } 00363 if (a_pseudo) { 00364 ctxt->cur_stmt->kind.page_rule->pseudo = 00365 cr_string_dup (a_pseudo) ; 00366 if (!ctxt->cur_stmt->kind.page_rule->pseudo) { 00367 goto error; 00368 } 00369 } 00370 return; 00371 00372 error: 00373 if (ctxt->cur_stmt) { 00374 cr_statement_destroy (ctxt->cur_stmt); 00375 ctxt->cur_stmt = NULL; 00376 } 00377 } 00378 00379 static void 00380 end_page (CRDocHandler * a_this, 00381 CRString * a_page, 00382 CRString * a_pseudo_page) 00383 { 00384 enum CRStatus status = CR_OK; 00385 ParsingContext *ctxt = NULL; 00386 ParsingContext **ctxtptr = NULL; 00387 CRStatement *stmt = NULL; 00388 00389 (void) a_page; 00390 (void) a_pseudo_page; 00391 00392 g_return_if_fail (a_this); 00393 00394 ctxtptr = &ctxt; 00395 status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr); 00396 00397 g_return_if_fail (status == CR_OK && ctxt); 00398 00399 g_return_if_fail (ctxt->cur_stmt 00400 && ctxt->cur_stmt->type == AT_PAGE_RULE_STMT 00401 && ctxt->stylesheet); 00402 00403 stmt = cr_statement_append (ctxt->stylesheet->statements, 00404 ctxt->cur_stmt); 00405 00406 if (stmt) { 00407 ctxt->stylesheet->statements = stmt; 00408 stmt = NULL; 00409 ctxt->cur_stmt = NULL; 00410 } 00411 00412 if (ctxt->cur_stmt) { 00413 cr_statement_destroy (ctxt->cur_stmt); 00414 ctxt->cur_stmt = NULL; 00415 } 00416 a_page = NULL; /*keep compiler happy */ 00417 a_pseudo_page = NULL; /*keep compiler happy */ 00418 } 00419 00420 static void 00421 start_media (CRDocHandler * a_this, 00422 GList * a_media_list, 00423 CRParsingLocation *a_location) 00424 { 00425 enum CRStatus status = CR_OK; 00426 ParsingContext *ctxt = NULL; 00427 ParsingContext **ctxtptr = NULL; 00428 GList *media_list = NULL; 00429 00430 g_return_if_fail (a_this); 00431 ctxtptr = &ctxt; 00432 status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr); 00433 g_return_if_fail (status == CR_OK && ctxt); 00434 00435 g_return_if_fail (ctxt 00436 && ctxt->cur_stmt == NULL 00437 && ctxt->cur_media_stmt == NULL 00438 && ctxt->stylesheet); 00439 if (a_media_list) { 00440 /*duplicate the media_list */ 00441 media_list = cr_utils_dup_glist_of_cr_string 00442 (a_media_list); 00443 } 00444 ctxt->cur_media_stmt = 00445 cr_statement_new_at_media_rule 00446 (ctxt->stylesheet, NULL, media_list); 00447 00448 } 00449 00450 static void 00451 end_media (CRDocHandler * a_this, GList * a_media_list) 00452 { 00453 enum CRStatus status = CR_OK; 00454 ParsingContext *ctxt = NULL; 00455 ParsingContext **ctxtptr = NULL; 00456 CRStatement *stmts = NULL; 00457 00458 (void) a_media_list; 00459 00460 g_return_if_fail (a_this); 00461 00462 ctxtptr = &ctxt; 00463 status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr); 00464 00465 g_return_if_fail (status == CR_OK && ctxt); 00466 00467 g_return_if_fail (ctxt 00468 && ctxt->cur_media_stmt 00469 && ctxt->cur_media_stmt->type == AT_MEDIA_RULE_STMT 00470 && ctxt->stylesheet); 00471 00472 stmts = cr_statement_append (ctxt->stylesheet->statements, 00473 ctxt->cur_media_stmt); 00474 00475 if (!stmts) { 00476 cr_statement_destroy (ctxt->cur_media_stmt); 00477 ctxt->cur_media_stmt = NULL; 00478 } 00479 00480 ctxt->stylesheet->statements = stmts; 00481 stmts = NULL; 00482 00483 ctxt->cur_stmt = NULL ; 00484 ctxt->cur_media_stmt = NULL ; 00485 a_media_list = NULL; 00486 } 00487 00488 static void 00489 import_style (CRDocHandler * a_this, 00490 GList * a_media_list, 00491 CRString * a_uri, 00492 CRString * a_uri_default_ns, 00493 CRParsingLocation *a_location) 00494 { 00495 enum CRStatus status = CR_OK; 00496 CRString *uri = NULL; 00497 CRStatement *stmt = NULL, 00498 *stmt2 = NULL; 00499 ParsingContext *ctxt = NULL; 00500 ParsingContext **ctxtptr = NULL; 00501 GList *media_list = NULL ; 00502 00503 (void) a_uri_default_ns; 00504 00505 g_return_if_fail (a_this); 00506 00507 ctxtptr = &ctxt; 00508 status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr); 00509 00510 g_return_if_fail (status == CR_OK && ctxt); 00511 00512 g_return_if_fail (ctxt->stylesheet); 00513 00514 uri = cr_string_dup (a_uri) ; 00515 00516 if (a_media_list) 00517 media_list = cr_utils_dup_glist_of_cr_string (a_media_list) ; 00518 00519 stmt = cr_statement_new_at_import_rule 00520 (ctxt->stylesheet, uri, media_list, NULL); 00521 00522 if (!stmt) 00523 goto error; 00524 00525 if (ctxt->cur_stmt) { 00526 stmt2 = cr_statement_append (ctxt->cur_stmt, stmt); 00527 if (!stmt2) 00528 goto error; 00529 ctxt->cur_stmt = stmt2; 00530 stmt2 = NULL; 00531 stmt = NULL; 00532 } else { 00533 stmt2 = cr_statement_append (ctxt->stylesheet->statements, 00534 stmt); 00535 if (!stmt2) 00536 goto error; 00537 ctxt->stylesheet->statements = stmt2; 00538 stmt2 = NULL; 00539 stmt = NULL; 00540 } 00541 00542 return; 00543 00544 error: 00545 if (uri) { 00546 cr_string_destroy (uri); 00547 } 00548 00549 if (stmt) { 00550 cr_statement_destroy (stmt); 00551 stmt = NULL; 00552 } 00553 a_uri_default_ns = NULL; /*keep compiler happy */ 00554 } 00555 00556 static void 00557 start_selector (CRDocHandler * a_this, CRSelector * a_selector_list) 00558 { 00559 enum CRStatus status = CR_OK ; 00560 ParsingContext *ctxt = NULL; 00561 ParsingContext **ctxtptr = NULL; 00562 00563 g_return_if_fail (a_this); 00564 ctxtptr = &ctxt; 00565 status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr); 00566 g_return_if_fail (status == CR_OK && ctxt); 00567 if (ctxt->cur_stmt) { 00568 /*hmm, this should be NULL so free it */ 00569 cr_statement_destroy (ctxt->cur_stmt); 00570 ctxt->cur_stmt = NULL; 00571 } 00572 00573 ctxt->cur_stmt = cr_statement_new_ruleset 00574 (ctxt->stylesheet, a_selector_list, NULL, NULL); 00575 } 00576 00577 static void 00578 end_selector (CRDocHandler * a_this, CRSelector * a_selector_list) 00579 { 00580 enum CRStatus status = CR_OK; 00581 ParsingContext *ctxt = NULL; 00582 ParsingContext **ctxtptr = NULL; 00583 00584 (void) a_selector_list; 00585 00586 g_return_if_fail (a_this); 00587 00588 ctxtptr = &ctxt; 00589 status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr); 00590 00591 g_return_if_fail (status == CR_OK && ctxt); 00592 00593 g_return_if_fail (ctxt->cur_stmt && ctxt->stylesheet); 00594 00595 if (ctxt->cur_stmt) { 00596 CRStatement *stmts = NULL; 00597 00598 if (ctxt->cur_media_stmt) { 00599 CRAtMediaRule *media_rule = NULL; 00600 00601 media_rule = ctxt->cur_media_stmt->kind.media_rule; 00602 00603 stmts = cr_statement_append 00604 (media_rule->rulesets, ctxt->cur_stmt); 00605 00606 if (!stmts) { 00607 cr_utils_trace_info 00608 ("Could not append a new statement"); 00609 cr_statement_destroy (media_rule->rulesets); 00610 ctxt->cur_media_stmt-> 00611 kind.media_rule->rulesets = NULL; 00612 return; 00613 } 00614 media_rule->rulesets = stmts; 00615 ctxt->cur_stmt = NULL; 00616 } else { 00617 stmts = cr_statement_append 00618 (ctxt->stylesheet->statements, 00619 ctxt->cur_stmt); 00620 if (!stmts) { 00621 cr_utils_trace_info 00622 ("Could not append a new statement"); 00623 cr_statement_destroy (ctxt->cur_stmt); 00624 ctxt->cur_stmt = NULL; 00625 return; 00626 } 00627 ctxt->stylesheet->statements = stmts; 00628 ctxt->cur_stmt = NULL; 00629 } 00630 00631 } 00632 00633 a_selector_list = NULL; /*keep compiler happy */ 00634 } 00635 00636 static void 00637 property (CRDocHandler * a_this, 00638 CRString * a_name, 00639 CRTerm * a_expression, 00640 gboolean a_important) 00641 { 00642 enum CRStatus status = CR_OK; 00643 ParsingContext *ctxt = NULL; 00644 ParsingContext **ctxtptr = NULL; 00645 CRDeclaration *decl = NULL, 00646 *decl2 = NULL; 00647 CRString *str = NULL; 00648 00649 g_return_if_fail (a_this); 00650 ctxtptr = &ctxt; 00651 status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr); 00652 g_return_if_fail (status == CR_OK && ctxt); 00653 00654 /* 00655 *make sure a current ruleset statement has been allocated 00656 *already. 00657 */ 00658 g_return_if_fail 00659 (ctxt->cur_stmt 00660 && 00661 (ctxt->cur_stmt->type == RULESET_STMT 00662 || ctxt->cur_stmt->type == AT_FONT_FACE_RULE_STMT 00663 || ctxt->cur_stmt->type == AT_PAGE_RULE_STMT)); 00664 00665 if (a_name) { 00666 str = cr_string_dup (a_name); 00667 g_return_if_fail (str); 00668 } 00669 00670 /*instanciates a new declaration */ 00671 decl = cr_declaration_new (ctxt->cur_stmt, str, a_expression); 00672 g_return_if_fail (decl); 00673 str = NULL; 00674 decl->important = a_important; 00675 /* 00676 *add the new declaration to the current statement 00677 *being build. 00678 */ 00679 switch (ctxt->cur_stmt->type) { 00680 case RULESET_STMT: 00681 decl2 = cr_declaration_append 00682 (ctxt->cur_stmt->kind.ruleset->decl_list, decl); 00683 if (!decl2) { 00684 cr_declaration_destroy (decl); 00685 cr_utils_trace_info 00686 ("Could not append decl to ruleset"); 00687 goto error; 00688 } 00689 ctxt->cur_stmt->kind.ruleset->decl_list = decl2; 00690 decl = NULL; 00691 decl2 = NULL; 00692 break; 00693 00694 case AT_FONT_FACE_RULE_STMT: 00695 decl2 = cr_declaration_append 00696 (ctxt->cur_stmt->kind.font_face_rule->decl_list, 00697 decl); 00698 if (!decl2) { 00699 cr_declaration_destroy (decl); 00700 cr_utils_trace_info 00701 ("Could not append decl to ruleset"); 00702 goto error; 00703 } 00704 ctxt->cur_stmt->kind.font_face_rule->decl_list = decl2; 00705 decl = NULL; 00706 decl2 = NULL; 00707 break; 00708 case AT_PAGE_RULE_STMT: 00709 decl2 = cr_declaration_append 00710 (ctxt->cur_stmt->kind.page_rule->decl_list, decl); 00711 if (!decl2) { 00712 cr_declaration_destroy (decl); 00713 cr_utils_trace_info 00714 ("Could not append decl to ruleset"); 00715 goto error; 00716 } 00717 ctxt->cur_stmt->kind.page_rule->decl_list = decl2; 00718 decl = NULL; 00719 decl2 = NULL; 00720 break; 00721 00722 default: 00723 goto error; 00724 break; 00725 } 00726 00727 return; 00728 00729 error: 00730 if (str) { 00731 g_free (str); 00732 str = NULL; 00733 } 00734 00735 if (decl) { 00736 cr_declaration_destroy (decl); 00737 decl = NULL; 00738 } 00739 } 00740 00741 static void 00742 error (CRDocHandler * a_this) 00743 { 00744 enum CRStatus status = CR_OK; 00745 ParsingContext *ctxt = NULL; 00746 ParsingContext **ctxtptr = NULL; 00747 00748 g_return_if_fail (a_this); 00749 ctxtptr = &ctxt; 00750 status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr); 00751 g_return_if_fail (status == CR_OK && ctxt); 00752 00753 if (ctxt->cur_stmt) { 00754 cr_statement_destroy (ctxt->cur_stmt); 00755 ctxt->cur_stmt = NULL; 00756 } 00757 } 00758 00759 static void 00760 unrecoverable_error (CRDocHandler * a_this) 00761 { 00762 enum CRStatus status = CR_OK; 00763 ParsingContext *ctxt = NULL; 00764 ParsingContext **ctxtptr = NULL; 00765 00766 ctxtptr = &ctxt; 00767 status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr); 00768 g_return_if_fail (status == CR_OK); 00769 00770 if (ctxt) { 00771 if (ctxt->stylesheet) { 00772 status = cr_doc_handler_set_result 00773 (a_this, ctxt->stylesheet); 00774 g_return_if_fail (status == CR_OK); 00775 } 00776 g_free (ctxt); 00777 cr_doc_handler_set_ctxt (a_this, NULL); 00778 } 00779 } 00780 00781 /******************************************** 00782 *Public methods 00783 ********************************************/ 00784 00785 /** 00786 * cr_om_parser_new: 00787 *@a_input: the input stream. 00788 * 00789 *Constructor of the CROMParser. 00790 *Returns the newly built instance of #CROMParser. 00791 */ 00792 CROMParser * 00793 cr_om_parser_new (CRInput * a_input) 00794 { 00795 CROMParser *result = NULL; 00796 enum CRStatus status = CR_OK; 00797 00798 result = g_try_malloc (sizeof (CROMParser)); 00799 00800 if (!result) { 00801 cr_utils_trace_info ("Out of memory"); 00802 return NULL; 00803 } 00804 00805 memset (result, 0, sizeof (CROMParser)); 00806 PRIVATE (result) = g_try_malloc (sizeof (CROMParserPriv)); 00807 00808 if (!PRIVATE (result)) { 00809 cr_utils_trace_info ("Out of memory"); 00810 goto error; 00811 } 00812 00813 memset (PRIVATE (result), 0, sizeof (CROMParserPriv)); 00814 00815 PRIVATE (result)->parser = cr_parser_new_from_input (a_input); 00816 00817 if (!PRIVATE (result)->parser) { 00818 cr_utils_trace_info ("parsing instantiation failed"); 00819 goto error; 00820 } 00821 00822 status = cr_om_parser_init_default_sac_handler (result); 00823 00824 if (status != CR_OK) { 00825 goto error; 00826 } 00827 00828 return result; 00829 00830 error: 00831 00832 if (result) { 00833 cr_om_parser_destroy (result); 00834 } 00835 00836 return NULL; 00837 } 00838 00839 /** 00840 * cr_om_parser_parse_buf: 00841 *@a_this: the current instance of #CROMParser. 00842 *@a_buf: the in memory buffer to parse. 00843 *@a_len: the length of the in memory buffer in number of bytes. 00844 *@a_enc: the encoding of the in memory buffer. 00845 *@a_result: out parameter the resulting style sheet 00846 * 00847 *Parses the content of an in memory buffer. 00848 * 00849 *Returns CR_OK upon successfull completion, an error code otherwise. 00850 */ 00851 enum CRStatus 00852 cr_om_parser_parse_buf (CROMParser * a_this, 00853 const guchar * a_buf, 00854 gulong a_len, 00855 enum CREncoding a_enc, CRStyleSheet ** a_result) 00856 { 00857 00858 enum CRStatus status = CR_OK; 00859 00860 g_return_val_if_fail (a_this && a_result, CR_BAD_PARAM_ERROR); 00861 00862 if (!PRIVATE (a_this)->parser) { 00863 PRIVATE (a_this)->parser = cr_parser_new (NULL); 00864 } 00865 00866 status = cr_parser_parse_buf (PRIVATE (a_this)->parser, 00867 a_buf, a_len, a_enc); 00868 00869 if (status == CR_OK) { 00870 CRStyleSheet *result = NULL; 00871 CRStyleSheet **resultptr = NULL; 00872 CRDocHandler *sac_handler = NULL; 00873 00874 cr_parser_get_sac_handler (PRIVATE (a_this)->parser, 00875 &sac_handler); 00876 g_return_val_if_fail (sac_handler, CR_ERROR); 00877 resultptr = &result; 00878 status = cr_doc_handler_get_result (sac_handler, 00879 (gpointer *) resultptr); 00880 g_return_val_if_fail (status == CR_OK, status); 00881 00882 if (result) 00883 *a_result = result; 00884 } 00885 00886 return status; 00887 } 00888 00889 /** 00890 * cr_om_parser_simply_parse_buf: 00891 *@a_buf: the css2 in memory buffer. 00892 *@a_len: the length of the in memory buffer. 00893 *@a_enc: the encoding of the in memory buffer. 00894 *@a_result: out parameter. The resulting css2 style sheet. 00895 * 00896 *The simpler way to parse an in memory css2 buffer. 00897 * 00898 *Returns CR_OK upon successfull completion, an error code otherwise. 00899 */ 00900 enum CRStatus 00901 cr_om_parser_simply_parse_buf (const guchar * a_buf, 00902 gulong a_len, 00903 enum CREncoding a_enc, 00904 CRStyleSheet ** a_result) 00905 { 00906 CROMParser *parser = NULL; 00907 enum CRStatus status = CR_OK; 00908 00909 parser = cr_om_parser_new (NULL); 00910 if (!parser) { 00911 cr_utils_trace_info ("Could not create om parser"); 00912 cr_utils_trace_info ("System possibly out of memory"); 00913 return CR_ERROR; 00914 } 00915 00916 status = cr_om_parser_parse_buf (parser, a_buf, a_len, 00917 a_enc, a_result); 00918 00919 if (parser) { 00920 cr_om_parser_destroy (parser); 00921 parser = NULL; 00922 } 00923 00924 return status; 00925 } 00926 00927 /** 00928 * cr_om_parser_parse_file: 00929 *@a_this: the current instance of the cssom parser. 00930 *@a_file_uri: the uri of the file. 00931 *(only local file paths are suppported so far) 00932 *@a_enc: the encoding of the file. 00933 *@a_result: out parameter. A pointer 00934 *the build css object model. 00935 * 00936 *Parses a css2 stylesheet contained 00937 *in a file. 00938 * 00939 * Returns CR_OK upon succesful completion, an error code otherwise. 00940 */ 00941 enum CRStatus 00942 cr_om_parser_parse_file (CROMParser * a_this, 00943 const guchar * a_file_uri, 00944 enum CREncoding a_enc, CRStyleSheet ** a_result) 00945 { 00946 enum CRStatus status = CR_OK; 00947 00948 g_return_val_if_fail (a_this && a_file_uri && a_result, 00949 CR_BAD_PARAM_ERROR); 00950 00951 if (!PRIVATE (a_this)->parser) { 00952 PRIVATE (a_this)->parser = cr_parser_new_from_file 00953 (a_file_uri, a_enc); 00954 } 00955 00956 status = cr_parser_parse_file (PRIVATE (a_this)->parser, 00957 a_file_uri, a_enc); 00958 00959 if (status == CR_OK) { 00960 CRStyleSheet *result = NULL; 00961 CRStyleSheet **resultptr = NULL; 00962 CRDocHandler *sac_handler = NULL; 00963 00964 cr_parser_get_sac_handler (PRIVATE (a_this)->parser, 00965 &sac_handler); 00966 g_return_val_if_fail (sac_handler, CR_ERROR); 00967 resultptr = &result; 00968 status = cr_doc_handler_get_result 00969 (sac_handler, (gpointer *) resultptr); 00970 g_return_val_if_fail (status == CR_OK, status); 00971 if (result) 00972 *a_result = result; 00973 } 00974 00975 return status; 00976 } 00977 00978 /** 00979 * cr_om_parser_simply_parse_file: 00980 *@a_file_path: the css2 local file path. 00981 *@a_enc: the file encoding. 00982 *@a_result: out parameter. The returned css stylesheet. 00983 *Must be freed by the caller using cr_stylesheet_destroy. 00984 * 00985 *The simpler method to parse a css2 file. 00986 * 00987 *Returns CR_OK upon successfull completion, an error code otherwise. 00988 *Note that this method uses cr_om_parser_parse_file() so both methods 00989 *have the same return values. 00990 */ 00991 enum CRStatus 00992 cr_om_parser_simply_parse_file (const guchar * a_file_path, 00993 enum CREncoding a_enc, 00994 CRStyleSheet ** a_result) 00995 { 00996 CROMParser *parser = NULL; 00997 enum CRStatus status = CR_OK; 00998 00999 parser = cr_om_parser_new (NULL); 01000 if (!parser) { 01001 cr_utils_trace_info ("Could not allocate om parser"); 01002 cr_utils_trace_info ("System may be out of memory"); 01003 return CR_ERROR; 01004 } 01005 01006 status = cr_om_parser_parse_file (parser, a_file_path, 01007 a_enc, a_result); 01008 if (parser) { 01009 cr_om_parser_destroy (parser); 01010 parser = NULL; 01011 } 01012 01013 return status; 01014 } 01015 01016 /** 01017 * cr_om_parser_parse_paths_to_cascade: 01018 *@a_this: the current instance of #CROMParser 01019 *@a_author_path: the path to the author stylesheet 01020 *@a_user_path: the path to the user stylesheet 01021 *@a_ua_path: the path to the User Agent stylesheet 01022 *@a_encoding: the encoding of the sheets. 01023 *@a_result: out parameter. The resulting cascade if the parsing 01024 *was okay 01025 * 01026 *Parses three sheets located by their paths and build a cascade 01027 * 01028 *Returns CR_OK upon successful completion, an error code otherwise 01029 */ 01030 enum CRStatus 01031 cr_om_parser_parse_paths_to_cascade (CROMParser * a_this, 01032 const guchar * a_author_path, 01033 const guchar * a_user_path, 01034 const guchar * a_ua_path, 01035 enum CREncoding a_encoding, 01036 CRCascade ** a_result) 01037 { 01038 enum CRStatus status = CR_OK; 01039 01040 /*0->author sheet, 1->user sheet, 2->UA sheet */ 01041 CRStyleSheet *sheets[3]; 01042 guchar *paths[3]; 01043 CRCascade *result = NULL; 01044 gint i = 0; 01045 01046 g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR); 01047 01048 memset (sheets, 0, sizeof (CRStyleSheet*) * 3); 01049 paths[0] = (guchar *) a_author_path; 01050 paths[1] = (guchar *) a_user_path; 01051 paths[2] = (guchar *) a_ua_path; 01052 01053 for (i = 0; i < 3; i++) { 01054 status = cr_om_parser_parse_file (a_this, paths[i], 01055 a_encoding, &sheets[i]); 01056 if (status != CR_OK) { 01057 if (sheets[i]) { 01058 cr_stylesheet_unref (sheets[i]); 01059 sheets[i] = NULL; 01060 } 01061 continue; 01062 } 01063 } 01064 result = cr_cascade_new (sheets[0], sheets[1], sheets[2]); 01065 if (!result) { 01066 for (i = 0; i < 3; i++) { 01067 cr_stylesheet_unref (sheets[i]); 01068 sheets[i] = 0; 01069 } 01070 return CR_ERROR; 01071 } 01072 *a_result = result; 01073 return CR_OK; 01074 } 01075 01076 /** 01077 * cr_om_parser_simply_parse_paths_to_cascade: 01078 *@a_author_path: the path to the author stylesheet 01079 *@a_user_path: the path to the user stylesheet 01080 *@a_ua_path: the path to the User Agent stylesheet 01081 *@a_encoding: the encoding of the sheets. 01082 *@a_result: out parameter. The resulting cascade if the parsing 01083 *was okay 01084 * 01085 *Parses three sheets located by their paths and build a cascade 01086 * 01087 *Returns CR_OK upon successful completion, an error code otherwise 01088 */ 01089 enum CRStatus 01090 cr_om_parser_simply_parse_paths_to_cascade (const guchar * a_author_path, 01091 const guchar * a_user_path, 01092 const guchar * a_ua_path, 01093 enum CREncoding a_encoding, 01094 CRCascade ** a_result) 01095 { 01096 enum CRStatus status = CR_OK; 01097 CROMParser *parser = NULL; 01098 01099 parser = cr_om_parser_new (NULL); 01100 if (!parser) { 01101 cr_utils_trace_info ("could not allocated om parser"); 01102 cr_utils_trace_info ("System may be out of memory"); 01103 return CR_ERROR; 01104 } 01105 status = cr_om_parser_parse_paths_to_cascade (parser, 01106 a_author_path, 01107 a_user_path, 01108 a_ua_path, 01109 a_encoding, a_result); 01110 if (parser) { 01111 cr_om_parser_destroy (parser); 01112 parser = NULL; 01113 } 01114 return status; 01115 } 01116 01117 /** 01118 * cr_om_parser_destroy: 01119 *@a_this: the current instance of #CROMParser. 01120 * 01121 *Destructor of the #CROMParser. 01122 */ 01123 void 01124 cr_om_parser_destroy (CROMParser * a_this) 01125 { 01126 g_return_if_fail (a_this && PRIVATE (a_this)); 01127 01128 if (PRIVATE (a_this)->parser) { 01129 cr_parser_destroy (PRIVATE (a_this)->parser); 01130 PRIVATE (a_this)->parser = NULL; 01131 } 01132 01133 if (PRIVATE (a_this)) { 01134 g_free (PRIVATE (a_this)); 01135 PRIVATE (a_this) = NULL; 01136 } 01137 01138 if (a_this) { 01139 g_free (a_this); 01140 a_this = NULL; 01141 } 01142 }