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

cr-statement.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-statement.c,v 1.15 2003/06/29 15:14:51 dodji Exp $
00025  */
00026 
00027 #include <string.h>
00028 #include "cr-statement.h"
00029 #include "cr-parser.h"
00030 
00031 /**
00032  *@file
00033  *Definition of the #CRStatement class.
00034  */
00035 
00036 #define DECLARATION_INDENT_NB 2
00037 
00038 static void
00039 cr_statement_clear (CRStatement *a_this) ;
00040 
00041 static void
00042 cr_statement_dump_ruleset (CRStatement *a_this, FILE *a_fp, glong a_indent) ;
00043 
00044 static void
00045 cr_statement_dump_charset (CRStatement *a_this, FILE *a_fp,
00046                            gulong a_indent) ;
00047 
00048 static void
00049 cr_statement_dump_page (CRStatement *a_this, FILE *a_fp, gulong a_indent) ;
00050 
00051 static void
00052 cr_statement_dump_media_rule (CRStatement *a_this, FILE *a_fp,
00053                               gulong a_indent) ;
00054 
00055 static void
00056 cr_statement_dump_import_rule (CRStatement *a_this, FILE *a_fp,
00057                                gulong a_indent) ;
00058 
00059 static void
00060 parse_font_face_start_font_face_cb (CRDocHandler *a_this)
00061 {
00062         CRStatement *stmt = NULL ;
00063         enum CRStatus status = CR_OK ;
00064 
00065         stmt = cr_statement_new_at_font_face_rule (NULL,
00066                                                    NULL) ;
00067         g_return_if_fail (stmt) ;
00068         
00069         status = cr_doc_handler_set_ctxt (a_this, stmt) ;
00070         g_return_if_fail (status == CR_OK) ;
00071 }
00072 
00073 static void
00074 parse_font_face_unrecoverable_error_cb (CRDocHandler *a_this)
00075 {
00076         CRStatement *stmt = NULL ;
00077         enum CRStatus status = CR_OK ;
00078 
00079         g_return_if_fail (a_this) ;
00080         
00081         status = cr_doc_handler_get_ctxt (a_this, (gpointer*)&stmt) ;
00082         if (status != CR_OK)
00083         {
00084                 cr_utils_trace_info ("Couldn't get parsing context. "
00085                                      "This may lead to some memory leaks.") ;
00086                 return ;
00087         }
00088         if (stmt)
00089         {
00090                 cr_statement_destroy (stmt) ;
00091                 cr_doc_handler_set_ctxt (a_this, NULL) ;
00092                 return ;
00093         }        
00094 }
00095 
00096 static void
00097 parse_font_face_property_cb (CRDocHandler *a_this,
00098                              GString *a_name,
00099                              CRTerm *a_value)
00100 {
00101         enum CRStatus status = CR_OK ;
00102         GString *name = NULL ;
00103         CRDeclaration *decl = NULL ;
00104         CRStatement *stmt = NULL ;
00105 
00106         g_return_if_fail (a_this && a_name) ;
00107 
00108         status = cr_doc_handler_get_ctxt (a_this, (gpointer*)&stmt) ;
00109         g_return_if_fail (status == CR_OK && stmt) ;
00110         g_return_if_fail (stmt->type == AT_FONT_FACE_RULE_STMT) ;
00111 
00112         name = g_string_new_len (a_name->str, a_name->len) ;
00113         g_return_if_fail (name) ;       
00114         decl = cr_declaration_new (stmt, name, a_value) ;
00115         if (!decl)
00116         {
00117                 cr_utils_trace_info ("cr_declaration_new () failed.") ;
00118                 goto error ;
00119         }
00120         name = NULL ;
00121 
00122         stmt->kind.font_face_rule->decl_list = 
00123                 cr_declaration_append (stmt->kind.font_face_rule->decl_list,
00124                                        decl) ;
00125         if (!stmt->kind.font_face_rule->decl_list)
00126                 goto error ;
00127         decl = NULL ;
00128 
00129  error:
00130         if (decl)
00131         {
00132                 cr_declaration_unref (decl) ;
00133                 decl = NULL ;
00134         }
00135         if (name)
00136         {
00137                 g_string_free (name, TRUE) ;
00138                 name = NULL ;
00139         }
00140 }
00141 
00142 static void
00143 parse_font_face_end_font_face_cb (CRDocHandler *a_this)
00144 
00145 {       
00146         CRStatement *result = NULL ;
00147         enum CRStatus status = CR_OK ;
00148         
00149         g_return_if_fail (a_this) ;
00150         
00151         status = cr_doc_handler_get_ctxt (a_this, (gpointer*)&result) ;
00152         g_return_if_fail (status == CR_OK && result) ;
00153         g_return_if_fail (result->type == AT_FONT_FACE_RULE_STMT) ;
00154 
00155         status = cr_doc_handler_set_result (a_this, result) ;
00156         g_return_if_fail (status == CR_OK) ;
00157 }
00158 
00159 static void
00160 parse_page_start_page_cb (CRDocHandler *a_this, 
00161                           GString *a_name,
00162                           GString *a_pseudo_page)
00163 {
00164         CRStatement *stmt = NULL ;
00165         enum CRStatus status = CR_OK ;
00166         
00167         stmt = cr_statement_new_at_page_rule (NULL, NULL, a_name, 
00168                                               a_pseudo_page) ;
00169         g_return_if_fail (stmt) ;
00170         status = cr_doc_handler_set_ctxt (a_this, stmt) ;
00171         g_return_if_fail (status == CR_OK) ;
00172 }
00173 
00174 static void
00175 parse_page_unrecoverable_error_cb (CRDocHandler *a_this)
00176 {
00177         CRStatement *stmt = NULL ;
00178         enum CRStatus status = CR_OK ;
00179 
00180         g_return_if_fail (a_this) ;
00181 
00182         status = cr_doc_handler_get_ctxt (a_this, (gpointer*)&stmt) ;
00183         if (status != CR_OK)
00184         {
00185                 cr_utils_trace_info ("Couldn't get parsing context. "
00186                                      "This may lead to some memory leaks.") ;
00187                 return ;
00188         }
00189         if (stmt)
00190         {
00191                 cr_statement_destroy (stmt) ;
00192                 stmt = NULL ;
00193                 cr_doc_handler_set_ctxt (a_this, NULL) ;
00194         }
00195 }
00196 
00197 static void
00198 parse_page_property_cb (CRDocHandler *a_this,
00199                         GString *a_name, 
00200                         CRTerm *a_expression)
00201 {
00202         GString *name = NULL ;
00203         CRStatement *stmt = NULL ;
00204         CRDeclaration *decl = NULL ;
00205         enum CRStatus status = CR_OK ;
00206 
00207         status = cr_doc_handler_get_ctxt (a_this, (gpointer*)&stmt) ;
00208         g_return_if_fail (status == CR_OK && stmt->type == AT_PAGE_RULE_STMT) ;
00209 
00210         name = g_string_new_len (a_name->str, a_name->len) ;    
00211         g_return_if_fail (name) ;
00212 
00213         decl = cr_declaration_new (stmt, name, a_expression) ;
00214         g_return_if_fail (decl) ;
00215 
00216         stmt->kind.page_rule->decl_list = 
00217                 cr_declaration_append (stmt->kind.page_rule->decl_list,
00218                                        decl) ;
00219         g_return_if_fail (stmt->kind.page_rule->decl_list) ;
00220 }
00221 
00222 static void
00223 parse_page_end_page_cb (CRDocHandler *a_this, 
00224                         GString *a_name,
00225                         GString *a_pseudo_page)
00226 {
00227         enum CRStatus status = CR_OK ;
00228         CRStatement *stmt = NULL ;
00229         
00230         status = cr_doc_handler_get_ctxt (a_this, (gpointer*)&stmt) ;
00231         g_return_if_fail (status == CR_OK && stmt);
00232         g_return_if_fail (stmt->type == AT_PAGE_RULE_STMT);
00233         
00234         status = cr_doc_handler_set_result (a_this, stmt) ;
00235         g_return_if_fail (status == CR_OK) ;
00236 }
00237 
00238 static void
00239 parse_at_media_start_media_cb (CRDocHandler *a_this,
00240                                GList *a_media_list)
00241 {
00242         enum CRStatus status = CR_OK ;
00243         CRStatement *at_media = NULL ;
00244         GList *media_list = NULL ;
00245 
00246         g_return_if_fail (a_this && a_this->priv) ;
00247 
00248         if (a_media_list)
00249         {
00250                 /*duplicate media list*/
00251                 media_list = cr_dup_glist_of_string (a_media_list) ;
00252         }
00253 
00254         g_return_if_fail (media_list) ;
00255 
00256         /*make sure cr_statement_new_at_media_rule works in this case.*/
00257         at_media = cr_statement_new_at_media_rule (NULL, NULL,
00258                                                    media_list) ;
00259 
00260         status = cr_doc_handler_set_ctxt (a_this, at_media) ;        
00261         g_return_if_fail (status == CR_OK) ;
00262         status = cr_doc_handler_set_result (a_this, at_media) ;
00263         g_return_if_fail (status == CR_OK) ;
00264 }
00265 
00266 static void
00267 parse_at_media_unrecoverable_error_cb (CRDocHandler *a_this)
00268 {
00269         enum CRStatus status = CR_OK ;
00270         CRStatement * stmt = NULL ;
00271 
00272         g_return_if_fail (a_this) ;
00273 
00274         status = cr_doc_handler_get_result (a_this, (gpointer*)&stmt) ;
00275         if (status != CR_OK)
00276         {
00277                 cr_utils_trace_info ("Couldn't get parsing context. "
00278                                      "This may lead to some memory leaks.") ;
00279                 return ;
00280         }
00281         if (stmt)
00282         {
00283                 cr_statement_destroy (stmt) ;
00284                 stmt = NULL ;
00285                 cr_doc_handler_set_ctxt (a_this, NULL) ;
00286                 cr_doc_handler_set_result (a_this, NULL) ;
00287         }
00288 }
00289 
00290 static void
00291 parse_at_media_start_selector_cb (CRDocHandler *a_this, 
00292                                   CRSelector *a_sellist)
00293 {
00294         enum CRStatus status = CR_OK ;
00295         CRStatement *at_media = NULL, *ruleset = NULL ;
00296         
00297         g_return_if_fail (a_this 
00298                           && a_this->priv
00299                           && a_sellist) ;
00300         
00301         status = cr_doc_handler_get_ctxt (a_this, 
00302                                           (gpointer*)&at_media) ;
00303         g_return_if_fail (status == CR_OK && at_media) ;
00304         g_return_if_fail (at_media->type == AT_MEDIA_RULE_STMT) ;
00305         ruleset = cr_statement_new_ruleset (NULL, a_sellist,
00306                                             NULL, at_media) ;
00307         g_return_if_fail (ruleset) ;
00308         status = cr_doc_handler_set_ctxt (a_this, ruleset) ;
00309         g_return_if_fail (status == CR_OK) ;
00310 }
00311 
00312 static void
00313 parse_at_media_property_cb (CRDocHandler *a_this,
00314                             GString *a_name, CRTerm *a_value)
00315 {
00316         enum CRStatus status = CR_OK ;
00317         /*
00318          *the current ruleset stmt, child of the 
00319          *current at-media being parsed.
00320          */
00321         CRStatement *stmt = NULL;
00322         GString *name = NULL ;
00323 
00324         g_return_if_fail (a_this && a_name) ;
00325         
00326         name = g_string_new_len (a_name->str, a_name->len) ;
00327         g_return_if_fail (name) ;
00328         
00329         status = cr_doc_handler_get_ctxt (a_this, (gpointer*)&stmt) ;
00330         g_return_if_fail (status == CR_OK && stmt) ;
00331         g_return_if_fail (stmt->type == RULESET_STMT) ;
00332 
00333         status = cr_statement_ruleset_append_decl2
00334                 (stmt, name, a_value) ;
00335         g_return_if_fail (status == CR_OK) ;
00336 
00337         
00338 }
00339 
00340 static void
00341 parse_at_media_end_selector_cb (CRDocHandler *a_this,
00342                                 CRSelector *a_sellist)
00343 {
00344         enum CRStatus status = CR_OK ;
00345         /*
00346          *the current ruleset stmt, child of the 
00347          *current at-media being parsed.
00348          */
00349         CRStatement *stmt = NULL ;
00350    
00351         g_return_if_fail (a_this && a_sellist) ;
00352 
00353         status = cr_doc_handler_get_ctxt (a_this, 
00354                                           (gpointer *)&stmt) ;
00355         g_return_if_fail (status == CR_OK && stmt 
00356                           && stmt->type == RULESET_STMT) ;
00357         g_return_if_fail (stmt->kind.ruleset->parent_media_rule) ;
00358 
00359         status = cr_doc_handler_set_ctxt 
00360                 (a_this, 
00361                  stmt->kind.ruleset->parent_media_rule) ;
00362         g_return_if_fail (status == CR_OK) ;
00363 }
00364 
00365 static void
00366 parse_at_media_end_media_cb (CRDocHandler *a_this,
00367                              GList *a_media_list)
00368 {
00369         enum CRStatus status = CR_OK ;
00370         CRStatement *at_media = NULL ;
00371         g_return_if_fail (a_this && a_this->priv) ;
00372 
00373         status = cr_doc_handler_get_ctxt (a_this, 
00374                                           (gpointer*)&at_media) ;
00375         g_return_if_fail (status == CR_OK && at_media) ;
00376         
00377         status = cr_doc_handler_set_result (a_this, at_media) ;
00378 }
00379 
00380 
00381 static void
00382 parse_ruleset_start_selector_cb (CRDocHandler *a_this, 
00383                                  CRSelector *a_sellist)
00384 {
00385         CRStatement *ruleset = NULL ;
00386 
00387         g_return_if_fail (a_this 
00388                           && a_this->priv
00389                           && a_sellist) ;
00390         
00391         ruleset = cr_statement_new_ruleset (NULL, a_sellist,
00392                                             NULL, NULL) ;
00393         g_return_if_fail (ruleset) ;
00394 
00395         cr_doc_handler_set_result (a_this, ruleset) ;   
00396 }
00397 
00398 static void
00399 parse_ruleset_unrecoverable_error_cb (CRDocHandler *a_this)
00400 {
00401         CRStatement *stmt = NULL ;
00402         enum CRStatus status = CR_OK ;
00403 
00404         status = cr_doc_handler_get_result (a_this, (gpointer*)&stmt) ;
00405         if (status != CR_OK)
00406         {
00407                 cr_utils_trace_info ("Couldn't get parsing context. "
00408                                      "This may lead to some memory leaks.") ;
00409                 return ;
00410         }
00411         if (stmt)
00412         {
00413                 cr_statement_destroy (stmt) ;
00414                 stmt = NULL ;
00415                 cr_doc_handler_set_result (a_this, NULL) ;
00416         }
00417 }
00418 
00419 static void
00420 parse_ruleset_property_cb (CRDocHandler *a_this,
00421                            GString *a_name, CRTerm *a_value)
00422 {
00423         enum CRStatus status = CR_OK ;
00424         CRStatement *ruleset = NULL ;
00425         GString * stringue = NULL ;
00426 
00427         g_return_if_fail (a_this && a_this->priv && a_name) ;
00428 
00429         stringue = g_string_new (a_name->str) ;
00430         g_return_if_fail (stringue) ;
00431 
00432         status = cr_doc_handler_get_result (a_this, (gpointer *)&ruleset) ;
00433         g_return_if_fail (status == CR_OK
00434                           && ruleset && ruleset->type == RULESET_STMT) ;
00435 
00436         status = cr_statement_ruleset_append_decl2 
00437                 (ruleset, stringue, a_value) ;
00438         g_return_if_fail (status == CR_OK) ;
00439 }
00440 
00441 static void
00442 parse_ruleset_end_selector_cb (CRDocHandler *a_this, 
00443                                CRSelector *a_sellist)
00444 {
00445         CRStatement *result = NULL ;
00446         enum CRStatus status = CR_OK ;
00447 
00448         g_return_if_fail (a_this && a_sellist) ;
00449 
00450         status = cr_doc_handler_get_result (a_this, (gpointer *)&result) ;
00451 
00452         g_return_if_fail (status == CR_OK 
00453                           && result 
00454                           && result->type == RULESET_STMT) ;
00455 }
00456 
00457 static void
00458 cr_statement_clear (CRStatement *a_this)
00459 {
00460         g_return_if_fail (a_this) ;
00461 
00462         switch (a_this->type)
00463         {
00464         case AT_RULE_STMT:
00465                 break ;
00466         case RULESET_STMT:
00467                 if (!a_this->kind.ruleset)
00468                         return ;
00469                 if (a_this->kind.ruleset->sel_list)
00470                 {
00471                         cr_selector_unref 
00472                                 (a_this->kind.ruleset->sel_list) ;
00473                         a_this->kind.ruleset->sel_list = NULL ;
00474                 }
00475                 if (a_this->kind.ruleset->decl_list)
00476                 {
00477                         cr_declaration_destroy
00478                                 (a_this->kind.ruleset->decl_list) ;
00479                         a_this->kind.ruleset->decl_list = NULL ;
00480                 }
00481                 g_free (a_this->kind.ruleset) ;
00482                 a_this->kind.ruleset = NULL ;
00483                 break ;
00484 
00485         case AT_IMPORT_RULE_STMT:
00486                 if (!a_this->kind.import_rule)
00487                         return ;
00488                 if (a_this->kind.import_rule->url)
00489                 {
00490                         g_string_free 
00491                                 (a_this->kind.import_rule->url,
00492                                  TRUE) ;
00493                         a_this->kind.import_rule->url = NULL ;
00494                 }
00495                 g_free (a_this->kind.import_rule) ;
00496                 a_this->kind.import_rule = NULL ;
00497                 break ;
00498 
00499         case AT_MEDIA_RULE_STMT:
00500                 if (!a_this->kind.media_rule)
00501                         return;
00502                 if (a_this->kind.media_rule->rulesets)
00503                 {
00504                         cr_statement_destroy 
00505                                 (a_this->kind.media_rule->rulesets) ;
00506                         a_this->kind.media_rule->rulesets = NULL ;
00507                 }
00508                 if (a_this->kind.media_rule->media_list)
00509                 {
00510                         GList *cur = NULL ;
00511                         
00512                         for (cur = a_this->kind.media_rule->media_list;
00513                              cur ; cur = cur->next)
00514                         {
00515                                 if (cur->data)
00516                                 {
00517                                         g_string_free ((GString*)cur->data,
00518                                                        TRUE) ;
00519                                         cur->data = NULL ;
00520                                 }
00521                                 
00522                         }
00523                         g_list_free 
00524                                 (a_this->kind.media_rule->media_list) ;
00525                         a_this->kind.media_rule->media_list = NULL ;
00526                 }
00527                 g_free (a_this->kind.media_rule) ;
00528                 a_this->kind.media_rule = NULL ;
00529                 break ;
00530 
00531         case AT_PAGE_RULE_STMT:
00532                 if (!a_this->kind.page_rule)
00533                         return ;
00534 
00535                 if (a_this->kind.page_rule->decl_list)
00536                 {
00537                         cr_declaration_destroy
00538                                 (a_this->kind.page_rule->decl_list) ;
00539                         a_this->kind.page_rule->decl_list = NULL ;
00540                 }
00541                 if (a_this->kind.page_rule->name)
00542                 {
00543                         g_string_free (a_this->kind.page_rule->name,
00544                                        TRUE) ;
00545                         a_this->kind.page_rule->name = NULL ;
00546                 }
00547                 if (a_this->kind.page_rule->pseudo)
00548                 {
00549                         g_string_free (a_this->kind.page_rule->pseudo,
00550                                        TRUE) ;
00551                         a_this->kind.page_rule->pseudo = NULL ;
00552                 }
00553 
00554                 g_free (a_this->kind.page_rule) ;
00555                 a_this->kind.page_rule = NULL ;
00556                 break ;
00557 
00558         case AT_CHARSET_RULE_STMT:
00559                 if (!a_this->kind.charset_rule)
00560                         return ;
00561 
00562                 if (a_this->kind.charset_rule->charset)
00563                 {
00564                         g_string_free 
00565                                 (a_this->kind.charset_rule->charset, 
00566                                  TRUE) ;
00567                         a_this->kind.charset_rule->charset = NULL ;
00568                 }
00569                 g_free (a_this->kind.charset_rule) ;
00570                 a_this->kind.charset_rule = NULL;
00571                 break ;
00572 
00573         case AT_FONT_FACE_RULE_STMT:
00574                 if (!a_this->kind.font_face_rule)
00575                         return ;
00576 
00577                 if (a_this->kind.font_face_rule->decl_list)
00578                 {
00579                         cr_declaration_unref 
00580                                 (a_this->kind.font_face_rule->decl_list);
00581                         a_this->kind.font_face_rule->decl_list = NULL ;
00582                 }
00583                 g_free (a_this->kind.font_face_rule) ;
00584                 a_this->kind.font_face_rule = NULL ;
00585                 break ;
00586 
00587         default:
00588                 break ;
00589         }
00590 }
00591 
00592 /**
00593  *Dumps a ruleset statement to a file.
00594  *@param a_this the current instance of #CRStatement.
00595  *@param a_fp the destination file pointer.
00596  *@param a_indent the number of indentation white spaces to add.
00597  */
00598 static void
00599 cr_statement_dump_ruleset (CRStatement *a_this, FILE *a_fp, glong a_indent)
00600 {
00601         guchar *str = NULL, *tmp_str = NULL ;
00602 
00603         g_return_if_fail (a_this && a_this->type == RULESET_STMT) ;
00604 
00605         if (a_this->kind.ruleset->sel_list)
00606         {
00607                 if (a_indent)
00608                         cr_utils_dump_n_chars (' ', a_fp, a_indent) ;
00609 
00610                 cr_selector_dump (a_this->kind.ruleset->sel_list, a_fp) ;
00611         }
00612 
00613         if (a_this->kind.ruleset->decl_list)
00614         {
00615                 fprintf (a_fp," {\n") ;
00616                 cr_declaration_dump (a_this->kind.ruleset->decl_list,
00617                                      a_fp, a_indent + DECLARATION_INDENT_NB,
00618                                      TRUE) ;
00619                 fprintf (a_fp,"\n") ;
00620                 cr_utils_dump_n_chars (' ', a_fp, a_indent) ;
00621                 fprintf (a_fp,"}") ;
00622         }
00623 
00624         if (str)
00625         {
00626                 g_free (str) ;
00627                 str = NULL ;
00628         }
00629         if (tmp_str)
00630         {
00631                 g_free (tmp_str) ;
00632                 tmp_str = NULL ;
00633         }
00634 }
00635 
00636 /**
00637  *Dumps a font face rule statement to a file.
00638  *@param a_this the current instance of font face rule statement.
00639  *@param a_fp the destination file pointer.
00640  *@param a_indent the number of white space indentation.
00641  */
00642 static void
00643 cr_statement_dump_font_face_rule (CRStatement *a_this , FILE *a_fp,
00644                                   glong a_indent)
00645 {
00646         g_return_if_fail (a_this 
00647                           && a_this->type == AT_FONT_FACE_RULE_STMT) ;
00648         
00649         if (a_this->kind.font_face_rule->decl_list)
00650         {
00651                 cr_utils_dump_n_chars (' ', a_fp, a_indent) ;
00652 
00653                 if (a_indent)
00654                         cr_utils_dump_n_chars (' ', a_fp, a_indent) ;
00655                 
00656                 fprintf (a_fp,"@font-face {\n") ;
00657                 cr_declaration_dump 
00658                         (a_this->kind.font_face_rule->decl_list,
00659                          a_fp, a_indent + DECLARATION_INDENT_NB, TRUE) ;
00660                 fprintf (a_fp,"\n}") ;
00661         }
00662 }
00663 
00664 /**
00665  *Dumps an @charset rule statement to a file.
00666  *@param a_this the current instance of the @charset rule statement.
00667  *@param a_fp the destination file pointer.
00668  *@param a_indent the number of indentation white spaces.
00669  */
00670 static void
00671 cr_statement_dump_charset (CRStatement *a_this, FILE *a_fp,
00672                            gulong a_indent)
00673 {
00674         guchar *str = NULL ;
00675 
00676         g_return_if_fail (a_this 
00677                           && a_this->type == AT_CHARSET_RULE_STMT) ;
00678         
00679         if (a_this->kind.charset_rule
00680             && a_this->kind.charset_rule->charset)
00681         {
00682                 str = g_strndup (a_this->kind.charset_rule->charset->str,
00683                                  a_this->kind.charset_rule->charset->len) ;
00684 
00685                 g_return_if_fail (str) ;
00686 
00687                 cr_utils_dump_n_chars (' ', a_fp, a_indent) ;
00688                 fprintf (a_fp,"@charset \"%s\" ;", str) ;
00689                 if (str)
00690                 {
00691                         g_free (str) ;
00692                         str = NULL; 
00693                 }
00694         }
00695 }
00696 
00697 /**
00698  *Dumps an @page rule statement on stdout.
00699  *@param a_this the statement to dump on stdout.
00700  *@param a_fp the destination file pointer.
00701  *@param a_indent the number of indentation white spaces.
00702  */
00703 static void
00704 cr_statement_dump_page (CRStatement *a_this, FILE *a_fp, gulong a_indent)
00705 {
00706         guchar *str = NULL ;
00707 
00708         g_return_if_fail (a_this 
00709                           && a_this->type == AT_PAGE_RULE_STMT
00710                           && a_this->kind.page_rule) ;
00711 
00712         cr_utils_dump_n_chars (' ', a_fp, a_indent) ;
00713         fprintf (a_fp,"@page") ;
00714 
00715         if (a_this->kind.page_rule->name)
00716         {
00717                 str = g_strndup (a_this->kind.page_rule->name->str,
00718                                  a_this->kind.page_rule->name->len) ;
00719                 g_return_if_fail (str) ;
00720                 fprintf (a_fp," %s", str) ;
00721                 if (str)
00722                 {
00723                         g_free (str) ;
00724                         str = NULL ;
00725                 }
00726         }
00727         else
00728         {
00729                 fprintf (a_fp," ") ;
00730         }
00731 
00732         if (a_this->kind.page_rule->pseudo)
00733         {
00734                 str = g_strndup (a_this->kind.page_rule->pseudo->str,
00735                                  a_this->kind.page_rule->pseudo->len) ;
00736                 g_return_if_fail (str) ;
00737                 fprintf (a_fp,":%s", str) ;
00738                 if (str)
00739                 {
00740                         g_free (str) ;
00741                         str = NULL ;
00742                 }
00743         }
00744 
00745         if (a_this->kind.page_rule->decl_list)
00746         {
00747                 fprintf (a_fp," {\n") ;
00748                 cr_declaration_dump 
00749                         (a_this->kind.page_rule->decl_list,
00750                          a_fp, a_indent + DECLARATION_INDENT_NB, TRUE) ;
00751                 fprintf (a_fp,"\n}\n") ;
00752         }
00753 }
00754 
00755 /**
00756  *Dumps an @media rule statement to a file.
00757  *@param a_this the statement to dump.
00758  *@param a_fp the destination file pointer
00759  *@param a_indent the number of white spaces indentation.
00760  */
00761 static void
00762 cr_statement_dump_media_rule (CRStatement *a_this, FILE *a_fp,
00763                               gulong a_indent)
00764 {
00765         GList *cur = NULL ;
00766 
00767         g_return_if_fail (a_this->type == AT_MEDIA_RULE_STMT) ;
00768         
00769         if (a_this->kind.media_rule)
00770         {
00771                 cr_utils_dump_n_chars (' ', a_fp, a_indent) ;
00772                 fprintf (a_fp,"@media") ;
00773                 for (cur = a_this->kind.media_rule->media_list ; cur ;
00774                         cur = cur->next)
00775                 {
00776                         if (cur->data)
00777                         {
00778                                 guchar *str = g_strndup 
00779                                         (((GString*)cur->data)->str,
00780                                          ((GString*)cur->data)->len) ;
00781                                 if (str)
00782                                 {
00783                                         if (cur->prev)
00784                                         {
00785                                                 fprintf (a_fp,",") ;
00786                                         }
00787                                         fprintf (a_fp," %s", str) ;
00788                                         g_free (str) ; str = NULL ;
00789                                 }
00790                         }
00791                 }
00792                 fprintf (a_fp," {\n") ;
00793                 cr_statement_dump (a_this->kind.media_rule->rulesets, 
00794                                    a_fp, a_indent + DECLARATION_INDENT_NB) ;
00795                 fprintf (a_fp,"\n}") ;
00796         }
00797 }
00798 
00799 /**
00800  *Dumps an @import rule statement to a file.
00801  *@param a_fp the destination file pointer.
00802  *@param a_indent the number of white space indentations.
00803  */
00804 static void
00805 cr_statement_dump_import_rule (CRStatement *a_this, FILE *a_fp,
00806                                gulong a_indent)
00807 {
00808         g_return_if_fail (a_this 
00809                           && a_this->type == AT_IMPORT_RULE_STMT
00810                           && a_this->kind.import_rule) ;
00811 
00812         if (a_this->kind.import_rule->url)
00813         {
00814                 guchar *str = NULL ;
00815 
00816                 str = g_strndup (a_this->kind.import_rule->url->str,
00817                                  a_this->kind.import_rule->url->len) ;
00818                 cr_utils_dump_n_chars (' ', a_fp, a_indent) ;
00819 
00820                 if (str)
00821                 {
00822                         fprintf (a_fp,"@import url(\"%s\")", str) ;
00823                         g_free (str) ;
00824                 }
00825                 else /*there is no url, so no import rule, get out!*/
00826                         return ;
00827 
00828                 if (a_this->kind.import_rule->media_list)
00829                 {
00830                         GList *cur = NULL ;
00831 
00832                         for (cur = a_this->kind.import_rule->media_list ;
00833                              cur; cur = cur->next)
00834                         {
00835                                 if (cur->data)
00836                                 {
00837                                         GString *gstr = cur->data ;
00838 
00839                                         if (cur->prev)
00840                                         {
00841                                                 fprintf (a_fp,", ") ;
00842                                         }
00843 
00844                                         str = g_strndup (gstr->str,
00845                                                          gstr->len) ;
00846                                         if (str)
00847                                         {
00848                                                 fprintf (a_fp,str) ;
00849                                                 g_free (str) ;
00850                                         }
00851                                 }
00852                         }
00853                         fprintf (a_fp," ;") ;
00854                 }
00855         }
00856 }
00857 
00858 
00859 /*******************
00860  *public functions
00861  ******************/
00862 
00863 /**
00864  *Tries to parse a buffer and says whether if the content of the buffer
00865  *is a css statement as defined by the "Core CSS Grammar" (chapter 4 of the
00866  *css spec) or not.
00867  *@param a_buf the buffer to parse.
00868  *@param a_encoding the character encoding of a_buf.
00869  *@return TRUE if the buffer parses against the core grammar, false otherwise.
00870  */
00871 gboolean
00872 cr_statement_does_buf_parses_against_core (const guchar *a_buf,
00873                                            enum CREncoding a_encoding)
00874 {
00875         CRParser *parser = NULL ;
00876         enum CRStatus status = CR_OK ;
00877         gboolean result = FALSE ;
00878 
00879         parser = cr_parser_new_from_buf (a_buf, strlen (a_buf),
00880                                          a_encoding, FALSE) ;
00881         g_return_val_if_fail (parser, FALSE) ;
00882 
00883         status = cr_parser_set_use_core_grammar (parser, TRUE) ;
00884         if (status != CR_OK)
00885         {
00886                 goto cleanup ;
00887         }
00888         
00889         status = cr_parser_parse_statement_core (parser) ;
00890         if (status == CR_OK)
00891         {
00892                 result = TRUE ;
00893         }
00894 
00895  cleanup:
00896         if (parser)
00897         {
00898                 cr_parser_destroy (parser) ;
00899         }
00900 
00901         return result ;
00902 }
00903 
00904 /**
00905  *Parses a buffer that contains a css statement and returns 
00906  *an instance of #CRStatement in case of successfull parsing.
00907  *TODO: at support of "@import" rules.
00908  *@param a_buf the buffer to parse.
00909  *@param a_encoding the character encoding of a_buf.
00910  *@return the newly built instance of #CRStatement in case
00911  *of successfull parsing, NULL otherwise.
00912  */
00913 CRStatement *
00914 cr_statement_parse_from_buf (const guchar *a_buf,
00915                              enum CREncoding a_encoding)
00916 {
00917         CRStatement *result = NULL ;
00918 
00919         /*
00920          *The strategy of this function is "brute force".
00921          *It tries to parse all the types of #CRStatement it knows about.
00922          *I could do this a smarter way but I don't have the time now.
00923          *I think I will revisit this when time of performances and
00924          *pull based incremental parsing comes.
00925          */
00926 
00927         result = cr_statement_ruleset_parse_from_buf (a_buf, a_encoding) ;
00928         if (!result)
00929         {
00930                 result = cr_statement_at_charset_rule_parse_from_buf 
00931                         (a_buf, a_encoding) ;                   
00932         }
00933         else
00934         {
00935                 goto out ;
00936         }
00937 
00938         if (!result)
00939         {
00940                 result = cr_statement_at_media_rule_parse_from_buf
00941                         (a_buf, a_encoding) ;
00942         }
00943         else
00944         {
00945                 goto out ;
00946         }
00947 
00948         if (!result)
00949         {
00950                 result = cr_statement_at_charset_rule_parse_from_buf 
00951                         (a_buf, a_encoding) ;
00952         }
00953         else
00954         {
00955                 goto out ;
00956         }
00957 
00958         if (!result)
00959         {
00960                 result = cr_statement_font_face_rule_parse_from_buf
00961                         (a_buf, a_encoding) ;
00962 
00963         }
00964         else
00965         {
00966                 goto out ;
00967         }
00968 
00969         if (!result)
00970         {
00971                 result = cr_statement_at_page_rule_parse_from_buf
00972                         (a_buf, a_encoding) ;
00973         }
00974         else
00975         {
00976                 goto out ;
00977         }
00978 
00979         if (!result)
00980         {
00981                 result = cr_statement_at_import_rule_parse_from_buf 
00982                         (a_buf, a_encoding) ;
00983         }
00984         else
00985         {
00986                 goto out ;
00987         }
00988         
00989  out:
00990         return result ;
00991 }
00992 
00993 /**
00994  *Parses a buffer that contains a ruleset statement an instanciates
00995  *a #CRStatement of type RULESET_STMT.
00996  *@param a_buf the buffer to parse.
00997  *@param a_enc the character encoding of a_buf.
00998  *@param the newly built instance of #CRStatement in case of successfull parsing,
00999  *NULL otherwise.
01000  */
01001 CRStatement *
01002 cr_statement_ruleset_parse_from_buf (const guchar * a_buf,
01003                                      enum CREncoding a_enc)
01004 {
01005         enum CRStatus status = CR_OK ;
01006         CRStatement *result = NULL;
01007         CRParser *parser = NULL ;
01008         CRDocHandler *sac_handler = NULL ;
01009 
01010         g_return_val_if_fail (a_buf, NULL) ;
01011 
01012         parser = cr_parser_new_from_buf (a_buf, strlen (a_buf),
01013                                          a_enc, FALSE) ;
01014 
01015         g_return_val_if_fail (parser, NULL) ;
01016 
01017         sac_handler = cr_doc_handler_new () ;
01018         g_return_val_if_fail (parser, NULL) ;
01019 
01020         sac_handler->start_selector = parse_ruleset_start_selector_cb ;
01021         sac_handler->end_selector = parse_ruleset_end_selector_cb ;
01022         sac_handler->property = parse_ruleset_property_cb ;
01023         sac_handler->unrecoverable_error = 
01024                 parse_ruleset_unrecoverable_error_cb ;
01025         
01026         cr_parser_set_sac_handler (parser, sac_handler) ;
01027         cr_parser_try_to_skip_spaces_and_comments (parser) ;
01028         status = cr_parser_parse_ruleset (parser) ;
01029         if (status != CR_OK)
01030         {
01031                 goto cleanup ;
01032         }
01033 
01034         status = cr_doc_handler_get_result (sac_handler, 
01035                                             (gpointer*)&result) ;
01036         if (! ((status == CR_OK) && result) )
01037         {
01038                 if (result)
01039                 {
01040                         cr_statement_destroy (result) ;
01041                         result = NULL ;
01042                 }
01043         }
01044 
01045  cleanup:
01046         if (parser)
01047         {
01048                 cr_parser_destroy (parser) ;
01049                 parser = NULL ;
01050         }
01051         if (sac_handler)
01052         {
01053                 cr_doc_handler_unref (sac_handler) ;
01054                 sac_handler = NULL ;
01055         }
01056         return result ;
01057 }
01058 
01059 /**
01060  *Creates a new instance of #CRStatement of type
01061  *#CRRulSet.
01062  *@param a_sel_list the list of #CRSimpleSel (selectors)
01063  *the rule applies to.
01064  *@param a_decl_list the list of instances of #CRDeclaration
01065  *that composes the ruleset.
01066  *@param a_media_types a list of instances of GString that
01067  *describe the media list this ruleset applies to.
01068  *@return the new instance of #CRStatement or NULL if something
01069  *went wrong.
01070  */
01071 CRStatement*
01072 cr_statement_new_ruleset (CRStyleSheet * a_sheet,
01073                           CRSelector *a_sel_list, 
01074                           CRDeclaration *a_decl_list,
01075                           CRStatement *a_parent_media_rule)
01076 {
01077         CRStatement *result = NULL ;
01078 
01079         g_return_val_if_fail (a_sel_list, NULL) ;
01080 
01081         if (a_parent_media_rule)
01082         {
01083                 g_return_val_if_fail 
01084                         (a_parent_media_rule->type == AT_MEDIA_RULE_STMT,
01085                          NULL) ;
01086                 g_return_val_if_fail (a_parent_media_rule->kind.media_rule,
01087                                       NULL) ;
01088         }
01089 
01090         result = g_try_malloc (sizeof (CRStatement)) ;
01091 
01092         if (!result)
01093         {
01094                 cr_utils_trace_info ("Out of memory") ;
01095                 return NULL ;
01096         }
01097 
01098         memset (result, 0, sizeof (CRStatement)) ;
01099         result->type = RULESET_STMT ;
01100         result->kind.ruleset = g_try_malloc (sizeof (CRRuleSet)) ;
01101 
01102         if (!result->kind.ruleset)
01103         {
01104                 cr_utils_trace_info ("Out of memory") ;
01105                 if (result) g_free (result) ;
01106                 return NULL ;
01107         }
01108 
01109         memset (result->kind.ruleset, 0, sizeof (CRRuleSet)) ;
01110         result->kind.ruleset->sel_list = a_sel_list;
01111         if (a_sel_list)
01112                 cr_selector_ref (a_sel_list) ;
01113         result->kind.ruleset->decl_list = a_decl_list;
01114 
01115         if (a_parent_media_rule)
01116         {
01117                 result->kind.ruleset->parent_media_rule = 
01118                         a_parent_media_rule;
01119                 a_parent_media_rule->kind.media_rule->rulesets = 
01120                         cr_statement_append 
01121                         (a_parent_media_rule->kind.media_rule->rulesets,
01122                          result) ;              
01123         }
01124         
01125 
01126         cr_statement_set_parent_sheet (result, a_sheet) ;
01127 
01128         return result ;
01129 }
01130 
01131 /**
01132  *Parses a buffer that contains an "@media" declaration
01133  *and builds an @media css statement.
01134  *@param a_buf the input to parse.
01135  *@param a_enc the encoding of the buffer.
01136  *@return the @media statement, or NULL if the buffer could not
01137  *be successfully parsed.
01138  */
01139 CRStatement *
01140 cr_statement_at_media_rule_parse_from_buf (const guchar *a_buf,
01141                                            enum CREncoding a_enc)
01142 {
01143         CRParser *parser = NULL ;
01144         CRStatement *result = NULL ;
01145         CRDocHandler *sac_handler = NULL ;
01146         enum CRStatus status = CR_OK ;
01147 
01148         parser = cr_parser_new_from_buf (a_buf, strlen (a_buf),
01149                                          a_enc, FALSE) ;
01150         if (!parser)
01151         {
01152                 cr_utils_trace_info ("Instanciation of the parser failed") ;
01153                 goto cleanup ;
01154         }
01155 
01156         sac_handler = cr_doc_handler_new () ;
01157         if (!sac_handler)
01158         {
01159                 cr_utils_trace_info ("Instanciation of the sac handler failed") ;
01160                 goto cleanup ;
01161         }
01162 
01163         sac_handler->start_media = 
01164                 parse_at_media_start_media_cb ;
01165         sac_handler->start_selector = 
01166                 parse_at_media_start_selector_cb ;
01167         sac_handler->property =
01168                 parse_at_media_property_cb ;
01169         sac_handler->end_selector =
01170                 parse_at_media_end_selector_cb ;
01171         sac_handler->end_media = 
01172                 parse_at_media_end_media_cb ;
01173         sac_handler->unrecoverable_error =
01174                 parse_at_media_unrecoverable_error_cb ;
01175 
01176         status = cr_parser_set_sac_handler (parser, sac_handler) ;
01177         if (status != CR_OK)
01178                 goto cleanup ;
01179         
01180         status = cr_parser_try_to_skip_spaces_and_comments (parser) ;
01181         if (status != CR_OK)
01182                 goto cleanup ;
01183 
01184         status = cr_parser_parse_media (parser) ;
01185         if (status != CR_OK)
01186                 goto cleanup ;
01187         
01188         status = cr_doc_handler_get_result (sac_handler, 
01189                                             (gpointer*)&result) ;
01190         if (status != CR_OK)
01191                 goto cleanup ;
01192 
01193         
01194  cleanup:
01195 
01196         if (parser)
01197         {
01198                 cr_parser_destroy (parser) ;
01199                 parser = NULL ;
01200         }
01201         if (sac_handler)
01202         {
01203                 cr_doc_handler_unref (sac_handler) ;
01204                 sac_handler = NULL ;
01205         }
01206 
01207         return result ; 
01208 }
01209 
01210 /**
01211  *Instanciates an instance of #CRStatement of type
01212  *AT_MEDIA_RULE_STMT (@media ruleset).
01213  *@param a_ruleset the ruleset statements contained
01214  *in the @media rule.
01215  *@param a_media, the media string list. A list of GString pointers.
01216  */
01217 CRStatement *
01218 cr_statement_new_at_media_rule (CRStyleSheet *a_sheet,
01219                                 CRStatement *a_rulesets,
01220                                 GList *a_media)
01221 {
01222         CRStatement *result = NULL, *cur = NULL ;
01223 
01224         if (a_rulesets)
01225                 g_return_val_if_fail (a_rulesets->type == RULESET_STMT,
01226                                       NULL) ;
01227 
01228         result = g_try_malloc (sizeof (CRStatement)) ;
01229 
01230         if (!result)
01231         {
01232                 cr_utils_trace_info ("Out of memory") ;
01233                 return NULL ;
01234         }
01235 
01236         memset (result, 0, sizeof (CRStatement)) ;
01237         result->type = AT_MEDIA_RULE_STMT ;
01238         
01239         result->kind.media_rule = g_try_malloc (sizeof (CRAtMediaRule)) ;
01240         if (!result->kind.media_rule)
01241         {
01242                 cr_utils_trace_info ("Out of memory") ;
01243                 g_free (result) ;
01244                 return NULL ;
01245         }
01246         memset (result->kind.media_rule, 0, sizeof (CRAtMediaRule)) ;
01247         result->kind.media_rule->rulesets = a_rulesets ;
01248         for (cur = a_rulesets ; cur ; cur = cur->next)
01249         {
01250                 if (cur->type != RULESET_STMT || !cur->kind.ruleset)
01251                 {
01252                         cr_utils_trace_info ("Bad parameter a_rulesets. "
01253                                              "It should be a list of "
01254                                              "correct ruleset statement only !");
01255                         goto error ;
01256                 }
01257                 cur->kind.ruleset->parent_media_rule = result ;
01258         }
01259 
01260         result->kind.media_rule->media_list = a_media ; 
01261         if (a_sheet)
01262         {
01263                 cr_statement_set_parent_sheet (result, a_sheet) ;
01264         }
01265 
01266         return result ;
01267         
01268  error:
01269         return NULL ;
01270 }
01271 
01272 
01273 /**
01274  *Creates a new instance of #CRStatment of type
01275  *#CRAtImportRule.
01276  *@param a_url the url to connect to the get the file
01277  *to be imported.
01278  *@param a_sheet the imported parsed stylesheet.
01279  *@return the newly built instance of #CRStatement.
01280  */
01281 CRStatement*
01282 cr_statement_new_at_import_rule (CRStyleSheet *a_container_sheet,
01283                                  GString *a_url,
01284                                  GList *a_media_list,
01285                                  CRStyleSheet *a_imported_sheet)
01286 {
01287         CRStatement *result = NULL ;
01288 
01289         result = g_try_malloc (sizeof (CRStatement)) ;
01290 
01291         if (!result)
01292         {
01293                 cr_utils_trace_info ("Out of memory") ;
01294                 return NULL ;
01295         }
01296 
01297         memset (result, 0, sizeof (CRStatement)) ;
01298         result->type = AT_IMPORT_RULE_STMT ;
01299 
01300         result->kind.import_rule = 
01301                 g_try_malloc (sizeof (CRAtImportRule)) ;
01302 
01303         if (!result->kind.import_rule)
01304         {
01305                 cr_utils_trace_info ("Out of memory") ;
01306                 g_free (result) ;
01307                 return NULL ;
01308         }
01309 
01310         memset (result->kind.import_rule, 0, sizeof (CRAtImportRule)) ;
01311         result->kind.import_rule->url = a_url;
01312         result->kind.import_rule->media_list = a_media_list ;
01313         result->kind.import_rule->sheet = a_imported_sheet;
01314         if (a_container_sheet)
01315                 cr_statement_set_parent_sheet (result, a_container_sheet) ;
01316 
01317         return result ;
01318 }
01319 
01320 /**
01321  *Parses a buffer that contains an "@import" rule and
01322  *instanciate a #CRStatement of type AT_IMPORT_RULE_STMT
01323  *@param a_buf the buffer to parse.
01324  *@param a_encoding the encoding of a_buf.
01325  *@return the newly built instance of #CRStatement in case of 
01326  *a successfull parsing, NULL otherwise.
01327  */
01328 CRStatement *
01329 cr_statement_at_import_rule_parse_from_buf (const guchar * a_buf,
01330                                             enum CREncoding a_encoding)
01331 {
01332         enum CRStatus status = CR_OK ;
01333         CRParser *parser = NULL ;
01334         CRStatement *result = NULL ;
01335         GList *media_list = NULL ;
01336         GString *import_string = NULL ;
01337 
01338         parser = cr_parser_new_from_buf (a_buf, strlen (a_buf),
01339                                          a_encoding, FALSE) ;
01340         if (!parser)
01341         {
01342                 cr_utils_trace_info ("Instanciation of parser failed.") ;
01343                 goto cleanup ;
01344         }
01345 
01346         status = cr_parser_try_to_skip_spaces_and_comments (parser) ;
01347         if (status != CR_OK)
01348                 goto cleanup ;
01349 
01350         status = cr_parser_parse_import (parser, &media_list,
01351                                          &import_string) ;
01352         if (status != CR_OK || !import_string)
01353                 goto cleanup ;
01354 
01355         result = cr_statement_new_at_import_rule (NULL, import_string,
01356                                                   media_list, NULL) ;
01357         if (result)
01358         {
01359                 import_string = NULL ;
01360                 media_list = NULL ;
01361         }
01362 
01363  cleanup:
01364         if (parser)
01365         {
01366                 cr_parser_destroy (parser) ;
01367                 parser = NULL ;
01368         }
01369         if (media_list)
01370         {
01371                 GList *cur = NULL ;
01372                 for (cur = media_list; media_list; 
01373                      media_list = g_list_next (media_list))
01374                 {
01375                         if (media_list->data)
01376                         {
01377                                 g_string_free (media_list->data, TRUE);
01378                                 media_list->data = NULL ;
01379                         }
01380                 }
01381                 g_list_free (media_list) ;
01382                 media_list = NULL;
01383         }
01384         if (import_string)
01385         {
01386                 g_string_free (import_string, TRUE) ;
01387                 import_string = NULL;
01388         }
01389 
01390         return result ;
01391 }
01392 
01393 /**
01394  *Creates a new instance of #CRStatement of type
01395  *#CRAtPageRule.
01396  *@param a_decl_list a list of instances of #CRDeclarations
01397  *which is actually the list of declarations that applies to
01398  *this page rule.
01399  *@param a_selector the page rule selector.
01400  *@return the newly built instance of #CRStatement or NULL
01401  *in case of error.
01402  */
01403 CRStatement *
01404 cr_statement_new_at_page_rule (CRStyleSheet *a_sheet,
01405                                CRDeclaration *a_decl_list,
01406                                GString *a_name,
01407                                GString *a_pseudo)
01408 {
01409         CRStatement *result = NULL ;
01410 
01411 
01412         result = g_try_malloc (sizeof (CRStatement)) ;
01413 
01414         if (!result)
01415         {
01416                 cr_utils_trace_info ("Out of memory") ;
01417                 return NULL ;
01418         }
01419 
01420         memset (result, 0, sizeof (CRStatement)) ;
01421         result->type = AT_PAGE_RULE_STMT ;
01422 
01423         result->kind.page_rule = g_try_malloc (sizeof (CRAtPageRule)) ;
01424 
01425         if (!result->kind.page_rule)
01426         {
01427                 cr_utils_trace_info ("Out of memory") ;
01428                 g_free (result) ;
01429                 return NULL ;
01430         }
01431 
01432         memset (result->kind.page_rule, 0, sizeof (CRAtPageRule)) ;
01433         if (a_decl_list)
01434         {
01435                 result->kind.page_rule->decl_list = a_decl_list;
01436                 cr_declaration_ref (a_decl_list) ;
01437         }
01438         result->kind.page_rule->name = a_name ;
01439         result->kind.page_rule->name = a_pseudo ;
01440         if (a_sheet)
01441                 cr_statement_set_parent_sheet (result, a_sheet) ;
01442 
01443         return result ;
01444 }
01445 
01446 /**
01447  *Parses a buffer that contains an "@page" production and,
01448  *if the parsing succeeds, builds the page statement.
01449  *@param a_buf the character buffer to parse.
01450  *@param a_encoding the character encoding of a_buf.
01451  *@return the newly built at page statement in case of successfull parsing,
01452  *NULL otherwise.
01453  */
01454 CRStatement *
01455 cr_statement_at_page_rule_parse_from_buf (const guchar *a_buf,
01456                                           enum CREncoding a_encoding) 
01457 {
01458         enum CRStatus status = CR_OK ;
01459         CRParser *parser = NULL ;
01460         CRDocHandler *sac_handler = NULL ;
01461         CRStatement *result = NULL ;
01462 
01463         g_return_val_if_fail (a_buf, NULL) ;
01464         
01465         parser = cr_parser_new_from_buf (a_buf, strlen (a_buf),
01466                                          a_encoding, FALSE) ;
01467         if (!parser)
01468         {
01469                 cr_utils_trace_info ("Instanciation of the parser failed.") ;
01470                 goto cleanup ;
01471         }
01472 
01473         sac_handler = cr_doc_handler_new () ;
01474         if (!sac_handler)
01475         {
01476                 cr_utils_trace_info 
01477                         ("Instanciation of the sac handler failed.") ;
01478                 goto cleanup ;
01479         }
01480 
01481         sac_handler->start_page = 
01482                 parse_page_start_page_cb ;
01483         sac_handler->property =
01484                 parse_page_property_cb ;
01485         sac_handler->end_page = 
01486                 parse_page_end_page_cb ;
01487         sac_handler->unrecoverable_error =
01488                 parse_page_unrecoverable_error_cb ;
01489 
01490         status = cr_parser_set_sac_handler (parser, sac_handler) ;
01491         if (status != CR_OK)
01492                 goto cleanup ;
01493         
01494         /*Now, invoke the parser to parse the "@page production"*/
01495         cr_parser_try_to_skip_spaces_and_comments (parser) ;
01496         if (status != CR_OK)
01497                 goto cleanup ;
01498         status = cr_parser_parse_page (parser) ;
01499         if (status != CR_OK)
01500                 goto cleanup ;
01501         
01502         status = cr_doc_handler_get_result (sac_handler,
01503                                             (gpointer*)&result) ;
01504 
01505  cleanup:
01506 
01507         if (parser)
01508         {
01509                 cr_parser_destroy (parser) ;
01510                 parser = NULL ;
01511         }
01512         if (sac_handler)
01513         {
01514                 cr_doc_handler_unref (sac_handler) ;
01515                 sac_handler = NULL ;
01516         }
01517         return result  ;
01518         
01519 }
01520 
01521 /**
01522  *Creates a new instance of #CRStatement of type
01523  *#CRAtCharsetRule.
01524  *@param a_charset the string representing the charset.
01525  *Note that the newly built instance of #CRStatement becomes
01526  *the owner of a_charset. The caller must not free a_charset !!!.
01527  *@return the newly built instance of #CRStatement or NULL
01528  *if an error arises.
01529  */
01530 CRStatement *
01531 cr_statement_new_at_charset_rule (CRStyleSheet *a_sheet,
01532                                   GString *a_charset)
01533 {
01534         CRStatement * result = NULL ;
01535 
01536         g_return_val_if_fail (a_charset, NULL) ;
01537 
01538         result = g_try_malloc (sizeof (CRStatement)) ;
01539 
01540         if (!result)
01541         {
01542                 cr_utils_trace_info ("Out of memory") ;
01543                 return NULL ;
01544         }
01545 
01546         memset (result, 0, sizeof (CRStatement)) ;
01547         result->type = AT_CHARSET_RULE_STMT ;
01548 
01549         result->kind.charset_rule = g_try_malloc 
01550                 (sizeof (CRAtCharsetRule)) ;
01551 
01552         if (!result->kind.charset_rule)
01553         {
01554                 cr_utils_trace_info ("Out of memory") ;
01555                 g_free (result) ;
01556                 return NULL ;
01557         }
01558         memset (result->kind.charset_rule, 0, sizeof (CRAtCharsetRule)) ;
01559         result->kind.charset_rule->charset = a_charset ;
01560         cr_statement_set_parent_sheet (result, a_sheet) ;
01561 
01562         return result ;
01563 }
01564 
01565 /**
01566  *Parses a buffer that contains an '@charset' rule and
01567  *creates an instance of #CRStatement of type AT_CHARSET_RULE_STMT.
01568  *@param a_buf the buffer to parse.
01569  *@param the character encoding of the buffer.
01570  *@return the newly built instance of #CRStatement.
01571  */
01572 CRStatement *
01573 cr_statement_at_charset_rule_parse_from_buf (const guchar *a_buf,
01574                                              enum CREncoding a_encoding) 
01575 {
01576         enum CRStatus status = CR_OK ;
01577         CRParser *parser = NULL ;
01578         CRStatement *result = NULL ;
01579         GString *charset = NULL ;
01580 
01581         g_return_val_if_fail (a_buf, NULL) ;    
01582         
01583         parser = cr_parser_new_from_buf (a_buf, strlen (a_buf),
01584                                          a_encoding, FALSE) ;
01585         if (!parser)
01586         {
01587                 cr_utils_trace_info ("Instanciation of the parser failed.") ;
01588                 goto cleanup ;
01589         }
01590         
01591         /*Now, invoke the parser to parse the "@charset production"*/
01592         cr_parser_try_to_skip_spaces_and_comments (parser) ;
01593         if (status != CR_OK)
01594                 goto cleanup ;
01595         status = cr_parser_parse_charset (parser, &charset) ;
01596         if (status != CR_OK || !charset)
01597                 goto cleanup ;
01598 
01599         result = cr_statement_new_at_charset_rule (NULL, charset) ;
01600         if (result)
01601                 charset = NULL ;
01602 
01603  cleanup:
01604 
01605         if (parser)
01606         {
01607                 cr_parser_destroy (parser) ;
01608                 parser = NULL ;
01609         }
01610         if (charset)
01611         {
01612                 g_string_free (charset, TRUE) ;
01613         }
01614 
01615         return result  ;
01616 }
01617 
01618 /**
01619  *Creates an instance of #CRStatement of type #CRAtFontFaceRule.
01620  *@param a_font_decls a list of instances of #CRDeclaration. Each declaration
01621  *is actually a font declaration.
01622  *@return the newly built instance of #CRStatement.
01623  */
01624 CRStatement *
01625 cr_statement_new_at_font_face_rule (CRStyleSheet *a_sheet,
01626                                     CRDeclaration *a_font_decls)
01627 {
01628         CRStatement *result = NULL ;
01629         
01630         result = g_try_malloc (sizeof (CRStatement)) ;
01631 
01632         if (!result)
01633         {
01634                 cr_utils_trace_info ("Out of memory") ;
01635                 return NULL ;
01636         }
01637         memset (result, 0, sizeof (CRStatement)) ;
01638         result->type = AT_FONT_FACE_RULE_STMT ;
01639 
01640         result->kind.font_face_rule = g_try_malloc 
01641                 (sizeof (CRAtFontFaceRule)) ;
01642 
01643         if (!result->kind.font_face_rule)
01644         {
01645                 cr_utils_trace_info ("Out of memory") ;
01646                 g_free (result) ;
01647                 return NULL ;
01648         }
01649         memset (result->kind.font_face_rule, 0, 
01650                 sizeof (CRAtFontFaceRule));
01651         
01652         result->kind.font_face_rule->decl_list = a_font_decls ;
01653         if (a_sheet)
01654                 cr_statement_set_parent_sheet (result, a_sheet) ;
01655 
01656         return result ;
01657 }
01658 
01659 /**
01660  *Parses a buffer that contains an "@font-face" rule and builds
01661  *an instance of #CRStatement of type AT_FONT_FACE_RULE_STMT out of it.
01662  *@param a_buf the buffer to parse.
01663  *@param a_encoding the character encoding of a_buf.
01664  *@return the newly built instance of #CRStatement in case of successufull
01665  *parsing, NULL otherwise.
01666  */
01667 CRStatement *
01668 cr_statement_font_face_rule_parse_from_buf (const guchar *a_buf,
01669                                             enum CREncoding a_encoding)
01670 {
01671         CRStatement *result = NULL ;
01672         CRParser *parser = NULL ;
01673         CRDocHandler *sac_handler = NULL ;
01674         enum CRStatus status = CR_OK ;
01675 
01676         parser = cr_parser_new_from_buf (a_buf, strlen (a_buf),
01677                                          a_encoding, FALSE) ;
01678         if (!parser)
01679                 goto cleanup ;
01680 
01681         sac_handler = cr_doc_handler_new () ;
01682         if (!sac_handler)
01683                 goto cleanup ;
01684 
01685         /*
01686          *set sac callbacks here
01687          */
01688         sac_handler->start_font_face = parse_font_face_start_font_face_cb ;
01689         sac_handler->property = parse_font_face_property_cb ;
01690         sac_handler->end_font_face = parse_font_face_end_font_face_cb ; 
01691         sac_handler->unrecoverable_error =
01692                 parse_font_face_unrecoverable_error_cb ;
01693 
01694         status = cr_parser_set_sac_handler (parser, sac_handler) ;
01695         if (status != CR_OK)
01696                 goto cleanup ;
01697 
01698         /*
01699          *cleanup spaces of comment that may be there before the real
01700          *"@font-face" thing.
01701          */
01702         status = cr_parser_try_to_skip_spaces_and_comments (parser) ;
01703         if (status != CR_OK)
01704                 goto cleanup ;
01705 
01706         status = cr_parser_parse_font_face (parser) ;
01707         if (status != CR_OK)
01708                 goto cleanup ;
01709 
01710         status = cr_doc_handler_get_result (sac_handler, (gpointer*)&result) ;
01711         if (status != CR_OK || !result)
01712                 goto cleanup ;
01713 
01714  cleanup:
01715         if (parser)
01716         {
01717                 cr_parser_destroy (parser) ;
01718                 parser = NULL ;
01719         }
01720         if (sac_handler)
01721         {
01722                 cr_doc_handler_unref (sac_handler) ;
01723                 sac_handler = NULL ;
01724         }
01725         return result ;
01726 }
01727 
01728 /**
01729  *Sets the container stylesheet.
01730  *@param a_this the current instance of #CRStatement.
01731  *@param a_sheet the sheet that contains the current statement.
01732  *@return CR_OK upon successfull completion, an errror code otherwise.
01733  */
01734 enum CRStatus
01735 cr_statement_set_parent_sheet (CRStatement *a_this, 
01736                                CRStyleSheet *a_sheet)
01737 {
01738         g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR) ;
01739         a_this->parent_sheet = a_sheet ;
01740         return CR_OK ;
01741 }
01742 
01743 /**
01744  *Gets the sheets that contains the current statement.
01745  *@param a_this the current #CRStatement.
01746  *@param a_sheet out parameter. A pointer to the sheets that
01747  *@return CR_OK upon successfull completion, an error code otherwise.
01748  */
01749 enum CRStatus
01750 cr_statement_get_parent_sheet (CRStatement *a_this, 
01751                                CRStyleSheet **a_sheet)
01752 {
01753         g_return_val_if_fail (a_this && a_sheet, 
01754                               CR_BAD_PARAM_ERROR) ;
01755         *a_sheet  = a_this->parent_sheet ;
01756         return CR_OK ;
01757 }
01758 
01759 /**
01760  *Appends a new statement to the statement list.
01761  *@param a_this the current instance of the statement list.
01762  *@param a_this a_new the new instance of #CRStatement to append.
01763  *@return the new list statement list, or NULL in cas of failure.
01764  */
01765 CRStatement *
01766 cr_statement_append (CRStatement *a_this,
01767                      CRStatement *a_new)
01768 {
01769         CRStatement * cur = NULL ;
01770 
01771         g_return_val_if_fail (a_new, NULL) ;
01772         
01773         if (!a_this)
01774         {
01775                 return a_new ;
01776         }
01777 
01778         /*walk forward in the current list to find the tail list element*/
01779         for (cur = a_this ; cur && cur->next ; cur = cur->next) ;
01780 
01781         cur->next = a_new ;
01782         a_new->prev = cur ;
01783 
01784         return a_this ;
01785 }
01786 
01787 /**
01788  *Prepends the an instance of #CRStatement to
01789  *the current statement list.
01790  *@param a_this the current instance of #CRStatement.
01791  *@param a_new the new statement to prepend.
01792  *@return the new list with the new statement prepended,
01793  *or NULL in case of an error.
01794  */
01795 CRStatement*
01796 cr_statement_prepend (CRStatement *a_this,
01797                       CRStatement *a_new)
01798 {
01799         CRStatement *cur = NULL ;
01800 
01801         g_return_val_if_fail (a_new, NULL) ;
01802 
01803         if (!a_this)
01804                 return a_new ;
01805 
01806         a_new->next = a_this ;
01807         a_this->prev = a_new ;
01808 
01809         /*walk backward in the prepended list to find the head list element*/
01810         for (cur = a_new ; cur && cur->prev ; cur = cur->prev) ;
01811         
01812         return cur ;
01813 }
01814 
01815 /**
01816  *Unlinks a statement from the statements list.
01817  *@param a_this the current statements list.
01818  *@param a_to_unlink the statement to unlink from the list.
01819  *@return the new list where a_to_unlink has been unlinked
01820  *from, or NULL in case of error.
01821  */
01822 CRStatement *
01823 cr_statement_unlink (CRStatement *a_stmt)
01824 {
01825         CRStatement *result = a_stmt ;
01826 
01827         g_return_val_if_fail (result, NULL) ;
01828 
01829         /**
01830          *Some sanity checks first
01831          */
01832         if (a_stmt->next)
01833         {
01834                 g_return_val_if_fail (a_stmt->next->prev == a_stmt,
01835                                       NULL) ;
01836         }
01837         if (a_stmt->prev)
01838         {
01839                 g_return_val_if_fail (a_stmt->prev->next == a_stmt,
01840                                       NULL) ;
01841         }
01842         
01843         /**
01844          *Now, the real unlinking job.
01845          */
01846         if (a_stmt->next)
01847         {
01848                 a_stmt->next->prev = a_stmt->prev ;
01849         }
01850         if (a_stmt->prev)
01851         {
01852                 a_stmt->prev->next = a_stmt->next ;
01853         }
01854         
01855         if (a_stmt->parent_sheet 
01856             && a_stmt->parent_sheet->statements == a_stmt)
01857         {
01858                 a_stmt->parent_sheet->statements = 
01859                         a_stmt->parent_sheet->statements->next ;
01860         }
01861 
01862         a_stmt->next = NULL ;
01863         a_stmt->prev = NULL ;
01864         a_stmt->parent_sheet = NULL ;
01865 
01866         return result ;
01867 }
01868 
01869 
01870 /**
01871  *Sets a selector list to a ruleset statement.
01872  *@param a_this the current ruleset statement.
01873  *@param a_sel_list the selector list to set. Note
01874  *that this function increments the ref count of a_sel_list.
01875  *The sel list will be destroyed at the destruction of the
01876  *current instance of #CRStatement.
01877  *@return CR_OK upon successfull completion, an error code otherwise.
01878  */
01879 enum CRStatus
01880 cr_statement_ruleset_set_sel_list (CRStatement *a_this,
01881                                    CRSelector *a_sel_list)
01882 {
01883         g_return_val_if_fail (a_this && a_this->type == RULESET_STMT,
01884                               CR_BAD_PARAM_ERROR) ;
01885         
01886         if (a_this->kind.ruleset->sel_list)
01887                 cr_selector_unref (a_this->kind.ruleset->sel_list) ;
01888         
01889         a_this->kind.ruleset->sel_list = a_sel_list ;
01890 
01891         if (a_sel_list)
01892                 cr_selector_ref (a_sel_list) ;
01893 
01894         return CR_OK ;  
01895 }
01896 
01897 /**
01898  *Gets a pointer to the list of declaration contained
01899  *in the ruleset statement.
01900  *@param a_this the current instance of #CRStatement.
01901  *@a_decl_list out parameter. A pointer to the the returned
01902  *list of declaration. Must not be NULL.
01903  *@return CR_OK upon successfull completion, an error code if something
01904  *bad happened.
01905  */
01906 enum CRStatus
01907 cr_statement_ruleset_get_declarations (CRStatement *a_this,
01908                                        CRDeclaration **a_decl_list)
01909 {
01910         g_return_val_if_fail (a_this 
01911                               && a_this->type == RULESET_STMT
01912                               && a_this->kind.ruleset
01913                               && a_decl_list,
01914                               CR_BAD_PARAM_ERROR) ;
01915 
01916         *a_decl_list = a_this->kind.ruleset->decl_list ;
01917 
01918         return CR_OK ;
01919 }
01920 
01921 /**
01922  *Gets a pointer to the selector list contained in
01923  *the current ruleset statement.
01924  *@param a_this the current ruleset statement.
01925  *@param a_list out parameter. The returned selector list,
01926  *if and only if the function returned CR_OK.
01927  *@return CR_OK upon successfull completion, an error code otherwise.
01928  */
01929 enum CRStatus
01930 cr_statement_ruleset_get_sel_list (CRStatement *a_this,
01931                                    CRSelector **a_list)
01932 {
01933         g_return_val_if_fail (a_this && a_this->type == RULESET_STMT
01934                               && a_this->kind.ruleset, CR_BAD_PARAM_ERROR) ;
01935         
01936         *a_list = a_this->kind.ruleset->sel_list ;
01937 
01938         return CR_OK ;
01939 }
01940 
01941 
01942 /**
01943  *Sets a declaration list to the current ruleset statement.
01944  *@param a_this the current ruleset statement.
01945  *@param a_list the declaration list to be added to the current
01946  *ruleset statement.
01947  *@return CR_OK upon successfull completion, an error code otherwise.
01948  */
01949 enum CRStatus
01950 cr_statement_ruleset_set_decl_list (CRStatement *a_this,
01951                                     CRDeclaration *a_list)
01952 {
01953         g_return_val_if_fail (a_this && a_this->type == RULESET_STMT
01954                               && a_this->kind.ruleset, CR_BAD_PARAM_ERROR);
01955 
01956         if (a_this->kind.ruleset->decl_list == a_list)
01957                 return CR_OK ;
01958 
01959         if (a_this->kind.ruleset->sel_list)
01960         {
01961                 cr_declaration_destroy (a_this->kind.ruleset->decl_list) ;
01962         }
01963 
01964         a_this->kind.ruleset->sel_list = NULL;
01965 
01966         return CR_OK ;
01967 }
01968 
01969 
01970 /**
01971  *Appends a declaration to the current ruleset statement.
01972  *@param a_this the current statement.
01973  *@param a_prop the property of the declaration.
01974  *@param a_value the value of the declaration.
01975  *@return CR_OK uppon successfull completion, an error code
01976  *otherwise.
01977  */
01978 enum CRStatus
01979 cr_statement_ruleset_append_decl2 (CRStatement *a_this,
01980                                    GString *a_prop, CRTerm *a_value)
01981 {
01982         CRDeclaration * new_decls = NULL ;
01983 
01984         g_return_val_if_fail (a_this && a_this->type == RULESET_STMT
01985                               && a_this->kind.ruleset, CR_BAD_PARAM_ERROR) ;
01986 
01987         new_decls = cr_declaration_append2 
01988                 (a_this->kind.ruleset->decl_list, a_prop, a_value) ;
01989         g_return_val_if_fail (new_decls, CR_ERROR) ;
01990         a_this->kind.ruleset->decl_list = new_decls ;
01991 
01992         return CR_OK ;
01993 }
01994 
01995 /**
01996  *Appends a declaration to the current statement.
01997  *@param a_this the current statement.
01998  *@param a_declaration the declaration to append.
01999  *@return CR_OK upon sucessfull completion, an error code
02000  *otherwise.
02001  */
02002 enum CRStatus
02003 cr_statement_ruleset_append_decl (CRStatement *a_this,
02004                                   CRDeclaration *a_decl)
02005 {
02006         CRDeclaration * new_decls = NULL ;
02007 
02008         g_return_val_if_fail (a_this && a_this->type == RULESET_STMT
02009                               && a_this->kind.ruleset, CR_BAD_PARAM_ERROR) ;
02010 
02011         new_decls = cr_declaration_append
02012                 (a_this->kind.ruleset->decl_list, a_decl) ;
02013         g_return_val_if_fail (new_decls, CR_ERROR) ;
02014         a_this->kind.ruleset->decl_list = new_decls ;
02015 
02016         return CR_OK ;
02017 }
02018 
02019 
02020 /**
02021  *Sets a stylesheet to the current @import rule.
02022  *@param a_this the current @import rule.
02023  *@param a_sheet the stylesheet. The stylesheet is owned
02024  *by the current instance of #CRStatement, that is, the 
02025  *stylesheet will be destroyed when the current instance
02026  *of #CRStatement will be destroyed.
02027  *@return CR_OK upon successfull completion, an error code otherwise.
02028  */
02029 enum CRStatus
02030 cr_statement_at_import_rule_set_imported_sheet (CRStatement *a_this,
02031                                                 CRStyleSheet *a_sheet)
02032 {
02033         g_return_val_if_fail (a_this 
02034                               && a_this->type == AT_IMPORT_RULE_STMT
02035                               && a_this->kind.import_rule,
02036                               CR_BAD_PARAM_ERROR) ;
02037 
02038         a_this->kind.import_rule->sheet = a_sheet ;
02039 
02040         return CR_OK ;
02041 }
02042 
02043 
02044 /**
02045  *Gets the stylesheet contained by the @import rule statement.
02046  *@param a_this the current @import rule statement.
02047  *@param a_sheet out parameter. The returned stylesheet if and
02048  *only if the function returns CR_OK.
02049  *@return CR_OK upon sucessfull completion, an error code otherwise.
02050  */
02051 enum CRStatus
02052 cr_statement_at_import_rule_get_imported_sheet (CRStatement *a_this,
02053                                                 CRStyleSheet **a_sheet)
02054 {
02055         g_return_val_if_fail (a_this 
02056                               && a_this->type == AT_IMPORT_RULE_STMT
02057                               && a_this->kind.import_rule,
02058                               CR_BAD_PARAM_ERROR) ;
02059         *a_sheet = a_this->kind.import_rule->sheet ;
02060         return CR_OK ;
02061 
02062 }
02063 
02064 /**
02065  *Sets an url to the current @import rule statement.
02066  *@param a_this the current @import rule statement.
02067  *@param a_url the url to set.
02068  *@return CR_OK upon successfull completion, an error code otherwise.
02069  */
02070 enum CRStatus
02071 cr_statement_at_import_rule_set_url (CRStatement *a_this,
02072                                      GString *a_url)
02073 {
02074         g_return_val_if_fail (a_this 
02075                               && a_this->type == AT_IMPORT_RULE_STMT
02076                               && a_this->kind.import_rule,
02077                               CR_BAD_PARAM_ERROR) ;
02078 
02079         if (a_this->kind.import_rule->url)
02080         {
02081                 g_string_free (a_this->kind.import_rule->url, TRUE) ;
02082         }
02083         
02084         a_this->kind.import_rule->url = a_url ;
02085 
02086         return CR_OK ;
02087 }
02088 
02089 
02090 /**
02091  *Gets the url of the @import rule statement.
02092  *@param the current @import rule statement.
02093  *@param a_url out parameter. The returned url if
02094  *and only if the function returned CR_OK.
02095  */
02096 enum CRStatus
02097 cr_statement_at_import_rule_get_url (CRStatement *a_this,
02098                                      GString **a_url)
02099 {
02100         g_return_val_if_fail (a_this 
02101                               && a_this->type == AT_IMPORT_RULE_STMT
02102                               && a_this->kind.import_rule,
02103                               CR_BAD_PARAM_ERROR) ;
02104 
02105         *a_url = a_this->kind.import_rule->url ;
02106 
02107         return CR_OK ;
02108 }
02109 
02110 /**
02111  *Sets a declaration list to the current @page rule statement.
02112  *@param a_this the current @page rule statement.
02113  *@param a_decl_list the declaration list to add. Will be freed
02114  *by the current instance of #CRStatement when it is destroyed.
02115  *@return CR_OK upon successfull completion, an error code otherwise.
02116  */
02117 enum CRStatus
02118 cr_statement_at_page_rule_set_declarations (CRStatement *a_this,
02119                                             CRDeclaration *a_decl_list)
02120 {
02121         g_return_val_if_fail (a_this
02122                               && a_this->type == AT_PAGE_RULE_STMT
02123                               && a_this->kind.page_rule,
02124                               CR_BAD_PARAM_ERROR) ;
02125 
02126         if (a_this->kind.page_rule->decl_list)
02127         {
02128                 cr_declaration_unref (a_this->kind.page_rule->decl_list);
02129         }
02130 
02131         a_this->kind.page_rule->decl_list = a_decl_list ;
02132 
02133         if (a_decl_list)
02134         {
02135                 cr_declaration_ref (a_decl_list) ;
02136         }
02137 
02138         return CR_OK ;
02139 }
02140 
02141 
02142 /**
02143  *Gets the declaration list associated to the current @page rule
02144  *statement.
02145  *@param a_this the current  @page rule statement.
02146  *@param a_decl_list out parameter. The returned declaration list.
02147  *@return CR_OK upon successfull completion, an error code otherwise.
02148  */
02149 enum CRStatus
02150 cr_statement_at_page_rule_get_declarations (CRStatement *a_this,
02151                                             CRDeclaration **a_decl_list)
02152 {
02153         g_return_val_if_fail (a_this
02154                               && a_this->type == AT_PAGE_RULE_STMT
02155                               && a_this->kind.page_rule,
02156                               CR_BAD_PARAM_ERROR) ;
02157 
02158         *a_decl_list = a_this->kind.page_rule->decl_list ;
02159 
02160         return CR_OK ;
02161 }
02162 
02163 
02164 /**
02165  *Sets the charset of the current @charset rule statement.
02166  *@param a_this the current @charset rule statement.
02167  *@param a_charset the charset to set.
02168  *@return CR_OK upon successfull completion, an error code otherwise.
02169  */
02170 enum CRStatus
02171 cr_statement_at_charset_rule_set_charset (CRStatement *a_this,
02172                                           GString *a_charset)
02173 {
02174         g_return_val_if_fail (a_this
02175                               && a_this->type == AT_CHARSET_RULE_STMT
02176                               && a_this->kind.charset_rule,
02177                               CR_BAD_PARAM_ERROR) ;
02178 
02179         if (a_this->kind.charset_rule->charset)
02180         {
02181                 g_string_free (a_this->kind.charset_rule->charset,
02182                                TRUE) ;
02183         }
02184 
02185         a_this->kind.charset_rule->charset = a_charset ;
02186         return CR_OK ;
02187 }
02188 
02189 
02190 /**
02191  *Gets the charset string associated to the current
02192  *@charset rule statement.
02193  *@param a_this the current @charset rule statement.
02194  *@param a_charset out parameter. The returned charset string if
02195  *and only if the function returned CR_OK.
02196  */
02197 enum CRStatus
02198 cr_statement_at_charset_rule_get_charset (CRStatement *a_this,
02199                                           GString **a_charset)
02200 {
02201         g_return_val_if_fail (a_this
02202                               && a_this->type == AT_CHARSET_RULE_STMT
02203                               && a_this->kind.charset_rule,
02204                               CR_BAD_PARAM_ERROR) ;
02205 
02206         *a_charset = a_this->kind.charset_rule->charset ;
02207 
02208         return CR_OK ;
02209 }
02210 
02211 
02212 /**
02213  *Sets a declaration list to the current @font-face rule statement.
02214  *@param a_this the current @font-face rule statement.
02215  *@param a_decls the declarations list to set.
02216  *@return CR_OK upon successfull completion, an error code otherwise.
02217  */
02218 enum CRStatus
02219 cr_statement_at_font_face_rule_set_decls (CRStatement *a_this,
02220                                           CRDeclaration *a_decls)
02221 {
02222         g_return_val_if_fail (a_this 
02223                               && a_this->type == AT_FONT_FACE_RULE_STMT
02224                               && a_this->kind.font_face_rule,
02225                               CR_BAD_PARAM_ERROR) ;
02226 
02227         if (a_this->kind.font_face_rule->decl_list)
02228         {
02229                 cr_declaration_unref 
02230                         (a_this->kind.font_face_rule->decl_list) ;
02231         }
02232 
02233         a_this->kind.font_face_rule->decl_list = a_decls;
02234         cr_declaration_ref (a_decls) ;
02235         
02236         return CR_OK ;
02237 }
02238 
02239 
02240 /**
02241  *Gets the declaration list associated to the current instance
02242  *of @font-face rule statement.
02243  *@param a_this the current @font-face rule statement.
02244  *@param a_decls out parameter. The returned declaration list if
02245  *and only if this function returns CR_OK.
02246  *@return CR_OK upon successfull completion, an error code otherwise.
02247  */
02248 enum CRStatus
02249 cr_statement_at_font_face_rule_get_decls (CRStatement *a_this,
02250                                           CRDeclaration **a_decls)
02251 {
02252         g_return_val_if_fail (a_this 
02253                               && a_this->type == AT_FONT_FACE_RULE_STMT
02254                               && a_this->kind.font_face_rule,
02255                               CR_BAD_PARAM_ERROR) ;
02256 
02257         *a_decls = a_this->kind.font_face_rule->decl_list ;
02258         
02259         return CR_OK ;
02260 }
02261 
02262 
02263 /**
02264  *Adds a declaration to the current @font-face rule
02265  *statement.
02266  *@param a_this the current @font-face rule statement.
02267  *@param a_prop the property of the declaration.
02268  *@param a_value the value of the declaration.
02269  *@return CR_OK upon successfull completion, an error code otherwise.
02270  */
02271 enum CRStatus
02272 cr_statement_at_font_face_rule_add_decl (CRStatement *a_this,
02273                                          GString *a_prop,
02274                                          CRTerm *a_value)
02275 {
02276         CRDeclaration *decls = NULL ;
02277         
02278         g_return_val_if_fail (a_this 
02279                               && a_this->type == AT_FONT_FACE_RULE_STMT
02280                               && a_this->kind.font_face_rule,
02281                               CR_BAD_PARAM_ERROR) ;
02282 
02283         decls = cr_declaration_append2 
02284                 (a_this->kind.font_face_rule->decl_list,
02285                  a_prop, a_value) ;
02286 
02287         g_return_val_if_fail (decls, CR_ERROR) ;
02288                 
02289         if (a_this->kind.font_face_rule->decl_list == NULL)
02290                 cr_declaration_ref (decls) ;
02291 
02292         a_this->kind.font_face_rule->decl_list = decls ;
02293 
02294         return CR_OK ;
02295 }
02296 
02297 /**
02298  *Dumps the css2 statement to a file.
02299  *@param a_this the current css2 statement.
02300  *@param a_fp the destination file pointer.
02301  *@param a_indent the number of white space indentation characters.
02302  */
02303 void
02304 cr_statement_dump (CRStatement *a_this, FILE *a_fp, gulong a_indent)
02305 {
02306         g_return_if_fail (a_this) ;
02307 
02308         if (a_this->prev)
02309         {
02310                 fprintf (a_fp,"\n\n") ;
02311         }
02312 
02313         switch (a_this->type)
02314         {
02315         case RULESET_STMT:
02316                 cr_statement_dump_ruleset (a_this, a_fp, a_indent) ;
02317                 break ;
02318 
02319         case AT_FONT_FACE_RULE_STMT:
02320                 cr_statement_dump_font_face_rule 
02321                         (a_this, a_fp, a_indent);
02322                 break ;
02323 
02324         case AT_CHARSET_RULE_STMT:
02325                 cr_statement_dump_charset (a_this, a_fp, a_indent) ;
02326                 break ;
02327 
02328         case AT_PAGE_RULE_STMT:
02329                 cr_statement_dump_page (a_this, a_fp, a_indent) ;
02330                 break ;
02331 
02332         case AT_MEDIA_RULE_STMT:
02333                 cr_statement_dump_media_rule (a_this, a_fp, a_indent) ;
02334                 break ;
02335 
02336         case AT_IMPORT_RULE_STMT:
02337                 cr_statement_dump_import_rule (a_this, a_fp, a_indent) ;
02338                 break ;
02339 
02340         default :
02341                 fprintf (a_fp, "Statement unrecognized at %s:%d", 
02342                          __FILE__, __LINE__) ;
02343                 break ;
02344         }
02345 }
02346 
02347 /**
02348  *Destructor of #CRStatement.
02349  */
02350 void
02351 cr_statement_destroy (CRStatement *a_this)
02352 {
02353         CRStatement *cur = NULL ;
02354 
02355         g_return_if_fail (a_this) ;
02356         
02357         /*go get the tail of the list*/
02358         for (cur = a_this ; cur && cur->next; cur = cur->next)
02359         {
02360                 cr_statement_clear (cur) ;
02361         }
02362         
02363         if (cur)
02364                 cr_statement_clear (cur) ;
02365 
02366         if (cur->prev == NULL)
02367         {
02368                 g_free (a_this);
02369                 return ;
02370         }
02371 
02372         /*walk backward and free next element*/
02373         for (cur = cur->prev ; cur && cur->prev; cur = cur->prev)
02374         {
02375                 if (cur->next)
02376                 {
02377                         g_free (cur->next) ;
02378                         cur->next = NULL ;
02379                 }               
02380         }
02381 
02382         if (!cur)
02383                 return ;
02384 
02385         /*free the one remaining list*/
02386         if (cur->next)
02387         {
02388                 g_free (cur->next) ;            
02389                 cur->next = NULL ;
02390         }
02391 
02392         g_free (cur) ;
02393         cur = NULL ;
02394 }

Generated on Wed Oct 1 01:36:48 2003 for Libcroco by doxygen 1.3.3