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-2003 Dodji Seketeli <dodji@seketeli.org>
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 2004/03/07 13:22:47 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         a_media_list = NULL;    /*compiler happy */
00480 }
00481 
00482 static void
00483 import_style (CRDocHandler * a_this, GList * a_media_list,
00484               GString * a_uri, GString * a_uri_default_ns)
00485 {
00486         enum CRStatus status = CR_OK;
00487         GString *uri = NULL;
00488         CRStatement *stmt = NULL,
00489                 *stmt2 = NULL;
00490         ParsingContext *ctxt = NULL;
00491         ParsingContext **ctxtptr = NULL;
00492         GList *media_list = NULL,
00493                 *cur = NULL;
00494 
00495         g_return_if_fail (a_this);
00496         ctxtptr = &ctxt;
00497         status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr);
00498         g_return_if_fail (status == CR_OK && ctxt);
00499         g_return_if_fail (ctxt->stylesheet);
00500 
00501         uri = g_string_new_len (a_uri->str, a_uri->len);
00502 
00503         for (cur = a_media_list; cur; cur = cur->next) {
00504                 if (cur->data) {
00505                         GString *str1 = NULL,
00506                                 *str2 = NULL;
00507 
00508                         str1 = (GString *) cur->data;
00509                         str2 = g_string_new_len (str1->str, str1->len);
00510 
00511                         media_list = g_list_append (media_list, str2);
00512                 }
00513         }
00514 
00515         stmt = cr_statement_new_at_import_rule
00516                 (ctxt->stylesheet, uri, media_list, NULL);
00517         if (!stmt)
00518                 goto error;
00519 
00520         if (ctxt->cur_stmt) {
00521                 stmt2 = cr_statement_append (ctxt->cur_stmt, stmt);
00522                 if (!stmt2)
00523                         goto error;
00524                 ctxt->cur_stmt = stmt2;
00525                 stmt2 = NULL;
00526                 stmt = NULL;
00527         } else {
00528                 stmt2 = cr_statement_append (ctxt->stylesheet->statements,
00529                                              stmt);
00530                 if (!stmt2)
00531                         goto error;
00532                 ctxt->stylesheet->statements = stmt2;
00533                 stmt2 = NULL;
00534                 stmt = NULL;
00535         }
00536 
00537         return;
00538 
00539       error:
00540         if (uri) {
00541                 g_string_free (uri, TRUE);
00542         }
00543 
00544         if (stmt) {
00545                 cr_statement_destroy (stmt);
00546                 stmt = NULL;
00547         }
00548         a_uri_default_ns = NULL; /*keep compiler happy */
00549 }
00550 
00551 static void
00552 start_selector (CRDocHandler * a_this, CRSelector * a_selector_list)
00553 {
00554         enum CRStatus status = CR_OK;
00555         ParsingContext *ctxt = NULL;
00556         ParsingContext **ctxtptr = NULL;
00557 
00558         g_return_if_fail (a_this);
00559         ctxtptr = &ctxt;
00560         status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr);
00561         g_return_if_fail (status == CR_OK && ctxt);
00562         if (ctxt->cur_stmt) {
00563                 /*hmm, this should be NULL so free it */
00564                 cr_statement_destroy (ctxt->cur_stmt);
00565                 ctxt->cur_stmt = NULL;
00566         }
00567 
00568         ctxt->cur_stmt = cr_statement_new_ruleset
00569                 (ctxt->stylesheet, a_selector_list, NULL, NULL);
00570 }
00571 
00572 static void
00573 end_selector (CRDocHandler * a_this, CRSelector * a_selector_list)
00574 {
00575         enum CRStatus status = CR_OK;
00576         ParsingContext *ctxt = NULL;
00577         ParsingContext **ctxtptr = NULL;
00578 
00579         g_return_if_fail (a_this);
00580         ctxtptr = &ctxt;
00581         status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr);
00582         g_return_if_fail (status == CR_OK && ctxt);
00583         g_return_if_fail (ctxt->cur_stmt && ctxt->stylesheet);
00584 
00585         if (ctxt->cur_stmt) {
00586                 CRStatement *stmts = NULL;
00587 
00588                 if (ctxt->cur_media_stmt) {
00589                         CRAtMediaRule *media_rule = NULL;
00590 
00591                         media_rule = ctxt->cur_media_stmt->kind.media_rule;
00592 
00593                         stmts = cr_statement_append
00594                                 (media_rule->rulesets, ctxt->cur_stmt);
00595 
00596                         if (!stmts) {
00597                                 cr_utils_trace_info
00598                                         ("Could not append a new statement");
00599                                 cr_statement_destroy (media_rule->rulesets);
00600                                 ctxt->cur_media_stmt->
00601                                         kind.media_rule->rulesets = NULL;
00602                                 return;
00603                         }
00604                         media_rule->rulesets = stmts;
00605                         ctxt->cur_stmt = NULL;
00606                 } else {
00607                         stmts = cr_statement_append
00608                                 (ctxt->stylesheet->statements,
00609                                  ctxt->cur_stmt);
00610                         if (!stmts) {
00611                                 cr_utils_trace_info
00612                                         ("Could not append a new statement");
00613                                 cr_statement_destroy (ctxt->cur_stmt);
00614                                 ctxt->cur_stmt = NULL;
00615                                 return;
00616                         }
00617                         ctxt->stylesheet->statements = stmts;
00618                         ctxt->cur_stmt = NULL;
00619                 }
00620 
00621         }
00622         a_selector_list = NULL; /*keep compiler happy */
00623 }
00624 
00625 static void
00626 property (CRDocHandler * a_this,
00627           GString * a_name, CRTerm * a_expression, gboolean a_important)
00628 {
00629         enum CRStatus status = CR_OK;
00630         ParsingContext *ctxt = NULL;
00631         ParsingContext **ctxtptr = NULL;
00632         CRDeclaration *decl = NULL,
00633                 *decl2 = NULL;
00634         GString *str = NULL;
00635 
00636         g_return_if_fail (a_this);
00637         ctxtptr = &ctxt;
00638         status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr);
00639         g_return_if_fail (status == CR_OK && ctxt);
00640 
00641         /*
00642          *make sure a current ruleset statement has been allocated
00643          *already.
00644          */
00645         g_return_if_fail
00646                 (ctxt->cur_stmt
00647                  &&
00648                  (ctxt->cur_stmt->type == RULESET_STMT
00649                   || ctxt->cur_stmt->type == AT_FONT_FACE_RULE_STMT
00650                   || ctxt->cur_stmt->type == AT_PAGE_RULE_STMT));
00651 
00652         if (a_name) {
00653                 str = g_string_new_len (a_name->str, a_name->len);
00654                 g_return_if_fail (str);
00655         }
00656 
00657         /*instanciates a new declaration */
00658         decl = cr_declaration_new (ctxt->cur_stmt, str, a_expression);
00659         g_return_if_fail (decl);
00660         str = NULL;
00661         decl->important = a_important;
00662         /*
00663          *add the new declaration to the current statement
00664          *being build.
00665          */
00666         switch (ctxt->cur_stmt->type) {
00667         case RULESET_STMT:
00668                 decl2 = cr_declaration_append
00669                         (ctxt->cur_stmt->kind.ruleset->decl_list, decl);
00670                 if (!decl2) {
00671                         cr_declaration_destroy (decl);
00672                         cr_utils_trace_info
00673                                 ("Could not append decl to ruleset");
00674                         goto error;
00675                 }
00676                 ctxt->cur_stmt->kind.ruleset->decl_list = decl2;
00677                 decl = NULL;
00678                 decl2 = NULL;
00679                 break;
00680 
00681         case AT_FONT_FACE_RULE_STMT:
00682                 decl2 = cr_declaration_append
00683                         (ctxt->cur_stmt->kind.font_face_rule->decl_list,
00684                          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.font_face_rule->decl_list = decl2;
00692                 decl = NULL;
00693                 decl2 = NULL;
00694                 break;
00695         case AT_PAGE_RULE_STMT:
00696                 decl2 = cr_declaration_append
00697                         (ctxt->cur_stmt->kind.page_rule->decl_list, decl);
00698                 if (!decl2) {
00699                         cr_declaration_destroy (decl);
00700                         cr_utils_trace_info
00701                                 ("Could not append decl to ruleset");
00702                         goto error;
00703                 }
00704                 ctxt->cur_stmt->kind.page_rule->decl_list = decl2;
00705                 decl = NULL;
00706                 decl2 = NULL;
00707                 break;
00708 
00709         default:
00710                 goto error;
00711                 break;
00712         }
00713 
00714         return;
00715 
00716       error:
00717         if (str) {
00718                 g_free (str);
00719                 str = NULL;
00720         }
00721 
00722         if (decl) {
00723                 cr_declaration_destroy (decl);
00724                 decl = NULL;
00725         }
00726 }
00727 
00728 static void
00729 error (CRDocHandler * a_this)
00730 {
00731         enum CRStatus status = CR_OK;
00732         ParsingContext *ctxt = NULL;
00733         ParsingContext **ctxtptr = NULL;
00734 
00735         g_return_if_fail (a_this);
00736         ctxtptr = &ctxt;
00737         status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr);
00738         g_return_if_fail (status == CR_OK && ctxt);
00739 
00740         if (ctxt->cur_stmt) {
00741                 cr_statement_destroy (ctxt->cur_stmt);
00742                 ctxt->cur_stmt = NULL;
00743         }
00744 }
00745 
00746 static void
00747 unrecoverable_error (CRDocHandler * a_this)
00748 {
00749         enum CRStatus status = CR_OK;
00750         ParsingContext *ctxt = NULL;
00751         ParsingContext **ctxtptr = NULL;
00752 
00753         ctxtptr = &ctxt;
00754         status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr);
00755         g_return_if_fail (status == CR_OK);
00756 
00757         if (ctxt) {
00758                 if (ctxt->stylesheet) {
00759                         status = cr_doc_handler_set_result
00760                                 (a_this, ctxt->stylesheet);
00761                         g_return_if_fail (status == CR_OK);
00762                 }
00763                 g_free (ctxt);
00764                 cr_doc_handler_set_ctxt (a_this, NULL);
00765         }
00766 }
00767 
00768 /********************************************
00769  *Public methods
00770  ********************************************/
00771 
00772 /**
00773  *Constructor of the CROMParser.
00774  *@param a_input the input stream.
00775  *@return the newly built instance of #CROMParser.
00776  */
00777 CROMParser *
00778 cr_om_parser_new (CRInput * a_input)
00779 {
00780         CROMParser *result = NULL;
00781         enum CRStatus status = CR_OK;
00782 
00783         result = g_try_malloc (sizeof (CROMParser));
00784 
00785         if (!result) {
00786                 cr_utils_trace_info ("Out of memory");
00787                 return NULL;
00788         }
00789 
00790         memset (result, 0, sizeof (CROMParser));
00791         PRIVATE (result) = g_try_malloc (sizeof (CROMParserPriv));
00792 
00793         if (!PRIVATE (result)) {
00794                 cr_utils_trace_info ("Out of memory");
00795                 goto error;
00796         }
00797 
00798         memset (PRIVATE (result), 0, sizeof (CROMParserPriv));
00799 
00800         PRIVATE (result)->parser = cr_parser_new_from_input (a_input);
00801 
00802         if (!PRIVATE (result)->parser) {
00803                 cr_utils_trace_info ("parsing instanciation failed");
00804                 goto error;
00805         }
00806 
00807         status = cr_om_parser_init_default_sac_handler (result);
00808 
00809         if (status != CR_OK) {
00810                 goto error;
00811         }
00812 
00813         return result;
00814 
00815       error:
00816 
00817         if (result) {
00818                 cr_om_parser_destroy (result);
00819         }
00820 
00821         return NULL;
00822 }
00823 
00824 /**
00825  *Parses the content of an in memory  buffer.
00826  *@param a_this the current instance of #CROMParser.
00827  *@param a_buf the in memory buffer to parse.
00828  *@param a_len the length of the in memory buffer in number of bytes.
00829  *@param a_enc the encoding of the in memory buffer.
00830  *@param a_result out parameter the resulting style sheet
00831  *@return CR_OK upon successfull completion, an error code otherwise.
00832  */
00833 enum CRStatus
00834 cr_om_parser_parse_buf (CROMParser * a_this,
00835                         const guchar * a_buf,
00836                         gulong a_len,
00837                         enum CREncoding a_enc, CRStyleSheet ** a_result)
00838 {
00839 
00840         enum CRStatus status = CR_OK;
00841 
00842         g_return_val_if_fail (a_this && a_result, CR_BAD_PARAM_ERROR);
00843 
00844         if (!PRIVATE (a_this)->parser) {
00845                 PRIVATE (a_this)->parser = cr_parser_new (NULL);
00846         }
00847 
00848         status = cr_parser_parse_buf (PRIVATE (a_this)->parser,
00849                                       a_buf, a_len, a_enc);
00850 
00851         if (status == CR_OK) {
00852                 CRStyleSheet *result = NULL;
00853                 CRStyleSheet **resultptr = NULL;
00854                 CRDocHandler *sac_handler = NULL;
00855 
00856                 cr_parser_get_sac_handler (PRIVATE (a_this)->parser,
00857                                            &sac_handler);
00858                 g_return_val_if_fail (sac_handler, CR_ERROR);
00859                 resultptr = &result;
00860                 status = cr_doc_handler_get_result (sac_handler,
00861                                                     (gpointer *) resultptr);
00862                 g_return_val_if_fail (status == CR_OK, status);
00863 
00864                 if (result)
00865                         *a_result = result;
00866         }
00867 
00868         return status;
00869 }
00870 
00871 /**
00872  *The simpler way to parse an in memory css2 buffer.
00873  *@param a_buf the css2 in memory buffer.
00874  *@param a_len the length of the in memory buffer.
00875  *@param a_enc the encoding of the in memory buffer.
00876  *@param a_result out parameter. The resulting css2 style sheet.
00877  *@return 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  *Parses a css2 stylesheet contained
00908  *in a file.
00909  *@param a_this the current instance of the cssom parser.
00910  *@param a_file_uri the uri of the file. 
00911  *(only local file paths are suppported so far)
00912  *@param a_enc the encoding of the file.
00913  *@param a_result out parameter. A pointer 
00914  *the build css object model.
00915  *@param CR_OK upon successfull completion, an error code
00916  *otherwise.
00917  */
00918 enum CRStatus
00919 cr_om_parser_parse_file (CROMParser * a_this,
00920                          const guchar * a_file_uri,
00921                          enum CREncoding a_enc, CRStyleSheet ** a_result)
00922 {
00923         enum CRStatus status = CR_OK;
00924 
00925         g_return_val_if_fail (a_this && a_file_uri && a_result,
00926                               CR_BAD_PARAM_ERROR);
00927 
00928         if (!PRIVATE (a_this)->parser) {
00929                 PRIVATE (a_this)->parser = cr_parser_new_from_file
00930                         (a_file_uri, a_enc);
00931         }
00932 
00933         status = cr_parser_parse_file (PRIVATE (a_this)->parser,
00934                                        a_file_uri, a_enc);
00935 
00936         if (status == CR_OK) {
00937                 CRStyleSheet *result = NULL;
00938                 CRStyleSheet **resultptr = NULL;
00939                 CRDocHandler *sac_handler = NULL;
00940 
00941                 cr_parser_get_sac_handler (PRIVATE (a_this)->parser,
00942                                            &sac_handler);
00943                 g_return_val_if_fail (sac_handler, CR_ERROR);
00944                 resultptr = &result;
00945                 status = cr_doc_handler_get_result
00946                         (sac_handler, (gpointer *) resultptr);
00947                 g_return_val_if_fail (status == CR_OK, status);
00948                 if (result)
00949                         *a_result = result;
00950         }
00951 
00952         return status;
00953 }
00954 
00955 /**
00956  *The simpler method to parse a css2 file.
00957  *@param a_file_path the css2 local file path.
00958  *@param a_enc the file encoding.
00959  *@param a_result out parameter. The returned css stylesheet.
00960  *Must be freed by the caller using cr_stylesheet_destroy.
00961  *@return 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  *Parses three sheets located by their paths and build a cascade
00992  *@param a_this the current instance of #CROMParser
00993  *@param a_author_path the path to the author stylesheet
00994  *@param a_user_path the path to the user stylesheet
00995  *@param a_ua_path the path to the User Agent stylesheet
00996  *@param a_result out parameter. The resulting cascade if the parsing
00997  *was okay
00998  *@return CR_OK upon successful completion, an error code otherwise
00999  */
01000 enum CRStatus
01001 cr_om_parser_parse_paths_to_cascade (CROMParser * a_this,
01002                                      const guchar * a_author_path,
01003                                      const guchar * a_user_path,
01004                                      const guchar * a_ua_path,
01005                                      enum CREncoding a_encoding,
01006                                      CRCascade ** a_result)
01007 {
01008         enum CRStatus status = CR_OK;
01009 
01010         /*0->author sheet, 1->user sheet, 2->UA sheet */
01011         CRStyleSheet *sheets[3];
01012         guchar *paths[3];
01013         CRCascade *result = NULL;
01014         gint i = 0;
01015 
01016         g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
01017 
01018         memset (sheets, 0, sizeof (CRStyleSheet) * 3);
01019         paths[0] = (guchar *) a_author_path;
01020         paths[1] = (guchar *) a_user_path;
01021         paths[2] = (guchar *) a_ua_path;
01022 
01023         for (i = 0; i < 3; i++) {
01024                 status = cr_om_parser_parse_file (a_this, paths[i],
01025                                                   a_encoding, &sheets[i]);
01026                 if (status != CR_OK) {
01027                         if (sheets[i]) {
01028                                 cr_stylesheet_unref (sheets[i]);
01029                                 sheets[i] = NULL;
01030                         }
01031                         continue;
01032                 }
01033         }
01034         result = cr_cascade_new (sheets[0], sheets[1], sheets[2]);
01035         if (!result) {
01036                 for (i = 0; i < 3; i++) {
01037                         cr_stylesheet_unref (sheets[i]);
01038                         sheets[i] = 0;
01039                 }
01040                 return CR_ERROR;
01041         }
01042         *a_result = result;
01043         return CR_OK;
01044 }
01045 
01046 /**
01047  *Parses three sheets located by their paths and build a cascade
01048  *@param a_author_path the path to the author stylesheet
01049  *@param a_user_path the path to the user stylesheet
01050  *@param a_ua_path the path to the User Agent stylesheet
01051  *@param a_result out parameter. The resulting cascade if the parsing
01052  *was okay
01053  *@return CR_OK upon successful completion, an error code otherwise
01054  */
01055 enum CRStatus
01056 cr_om_parser_simply_parse_paths_to_cascade (const guchar * a_author_path,
01057                                             const guchar * a_user_path,
01058                                             const guchar * a_ua_path,
01059                                             enum CREncoding a_encoding,
01060                                             CRCascade ** a_result)
01061 {
01062         enum CRStatus status = CR_OK;
01063         CROMParser *parser = NULL;
01064 
01065         parser = cr_om_parser_new (NULL);
01066         if (!parser) {
01067                 cr_utils_trace_info ("could not allocated om parser");
01068                 cr_utils_trace_info ("System may be out of memory");
01069                 return CR_ERROR;
01070         }
01071         status = cr_om_parser_parse_paths_to_cascade (parser,
01072                                                       a_author_path,
01073                                                       a_user_path,
01074                                                       a_ua_path,
01075                                                       a_encoding, a_result);
01076         if (parser) {
01077                 cr_om_parser_destroy (parser);
01078                 parser = NULL;
01079         }
01080         return status;
01081 }
01082 
01083 /**
01084  *Destructor of the #CROMParser.
01085  *@param a_this the current instance of #CROMParser.
01086  */
01087 void
01088 cr_om_parser_destroy (CROMParser * a_this)
01089 {
01090         g_return_if_fail (a_this && PRIVATE (a_this));
01091 
01092         if (PRIVATE (a_this)->parser) {
01093                 cr_parser_destroy (PRIVATE (a_this)->parser);
01094                 PRIVATE (a_this)->parser = NULL;
01095         }
01096 
01097         if (PRIVATE (a_this)) {
01098                 g_free (PRIVATE (a_this));
01099                 PRIVATE (a_this) = NULL;
01100         }
01101 
01102         if (a_this) {
01103                 g_free (a_this);
01104                 a_this = NULL;
01105         }
01106 }

Generated on Sat Mar 20 02:38:42 2004 for Libcroco by doxygen 1.3.5