Main Page | Alphabetical List | Data Structures | File List | Data Fields | Globals | Related Pages

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

Generated on Tue Apr 27 13:46:35 2004 for Libcroco by doxygen 1.3.6