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

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