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

Generated on Fri Oct 29 08:29:11 2004 for Libcroco by  doxygen 1.3.9.1