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 g_return_if_fail (a_this); 00390 ctxtptr = &ctxt; 00391 status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr); 00392 g_return_if_fail (status == CR_OK && ctxt); 00393 g_return_if_fail (ctxt->cur_stmt 00394 && ctxt->cur_stmt->type == AT_PAGE_RULE_STMT 00395 && ctxt->stylesheet); 00396 00397 stmt = cr_statement_append (ctxt->stylesheet->statements, 00398 ctxt->cur_stmt); 00399 00400 if (stmt) { 00401 ctxt->stylesheet->statements = stmt; 00402 stmt = NULL; 00403 ctxt->cur_stmt = NULL; 00404 } 00405 00406 if (ctxt->cur_stmt) { 00407 cr_statement_destroy (ctxt->cur_stmt); 00408 ctxt->cur_stmt = NULL; 00409 } 00410 a_page = NULL; /*keep compiler happy */ 00411 a_pseudo_page = NULL; /*keep compiler happy */ 00412 } 00413 00414 static void 00415 start_media (CRDocHandler * a_this, 00416 GList * a_media_list, 00417 CRParsingLocation *a_location) 00418 { 00419 enum CRStatus status = CR_OK; 00420 ParsingContext *ctxt = NULL; 00421 ParsingContext **ctxtptr = NULL; 00422 GList *media_list = NULL; 00423 00424 g_return_if_fail (a_this); 00425 ctxtptr = &ctxt; 00426 status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr); 00427 g_return_if_fail (status == CR_OK && ctxt); 00428 00429 g_return_if_fail (ctxt 00430 && ctxt->cur_stmt == NULL 00431 && ctxt->cur_media_stmt == NULL 00432 && ctxt->stylesheet); 00433 if (a_media_list) { 00434 /*duplicate the media_list */ 00435 media_list = cr_utils_dup_glist_of_cr_string 00436 (a_media_list); 00437 } 00438 ctxt->cur_media_stmt = 00439 cr_statement_new_at_media_rule 00440 (ctxt->stylesheet, NULL, media_list); 00441 00442 } 00443 00444 static void 00445 end_media (CRDocHandler * a_this, GList * a_media_list) 00446 { 00447 enum CRStatus status = CR_OK; 00448 ParsingContext *ctxt = NULL; 00449 ParsingContext **ctxtptr = NULL; 00450 CRStatement *stmts = NULL; 00451 00452 g_return_if_fail (a_this); 00453 ctxtptr = &ctxt; 00454 status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr); 00455 g_return_if_fail (status == CR_OK && ctxt); 00456 g_return_if_fail (ctxt 00457 && ctxt->cur_media_stmt 00458 && ctxt->cur_media_stmt->type == AT_MEDIA_RULE_STMT 00459 && ctxt->stylesheet); 00460 00461 stmts = cr_statement_append (ctxt->stylesheet->statements, 00462 ctxt->cur_media_stmt); 00463 if (!stmts) { 00464 cr_statement_destroy (ctxt->cur_media_stmt); 00465 ctxt->cur_media_stmt = NULL; 00466 } 00467 00468 ctxt->stylesheet->statements = stmts; 00469 stmts = NULL; 00470 00471 ctxt->cur_stmt = NULL ; 00472 ctxt->cur_media_stmt = NULL ; 00473 a_media_list = NULL; 00474 } 00475 00476 static void 00477 import_style (CRDocHandler * a_this, 00478 GList * a_media_list, 00479 CRString * a_uri, 00480 CRString * a_uri_default_ns, 00481 CRParsingLocation *a_location) 00482 { 00483 enum CRStatus status = CR_OK; 00484 CRString *uri = NULL; 00485 CRStatement *stmt = NULL, 00486 *stmt2 = NULL; 00487 ParsingContext *ctxt = NULL; 00488 ParsingContext **ctxtptr = NULL; 00489 GList *media_list = NULL ; 00490 00491 g_return_if_fail (a_this); 00492 ctxtptr = &ctxt; 00493 status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr); 00494 g_return_if_fail (status == CR_OK && ctxt); 00495 g_return_if_fail (ctxt->stylesheet); 00496 00497 uri = cr_string_dup (a_uri) ; 00498 if (a_media_list) 00499 media_list = cr_utils_dup_glist_of_cr_string (a_media_list) ; 00500 stmt = cr_statement_new_at_import_rule 00501 (ctxt->stylesheet, uri, media_list, NULL); 00502 if (!stmt) 00503 goto error; 00504 00505 if (ctxt->cur_stmt) { 00506 stmt2 = cr_statement_append (ctxt->cur_stmt, stmt); 00507 if (!stmt2) 00508 goto error; 00509 ctxt->cur_stmt = stmt2; 00510 stmt2 = NULL; 00511 stmt = NULL; 00512 } else { 00513 stmt2 = cr_statement_append (ctxt->stylesheet->statements, 00514 stmt); 00515 if (!stmt2) 00516 goto error; 00517 ctxt->stylesheet->statements = stmt2; 00518 stmt2 = NULL; 00519 stmt = NULL; 00520 } 00521 00522 return; 00523 00524 error: 00525 if (uri) { 00526 cr_string_destroy (uri); 00527 } 00528 00529 if (stmt) { 00530 cr_statement_destroy (stmt); 00531 stmt = NULL; 00532 } 00533 a_uri_default_ns = NULL; /*keep compiler happy */ 00534 } 00535 00536 static void 00537 start_selector (CRDocHandler * a_this, CRSelector * a_selector_list) 00538 { 00539 enum CRStatus status = CR_OK ; 00540 ParsingContext *ctxt = NULL; 00541 ParsingContext **ctxtptr = NULL; 00542 00543 g_return_if_fail (a_this); 00544 ctxtptr = &ctxt; 00545 status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr); 00546 g_return_if_fail (status == CR_OK && ctxt); 00547 if (ctxt->cur_stmt) { 00548 /*hmm, this should be NULL so free it */ 00549 cr_statement_destroy (ctxt->cur_stmt); 00550 ctxt->cur_stmt = NULL; 00551 } 00552 00553 ctxt->cur_stmt = cr_statement_new_ruleset 00554 (ctxt->stylesheet, a_selector_list, NULL, NULL); 00555 } 00556 00557 static void 00558 end_selector (CRDocHandler * a_this, CRSelector * a_selector_list) 00559 { 00560 enum CRStatus status = CR_OK; 00561 ParsingContext *ctxt = NULL; 00562 ParsingContext **ctxtptr = NULL; 00563 00564 g_return_if_fail (a_this); 00565 ctxtptr = &ctxt; 00566 status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr); 00567 g_return_if_fail (status == CR_OK && ctxt); 00568 g_return_if_fail (ctxt->cur_stmt && ctxt->stylesheet); 00569 00570 if (ctxt->cur_stmt) { 00571 CRStatement *stmts = NULL; 00572 00573 if (ctxt->cur_media_stmt) { 00574 CRAtMediaRule *media_rule = NULL; 00575 00576 media_rule = ctxt->cur_media_stmt->kind.media_rule; 00577 00578 stmts = cr_statement_append 00579 (media_rule->rulesets, ctxt->cur_stmt); 00580 00581 if (!stmts) { 00582 cr_utils_trace_info 00583 ("Could not append a new statement"); 00584 cr_statement_destroy (media_rule->rulesets); 00585 ctxt->cur_media_stmt-> 00586 kind.media_rule->rulesets = NULL; 00587 return; 00588 } 00589 media_rule->rulesets = stmts; 00590 ctxt->cur_stmt = NULL; 00591 } else { 00592 stmts = cr_statement_append 00593 (ctxt->stylesheet->statements, 00594 ctxt->cur_stmt); 00595 if (!stmts) { 00596 cr_utils_trace_info 00597 ("Could not append a new statement"); 00598 cr_statement_destroy (ctxt->cur_stmt); 00599 ctxt->cur_stmt = NULL; 00600 return; 00601 } 00602 ctxt->stylesheet->statements = stmts; 00603 ctxt->cur_stmt = NULL; 00604 } 00605 00606 } 00607 a_selector_list = NULL; /*keep compiler happy */ 00608 } 00609 00610 static void 00611 property (CRDocHandler * a_this, 00612 CRString * a_name, 00613 CRTerm * a_expression, 00614 gboolean a_important) 00615 { 00616 enum CRStatus status = CR_OK; 00617 ParsingContext *ctxt = NULL; 00618 ParsingContext **ctxtptr = NULL; 00619 CRDeclaration *decl = NULL, 00620 *decl2 = NULL; 00621 CRString *str = NULL; 00622 00623 g_return_if_fail (a_this); 00624 ctxtptr = &ctxt; 00625 status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr); 00626 g_return_if_fail (status == CR_OK && ctxt); 00627 00628 /* 00629 *make sure a current ruleset statement has been allocated 00630 *already. 00631 */ 00632 g_return_if_fail 00633 (ctxt->cur_stmt 00634 && 00635 (ctxt->cur_stmt->type == RULESET_STMT 00636 || ctxt->cur_stmt->type == AT_FONT_FACE_RULE_STMT 00637 || ctxt->cur_stmt->type == AT_PAGE_RULE_STMT)); 00638 00639 if (a_name) { 00640 str = cr_string_dup (a_name); 00641 g_return_if_fail (str); 00642 } 00643 00644 /*instanciates a new declaration */ 00645 decl = cr_declaration_new (ctxt->cur_stmt, str, a_expression); 00646 g_return_if_fail (decl); 00647 str = NULL; 00648 decl->important = a_important; 00649 /* 00650 *add the new declaration to the current statement 00651 *being build. 00652 */ 00653 switch (ctxt->cur_stmt->type) { 00654 case RULESET_STMT: 00655 decl2 = cr_declaration_append 00656 (ctxt->cur_stmt->kind.ruleset->decl_list, decl); 00657 if (!decl2) { 00658 cr_declaration_destroy (decl); 00659 cr_utils_trace_info 00660 ("Could not append decl to ruleset"); 00661 goto error; 00662 } 00663 ctxt->cur_stmt->kind.ruleset->decl_list = decl2; 00664 decl = NULL; 00665 decl2 = NULL; 00666 break; 00667 00668 case AT_FONT_FACE_RULE_STMT: 00669 decl2 = cr_declaration_append 00670 (ctxt->cur_stmt->kind.font_face_rule->decl_list, 00671 decl); 00672 if (!decl2) { 00673 cr_declaration_destroy (decl); 00674 cr_utils_trace_info 00675 ("Could not append decl to ruleset"); 00676 goto error; 00677 } 00678 ctxt->cur_stmt->kind.font_face_rule->decl_list = decl2; 00679 decl = NULL; 00680 decl2 = NULL; 00681 break; 00682 case AT_PAGE_RULE_STMT: 00683 decl2 = cr_declaration_append 00684 (ctxt->cur_stmt->kind.page_rule->decl_list, decl); 00685 if (!decl2) { 00686 cr_declaration_destroy (decl); 00687 cr_utils_trace_info 00688 ("Could not append decl to ruleset"); 00689 goto error; 00690 } 00691 ctxt->cur_stmt->kind.page_rule->decl_list = decl2; 00692 decl = NULL; 00693 decl2 = NULL; 00694 break; 00695 00696 default: 00697 goto error; 00698 break; 00699 } 00700 00701 return; 00702 00703 error: 00704 if (str) { 00705 g_free (str); 00706 str = NULL; 00707 } 00708 00709 if (decl) { 00710 cr_declaration_destroy (decl); 00711 decl = NULL; 00712 } 00713 } 00714 00715 static void 00716 error (CRDocHandler * a_this) 00717 { 00718 enum CRStatus status = CR_OK; 00719 ParsingContext *ctxt = NULL; 00720 ParsingContext **ctxtptr = NULL; 00721 00722 g_return_if_fail (a_this); 00723 ctxtptr = &ctxt; 00724 status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr); 00725 g_return_if_fail (status == CR_OK && ctxt); 00726 00727 if (ctxt->cur_stmt) { 00728 cr_statement_destroy (ctxt->cur_stmt); 00729 ctxt->cur_stmt = NULL; 00730 } 00731 } 00732 00733 static void 00734 unrecoverable_error (CRDocHandler * a_this) 00735 { 00736 enum CRStatus status = CR_OK; 00737 ParsingContext *ctxt = NULL; 00738 ParsingContext **ctxtptr = NULL; 00739 00740 ctxtptr = &ctxt; 00741 status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr); 00742 g_return_if_fail (status == CR_OK); 00743 00744 if (ctxt) { 00745 if (ctxt->stylesheet) { 00746 status = cr_doc_handler_set_result 00747 (a_this, ctxt->stylesheet); 00748 g_return_if_fail (status == CR_OK); 00749 } 00750 g_free (ctxt); 00751 cr_doc_handler_set_ctxt (a_this, NULL); 00752 } 00753 } 00754 00755 /******************************************** 00756 *Public methods 00757 ********************************************/ 00758 00759 /** 00760 * cr_om_parser_new: 00761 *@a_input: the input stream. 00762 * 00763 *Constructor of the CROMParser. 00764 *Returns the newly built instance of #CROMParser. 00765 */ 00766 CROMParser * 00767 cr_om_parser_new (CRInput * a_input) 00768 { 00769 CROMParser *result = NULL; 00770 enum CRStatus status = CR_OK; 00771 00772 result = g_try_malloc (sizeof (CROMParser)); 00773 00774 if (!result) { 00775 cr_utils_trace_info ("Out of memory"); 00776 return NULL; 00777 } 00778 00779 memset (result, 0, sizeof (CROMParser)); 00780 PRIVATE (result) = g_try_malloc (sizeof (CROMParserPriv)); 00781 00782 if (!PRIVATE (result)) { 00783 cr_utils_trace_info ("Out of memory"); 00784 goto error; 00785 } 00786 00787 memset (PRIVATE (result), 0, sizeof (CROMParserPriv)); 00788 00789 PRIVATE (result)->parser = cr_parser_new_from_input (a_input); 00790 00791 if (!PRIVATE (result)->parser) { 00792 cr_utils_trace_info ("parsing instanciation failed"); 00793 goto error; 00794 } 00795 00796 status = cr_om_parser_init_default_sac_handler (result); 00797 00798 if (status != CR_OK) { 00799 goto error; 00800 } 00801 00802 return result; 00803 00804 error: 00805 00806 if (result) { 00807 cr_om_parser_destroy (result); 00808 } 00809 00810 return NULL; 00811 } 00812 00813 /** 00814 * cr_om_parser_parse_buf: 00815 *@a_this: the current instance of #CROMParser. 00816 *@a_buf: the in memory buffer to parse. 00817 *@a_len: the length of the in memory buffer in number of bytes. 00818 *@a_enc: the encoding of the in memory buffer. 00819 *@a_result: out parameter the resulting style sheet 00820 * 00821 *Parses the content of an in memory buffer. 00822 * 00823 *Returns CR_OK upon successfull completion, an error code otherwise. 00824 */ 00825 enum CRStatus 00826 cr_om_parser_parse_buf (CROMParser * a_this, 00827 const guchar * a_buf, 00828 gulong a_len, 00829 enum CREncoding a_enc, CRStyleSheet ** a_result) 00830 { 00831 00832 enum CRStatus status = CR_OK; 00833 00834 g_return_val_if_fail (a_this && a_result, CR_BAD_PARAM_ERROR); 00835 00836 if (!PRIVATE (a_this)->parser) { 00837 PRIVATE (a_this)->parser = cr_parser_new (NULL); 00838 } 00839 00840 status = cr_parser_parse_buf (PRIVATE (a_this)->parser, 00841 a_buf, a_len, a_enc); 00842 00843 if (status == CR_OK) { 00844 CRStyleSheet *result = NULL; 00845 CRStyleSheet **resultptr = NULL; 00846 CRDocHandler *sac_handler = NULL; 00847 00848 cr_parser_get_sac_handler (PRIVATE (a_this)->parser, 00849 &sac_handler); 00850 g_return_val_if_fail (sac_handler, CR_ERROR); 00851 resultptr = &result; 00852 status = cr_doc_handler_get_result (sac_handler, 00853 (gpointer *) resultptr); 00854 g_return_val_if_fail (status == CR_OK, status); 00855 00856 if (result) 00857 *a_result = result; 00858 } 00859 00860 return status; 00861 } 00862 00863 /** 00864 * cr_om_parser_simply_parse_buf: 00865 *@a_buf: the css2 in memory buffer. 00866 *@a_len: the length of the in memory buffer. 00867 *@a_enc: the encoding of the in memory buffer. 00868 *@a_result: out parameter. The resulting css2 style sheet. 00869 * 00870 *The simpler way to parse an in memory css2 buffer. 00871 * 00872 *Returns CR_OK upon successfull completion, an error code otherwise. 00873 */ 00874 enum CRStatus 00875 cr_om_parser_simply_parse_buf (const guchar * a_buf, 00876 gulong a_len, 00877 enum CREncoding a_enc, 00878 CRStyleSheet ** a_result) 00879 { 00880 CROMParser *parser = NULL; 00881 enum CRStatus status = CR_OK; 00882 00883 parser = cr_om_parser_new (NULL); 00884 if (!parser) { 00885 cr_utils_trace_info ("Could not create om parser"); 00886 cr_utils_trace_info ("System possibly out of memory"); 00887 return CR_ERROR; 00888 } 00889 00890 status = cr_om_parser_parse_buf (parser, a_buf, a_len, 00891 a_enc, a_result); 00892 00893 if (parser) { 00894 cr_om_parser_destroy (parser); 00895 parser = NULL; 00896 } 00897 00898 return status; 00899 } 00900 00901 /** 00902 * cr_om_parser_parse_file: 00903 *@a_this: the current instance of the cssom parser. 00904 *@a_file_uri: the uri of the file. 00905 *(only local file paths are suppported so far) 00906 *@a_enc: the encoding of the file. 00907 *@a_result: out parameter. A pointer 00908 *the build css object model. 00909 * 00910 *Parses a css2 stylesheet contained 00911 *in a file. 00912 * 00913 * Returns CR_OK upon succesful completion, an error code otherwise. 00914 */ 00915 enum CRStatus 00916 cr_om_parser_parse_file (CROMParser * a_this, 00917 const guchar * a_file_uri, 00918 enum CREncoding a_enc, CRStyleSheet ** a_result) 00919 { 00920 enum CRStatus status = CR_OK; 00921 00922 g_return_val_if_fail (a_this && a_file_uri && a_result, 00923 CR_BAD_PARAM_ERROR); 00924 00925 if (!PRIVATE (a_this)->parser) { 00926 PRIVATE (a_this)->parser = cr_parser_new_from_file 00927 (a_file_uri, a_enc); 00928 } 00929 00930 status = cr_parser_parse_file (PRIVATE (a_this)->parser, 00931 a_file_uri, a_enc); 00932 00933 if (status == CR_OK) { 00934 CRStyleSheet *result = NULL; 00935 CRStyleSheet **resultptr = NULL; 00936 CRDocHandler *sac_handler = NULL; 00937 00938 cr_parser_get_sac_handler (PRIVATE (a_this)->parser, 00939 &sac_handler); 00940 g_return_val_if_fail (sac_handler, CR_ERROR); 00941 resultptr = &result; 00942 status = cr_doc_handler_get_result 00943 (sac_handler, (gpointer *) resultptr); 00944 g_return_val_if_fail (status == CR_OK, status); 00945 if (result) 00946 *a_result = result; 00947 } 00948 00949 return status; 00950 } 00951 00952 /** 00953 * cr_om_parser_simply_parse_file: 00954 *@a_file_path: the css2 local file path. 00955 *@a_enc: the file encoding. 00956 *@a_result: out parameter. The returned css stylesheet. 00957 *Must be freed by the caller using cr_stylesheet_destroy. 00958 * 00959 *The simpler method to parse a css2 file. 00960 * 00961 *Returns CR_OK upon successfull completion, an error code otherwise. 00962 *Note that this method uses cr_om_parser_parse_file() so both methods 00963 *have the same return values. 00964 */ 00965 enum CRStatus 00966 cr_om_parser_simply_parse_file (const guchar * a_file_path, 00967 enum CREncoding a_enc, 00968 CRStyleSheet ** a_result) 00969 { 00970 CROMParser *parser = NULL; 00971 enum CRStatus status = CR_OK; 00972 00973 parser = cr_om_parser_new (NULL); 00974 if (!parser) { 00975 cr_utils_trace_info ("Could not allocate om parser"); 00976 cr_utils_trace_info ("System may be out of memory"); 00977 return CR_ERROR; 00978 } 00979 00980 status = cr_om_parser_parse_file (parser, a_file_path, 00981 a_enc, a_result); 00982 if (parser) { 00983 cr_om_parser_destroy (parser); 00984 parser = NULL; 00985 } 00986 00987 return status; 00988 } 00989 00990 /** 00991 * cr_om_parser_parse_paths_to_cascade: 00992 *@a_this: the current instance of #CROMParser 00993 *@a_author_path: the path to the author stylesheet 00994 *@a_user_path: the path to the user stylesheet 00995 *@a_ua_path: the path to the User Agent stylesheet 00996 *@a_encoding: the encoding of the sheets. 00997 *@a_result: out parameter. The resulting cascade if the parsing 00998 *was okay 00999 * 01000 *Parses three sheets located by their paths and build a cascade 01001 * 01002 *Returns CR_OK upon successful completion, an error code otherwise 01003 */ 01004 enum CRStatus 01005 cr_om_parser_parse_paths_to_cascade (CROMParser * a_this, 01006 const guchar * a_author_path, 01007 const guchar * a_user_path, 01008 const guchar * a_ua_path, 01009 enum CREncoding a_encoding, 01010 CRCascade ** a_result) 01011 { 01012 enum CRStatus status = CR_OK; 01013 01014 /*0->author sheet, 1->user sheet, 2->UA sheet */ 01015 CRStyleSheet *sheets[3]; 01016 guchar *paths[3]; 01017 CRCascade *result = NULL; 01018 gint i = 0; 01019 01020 g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR); 01021 01022 memset (sheets, 0, sizeof (CRStyleSheet*) * 3); 01023 paths[0] = (guchar *) a_author_path; 01024 paths[1] = (guchar *) a_user_path; 01025 paths[2] = (guchar *) a_ua_path; 01026 01027 for (i = 0; i < 3; i++) { 01028 status = cr_om_parser_parse_file (a_this, paths[i], 01029 a_encoding, &sheets[i]); 01030 if (status != CR_OK) { 01031 if (sheets[i]) { 01032 cr_stylesheet_unref (sheets[i]); 01033 sheets[i] = NULL; 01034 } 01035 continue; 01036 } 01037 } 01038 result = cr_cascade_new (sheets[0], sheets[1], sheets[2]); 01039 if (!result) { 01040 for (i = 0; i < 3; i++) { 01041 cr_stylesheet_unref (sheets[i]); 01042 sheets[i] = 0; 01043 } 01044 return CR_ERROR; 01045 } 01046 *a_result = result; 01047 return CR_OK; 01048 } 01049 01050 /** 01051 * cr_om_parser_simply_parse_paths_to_cascade: 01052 *@a_author_path: the path to the author stylesheet 01053 *@a_user_path: the path to the user stylesheet 01054 *@a_ua_path: the path to the User Agent stylesheet 01055 *@a_encoding: the encoding of the sheets. 01056 *@a_result: out parameter. The resulting cascade if the parsing 01057 *was okay 01058 * 01059 *Parses three sheets located by their paths and build a cascade 01060 * 01061 *Returns CR_OK upon successful completion, an error code otherwise 01062 */ 01063 enum CRStatus 01064 cr_om_parser_simply_parse_paths_to_cascade (const guchar * a_author_path, 01065 const guchar * a_user_path, 01066 const guchar * a_ua_path, 01067 enum CREncoding a_encoding, 01068 CRCascade ** a_result) 01069 { 01070 enum CRStatus status = CR_OK; 01071 CROMParser *parser = NULL; 01072 01073 parser = cr_om_parser_new (NULL); 01074 if (!parser) { 01075 cr_utils_trace_info ("could not allocated om parser"); 01076 cr_utils_trace_info ("System may be out of memory"); 01077 return CR_ERROR; 01078 } 01079 status = cr_om_parser_parse_paths_to_cascade (parser, 01080 a_author_path, 01081 a_user_path, 01082 a_ua_path, 01083 a_encoding, a_result); 01084 if (parser) { 01085 cr_om_parser_destroy (parser); 01086 parser = NULL; 01087 } 01088 return status; 01089 } 01090 01091 /** 01092 * cr_om_parser_destroy: 01093 *@a_this: the current instance of #CROMParser. 01094 * 01095 *Destructor of the #CROMParser. 01096 */ 01097 void 01098 cr_om_parser_destroy (CROMParser * a_this) 01099 { 01100 g_return_if_fail (a_this && PRIVATE (a_this)); 01101 01102 if (PRIVATE (a_this)->parser) { 01103 cr_parser_destroy (PRIVATE (a_this)->parser); 01104 PRIVATE (a_this)->parser = NULL; 01105 } 01106 01107 if (PRIVATE (a_this)) { 01108 g_free (PRIVATE (a_this)); 01109 PRIVATE (a_this) = NULL; 01110 } 01111 01112 if (a_this) { 01113 g_free (a_this); 01114 a_this = NULL; 01115 } 01116 }