cr-om-parser.c

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

Generated on Thu Mar 9 19:18:50 2006 for Libcroco by  doxygen 1.4.6