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

cr-statement.c

Go to the documentation of this file.
00001 /* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
00002 
00003 /*
00004  * This file is part of The Croco Library
00005  *
00006  * 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  *Serializes the ruleset statement into a string
00579  *@param a_this the current instance of #CRStatement
00580  *@param a_indent the number of whitespace to use for indentation
00581  *@return the newly allocated serialised string. Must be freed
00582  *by the caller, using g_free().
00583  */
00584 static gchar *
00585 cr_statement_ruleset_to_string (CRStatement * a_this, glong a_indent)
00586 {
00587         GString *stringue = NULL;
00588         gchar *tmp_str = NULL,
00589                 *result = NULL;
00590 
00591         g_return_val_if_fail (a_this && a_this->type == RULESET_STMT, NULL);
00592 
00593         stringue = g_string_new (NULL);
00594 
00595         if (a_this->kind.ruleset->sel_list) {
00596                 if (a_indent)
00597                         cr_utils_dump_n_chars2 (' ', stringue, a_indent);
00598 
00599                 tmp_str =
00600                         cr_selector_to_string (a_this->kind.ruleset->
00601                                                sel_list);
00602                 if (tmp_str) {
00603                         g_string_append (stringue, tmp_str);
00604                         g_free (tmp_str);
00605                         tmp_str = NULL;
00606                 }
00607         }
00608         g_string_append (stringue, " {\n");
00609         if (a_this->kind.ruleset->decl_list) {
00610                 tmp_str = cr_declaration_list_to_string2
00611                         (a_this->kind.ruleset->decl_list,
00612                          a_indent + DECLARATION_INDENT_NB, TRUE);
00613                 if (tmp_str) {
00614                         g_string_append (stringue, tmp_str);
00615                         g_free (tmp_str);
00616                         tmp_str = NULL;
00617                 }
00618                 g_string_append (stringue, "\n");
00619                 cr_utils_dump_n_chars2 (' ', stringue, a_indent);
00620         }
00621         g_string_append (stringue, "}");
00622         result = stringue->str;
00623 
00624         if (stringue) {
00625                 g_string_free (stringue, FALSE);
00626                 stringue = NULL;
00627         }
00628         if (tmp_str) {
00629                 g_free (tmp_str);
00630                 tmp_str = NULL;
00631         }
00632         return result;
00633 }
00634 
00635 
00636 /**
00637  *Serializes a font face rule statement into a string.
00638  *@param a_this the current instance of #CRStatement to consider
00639  *It must be a font face rule statement.
00640  *@param a_indent the number of white spaces of indentation.
00641  *@return the serialized string. Must be deallocated by the caller
00642  *using g_free().
00643  */
00644 static gchar *
00645 cr_statement_font_face_rule_to_string (CRStatement * a_this, 
00646                                        glong a_indent)
00647 {
00648         gchar *result = NULL, *tmp_str = NULL ;
00649         GString *stringue = NULL ;
00650 
00651         g_return_val_if_fail (a_this 
00652                               && a_this->type == AT_FONT_FACE_RULE_STMT,
00653                               NULL);
00654 
00655         if (a_this->kind.font_face_rule->decl_list) {
00656                 stringue = g_string_new (NULL) ;
00657                 g_return_val_if_fail (stringue, NULL) ;
00658                 if (a_indent)
00659                         cr_utils_dump_n_chars2 (' ', stringue, 
00660                                         a_indent);
00661                 g_string_append (stringue, "@font-face {\n");
00662                 tmp_str = cr_declaration_list_to_string2 
00663                         (a_this->kind.font_face_rule->decl_list,
00664                          a_indent + DECLARATION_INDENT_NB, TRUE) ;
00665                 if (tmp_str) {
00666                         g_string_append (stringue,
00667                                          tmp_str) ;
00668                         g_free (tmp_str) ;
00669                         tmp_str = NULL ;
00670                 }
00671                 g_string_append (stringue, "\n}");
00672         }
00673         if (stringue) {
00674                 result = stringue->str ;
00675                 g_string_free (stringue, FALSE) ;
00676                 stringue = NULL ;
00677         }
00678         return result ;
00679 }
00680 
00681 
00682 /**
00683  *Serialises an @charset statement into a string.
00684  *@param a_this the statement to serialize.
00685  *@return the serialized charset statement. Must be
00686  *freed by the caller using g_free().
00687  */
00688 static gchar *
00689 cr_statement_charset_to_string (CRStatement *a_this, 
00690                                 gulong a_indent)
00691 {
00692         gchar *str = NULL ;
00693         GString *stringue = NULL ;
00694 
00695         g_return_val_if_fail (a_this
00696                               && a_this->type == AT_CHARSET_RULE_STMT,
00697                               NULL) ;
00698 
00699         if (a_this->kind.charset_rule
00700             && a_this->kind.charset_rule->charset
00701             && a_this->kind.charset_rule->charset->stryng
00702             && a_this->kind.charset_rule->charset->stryng->str) {
00703                 str = g_strndup (a_this->kind.charset_rule->charset->stryng->str,
00704                                  a_this->kind.charset_rule->charset->stryng->len);
00705                 g_return_val_if_fail (str, NULL);
00706                 stringue = g_string_new (NULL) ;
00707                 g_return_val_if_fail (stringue, NULL) ;
00708                 cr_utils_dump_n_chars2 (' ', stringue, a_indent);
00709                 g_string_append_printf (stringue, 
00710                                         "@charset \"%s\" ;", str);
00711                 if (str) {
00712                         g_free (str);
00713                         str = NULL;
00714                 }
00715         }
00716         if (stringue) {
00717                 str = stringue->str ;
00718                 g_string_free (stringue, FALSE) ;
00719         }
00720         return str ;
00721 }
00722 
00723 
00724 /**
00725  *Serialises the at page rule statement into a string
00726  *@param a_this the current instance of #CRStatement. Must
00727  *be an "@page" rule statement.
00728  *@return the serialized string. Must be freed by the caller
00729  */
00730 static gchar *
00731 cr_statement_at_page_rule_to_string (CRStatement *a_this,
00732                                      gulong a_indent)
00733 {
00734         GString *stringue = NULL;
00735         gchar *result = NULL ;
00736 
00737         stringue = g_string_new (NULL) ;
00738 
00739         cr_utils_dump_n_chars2 (' ', stringue, a_indent) ;
00740         g_string_append (stringue, "@page");
00741         if (a_this->kind.page_rule->name
00742             && a_this->kind.page_rule->name->stryng) {
00743                 g_string_append_printf 
00744                   (stringue, " %s",
00745                    a_this->kind.page_rule->name->stryng->str) ;
00746         } else {
00747                 g_string_append (stringue, " ");
00748         }
00749         if (a_this->kind.page_rule->pseudo
00750             && a_this->kind.page_rule->pseudo->stryng) {
00751                 g_string_append_printf 
00752                   (stringue,  " :%s",
00753                    a_this->kind.page_rule->pseudo->stryng->str) ;
00754         }
00755         if (a_this->kind.page_rule->decl_list) {
00756                 gchar *str = NULL ;
00757                 g_string_append (stringue, " {\n");
00758                 str = cr_declaration_list_to_string2
00759                         (a_this->kind.page_rule->decl_list,
00760                          a_indent + DECLARATION_INDENT_NB, TRUE) ;
00761                 if (str) {
00762                         g_string_append (stringue, str) ;
00763                         g_free (str) ;
00764                         str = NULL ;
00765                 }
00766                 g_string_append (stringue, "\n}\n");
00767         }
00768         result = stringue->str ;
00769         g_string_free (stringue, FALSE) ;
00770         stringue = NULL ;
00771         return result ;
00772 }
00773 
00774 
00775 /**
00776  *Serializes an @media statement.
00777  *@param a_this the current instance of #CRStatement
00778  *@param a_indent the number of spaces of indentation.
00779  *@return the serialized @media statement. Must be freed
00780  *by the caller using g_free().
00781  */
00782 static gchar *
00783 cr_statement_media_rule_to_string (CRStatement *a_this,
00784                                    gulong a_indent)
00785 {
00786         gchar *str = NULL ;
00787         GString *stringue = NULL ;
00788         GList *cur = NULL;
00789 
00790         g_return_val_if_fail (a_this->type == AT_MEDIA_RULE_STMT,
00791                               NULL);
00792 
00793         if (a_this->kind.media_rule) {
00794                 stringue = g_string_new (NULL) ;                
00795                 cr_utils_dump_n_chars2 (' ', stringue, a_indent);
00796                 g_string_append (stringue, "@media");
00797 
00798                 for (cur = a_this->kind.media_rule->media_list; cur;
00799                      cur = cur->next) {
00800                         if (cur->data) {
00801                                 guchar *str = cr_string_dup2
00802                                         ((CRString *) cur->data);
00803 
00804                                 if (str) {
00805                                         if (cur->prev) {
00806                                                 g_string_append
00807                                                         (stringue, 
00808                                                          ",");
00809                                         }
00810                                         g_string_append_printf 
00811                                                 (stringue, 
00812                                                  " %s", str);
00813                                         g_free (str);
00814                                         str = NULL;
00815                                 }
00816                         }
00817                 }
00818                 g_string_append (stringue, " {\n");
00819                 str = cr_statement_list_to_string
00820                         (a_this->kind.media_rule->rulesets,
00821                          a_indent + DECLARATION_INDENT_NB) ;
00822                 if (str) {
00823                         g_string_append (stringue, str) ;
00824                         g_free (str) ;
00825                         str = NULL ;
00826                 }
00827                 g_string_append (stringue, "\n}");
00828         }
00829         if (stringue) {
00830                 str = stringue->str ;
00831                 g_string_free (stringue, FALSE) ;
00832         }
00833         return str ;
00834 }
00835 
00836 
00837 static gchar *
00838 cr_statement_import_rule_to_string (CRStatement *a_this,
00839                                     gulong a_indent)
00840 {
00841         GString *stringue = NULL ;
00842         guchar *str = NULL;
00843 
00844         g_return_val_if_fail (a_this
00845                               && a_this->type == AT_IMPORT_RULE_STMT
00846                               && a_this->kind.import_rule,
00847                               NULL) ;
00848 
00849         if (a_this->kind.import_rule->url
00850             && a_this->kind.import_rule->url->stryng) { 
00851                 stringue = g_string_new (NULL) ;
00852                 g_return_val_if_fail (stringue, NULL) ;
00853                 str = g_strndup (a_this->kind.import_rule->url->stryng->str,
00854                                  a_this->kind.import_rule->url->stryng->len);
00855                 cr_utils_dump_n_chars2 (' ', stringue, a_indent);
00856                 if (str) {
00857                         g_string_append_printf (stringue,
00858                                                 "@import url(\"%s\")", 
00859                                                 str);
00860                         g_free (str);
00861                         str = NULL ;
00862                 } else          /*there is no url, so no import rule, get out! */
00863                         return NULL;
00864 
00865                 if (a_this->kind.import_rule->media_list) {
00866                         GList *cur = NULL;
00867 
00868                         for (cur = a_this->kind.import_rule->media_list;
00869                              cur; cur = cur->next) {
00870                                 if (cur->data) {
00871                                         CRString *crstr = cur->data;
00872 
00873                                         if (cur->prev) {
00874                                                 g_string_append 
00875                                                         (stringue, ", ");
00876                                         }
00877                                         if (crstr 
00878                                             && crstr->stryng
00879                                             && crstr->stryng->str) {
00880                                                 g_string_append_len 
00881                                                         (stringue,
00882                                                          crstr->stryng->str,
00883                                                          crstr->stryng->len) ;
00884                                         }
00885                                 }
00886                         }
00887                 }
00888                 g_string_append (stringue, " ;");
00889         }
00890         if (stringue) {
00891                 str = stringue->str ;
00892                 g_string_free (stringue, FALSE) ;
00893                 stringue = NULL ;
00894         }
00895         return str ;
00896 }
00897 
00898 
00899 /*******************
00900  *public functions
00901  ******************/
00902 
00903 /**
00904  *Tries to parse a buffer and says whether if the content of the buffer
00905  *is a css statement as defined by the "Core CSS Grammar" (chapter 4 of the
00906  *css spec) or not.
00907  *@param a_buf the buffer to parse.
00908  *@param a_encoding the character encoding of a_buf.
00909  *@return TRUE if the buffer parses against the core grammar, false otherwise.
00910  */
00911 gboolean
00912 cr_statement_does_buf_parses_against_core (const guchar * a_buf,
00913                                            enum CREncoding a_encoding)
00914 {
00915         CRParser *parser = NULL;
00916         enum CRStatus status = CR_OK;
00917         gboolean result = FALSE;
00918 
00919         parser = cr_parser_new_from_buf ((guchar*)a_buf, strlen (a_buf),
00920                                          a_encoding, FALSE);
00921         g_return_val_if_fail (parser, FALSE);
00922 
00923         status = cr_parser_set_use_core_grammar (parser, TRUE);
00924         if (status != CR_OK) {
00925                 goto cleanup;
00926         }
00927 
00928         status = cr_parser_parse_statement_core (parser);
00929         if (status == CR_OK) {
00930                 result = TRUE;
00931         }
00932 
00933       cleanup:
00934         if (parser) {
00935                 cr_parser_destroy (parser);
00936         }
00937 
00938         return result;
00939 }
00940 
00941 /**
00942  *Parses a buffer that contains a css statement and returns 
00943  *an instance of #CRStatement in case of successfull parsing.
00944  *TODO: at support of "@import" rules.
00945  *@param a_buf the buffer to parse.
00946  *@param a_encoding the character encoding of a_buf.
00947  *@return the newly built instance of #CRStatement in case
00948  *of successfull parsing, NULL otherwise.
00949  */
00950 CRStatement *
00951 cr_statement_parse_from_buf (const guchar * a_buf, enum CREncoding a_encoding)
00952 {
00953         CRStatement *result = NULL;
00954 
00955         /*
00956          *The strategy of this function is "brute force".
00957          *It tries to parse all the types of #CRStatement it knows about.
00958          *I could do this a smarter way but I don't have the time now.
00959          *I think I will revisit this when time of performances and
00960          *pull based incremental parsing comes.
00961          */
00962 
00963         result = cr_statement_ruleset_parse_from_buf (a_buf, a_encoding);
00964         if (!result) {
00965                 result = cr_statement_at_charset_rule_parse_from_buf
00966                         (a_buf, a_encoding);
00967         } else {
00968                 goto out;
00969         }
00970 
00971         if (!result) {
00972                 result = cr_statement_at_media_rule_parse_from_buf
00973                         (a_buf, a_encoding);
00974         } else {
00975                 goto out;
00976         }
00977 
00978         if (!result) {
00979                 result = cr_statement_at_charset_rule_parse_from_buf
00980                         (a_buf, a_encoding);
00981         } else {
00982                 goto out;
00983         }
00984 
00985         if (!result) {
00986                 result = cr_statement_font_face_rule_parse_from_buf
00987                         (a_buf, a_encoding);
00988 
00989         } else {
00990                 goto out;
00991         }
00992 
00993         if (!result) {
00994                 result = cr_statement_at_page_rule_parse_from_buf
00995                         (a_buf, a_encoding);
00996         } else {
00997                 goto out;
00998         }
00999 
01000         if (!result) {
01001                 result = cr_statement_at_import_rule_parse_from_buf
01002                         (a_buf, a_encoding);
01003         } else {
01004                 goto out;
01005         }
01006 
01007       out:
01008         return result;
01009 }
01010 
01011 /**
01012  *Parses a buffer that contains a ruleset statement an instanciates
01013  *a #CRStatement of type RULESET_STMT.
01014  *@param a_buf the buffer to parse.
01015  *@param a_enc the character encoding of a_buf.
01016  *@param the newly built instance of #CRStatement in case of successfull parsing,
01017  *NULL otherwise.
01018  */
01019 CRStatement *
01020 cr_statement_ruleset_parse_from_buf (const guchar * a_buf,
01021                                      enum CREncoding a_enc)
01022 {
01023         enum CRStatus status = CR_OK;
01024         CRStatement *result = NULL;
01025         CRStatement **resultptr = NULL;
01026         CRParser *parser = NULL;
01027         CRDocHandler *sac_handler = NULL;
01028 
01029         g_return_val_if_fail (a_buf, NULL);
01030 
01031         parser = cr_parser_new_from_buf ((guchar*)a_buf, strlen (a_buf), 
01032                                          a_enc, FALSE);
01033 
01034         g_return_val_if_fail (parser, NULL);
01035 
01036         sac_handler = cr_doc_handler_new ();
01037         g_return_val_if_fail (parser, NULL);
01038 
01039         sac_handler->start_selector = parse_ruleset_start_selector_cb;
01040         sac_handler->end_selector = parse_ruleset_end_selector_cb;
01041         sac_handler->property = parse_ruleset_property_cb;
01042         sac_handler->unrecoverable_error =
01043                 parse_ruleset_unrecoverable_error_cb;
01044 
01045         cr_parser_set_sac_handler (parser, sac_handler);
01046         cr_parser_try_to_skip_spaces_and_comments (parser);
01047         status = cr_parser_parse_ruleset (parser);
01048         if (status != CR_OK) {
01049                 goto cleanup;
01050         }
01051 
01052         resultptr = &result;
01053         status = cr_doc_handler_get_result (sac_handler,
01054                                             (gpointer *) resultptr);
01055         if (!((status == CR_OK) && result)) {
01056                 if (result) {
01057                         cr_statement_destroy (result);
01058                         result = NULL;
01059                 }
01060         }
01061 
01062       cleanup:
01063         if (parser) {
01064                 cr_parser_destroy (parser);
01065                 parser = NULL;
01066                 sac_handler = NULL ;
01067         }
01068         if (sac_handler) {
01069                 cr_doc_handler_unref (sac_handler);
01070                 sac_handler = NULL;
01071         }
01072         return result;
01073 }
01074 
01075 /**
01076  *Creates a new instance of #CRStatement of type
01077  *#CRRulSet.
01078  *@param a_sel_list the list of #CRSimpleSel (selectors)
01079  *the rule applies to.
01080  *@param a_decl_list the list of instances of #CRDeclaration
01081  *that composes the ruleset.
01082  *@param a_media_types a list of instances of GString that
01083  *describe the media list this ruleset applies to.
01084  *@return the new instance of #CRStatement or NULL if something
01085  *went wrong.
01086  */
01087 CRStatement *
01088 cr_statement_new_ruleset (CRStyleSheet * a_sheet,
01089                           CRSelector * a_sel_list,
01090                           CRDeclaration * a_decl_list,
01091                           CRStatement * a_parent_media_rule)
01092 {
01093         CRStatement *result = NULL;
01094 
01095         g_return_val_if_fail (a_sel_list, NULL);
01096 
01097         if (a_parent_media_rule) {
01098                 g_return_val_if_fail
01099                         (a_parent_media_rule->type == AT_MEDIA_RULE_STMT,
01100                          NULL);
01101                 g_return_val_if_fail (a_parent_media_rule->kind.media_rule,
01102                                       NULL);
01103         }
01104 
01105         result = g_try_malloc (sizeof (CRStatement));
01106 
01107         if (!result) {
01108                 cr_utils_trace_info ("Out of memory");
01109                 return NULL;
01110         }
01111 
01112         memset (result, 0, sizeof (CRStatement));
01113         result->type = RULESET_STMT;
01114         result->kind.ruleset = g_try_malloc (sizeof (CRRuleSet));
01115 
01116         if (!result->kind.ruleset) {
01117                 cr_utils_trace_info ("Out of memory");
01118                 if (result)
01119                         g_free (result);
01120                 return NULL;
01121         }
01122 
01123         memset (result->kind.ruleset, 0, sizeof (CRRuleSet));
01124         result->kind.ruleset->sel_list = a_sel_list;
01125         if (a_sel_list)
01126                 cr_selector_ref (a_sel_list);
01127         result->kind.ruleset->decl_list = a_decl_list;
01128 
01129         if (a_parent_media_rule) {
01130                 result->kind.ruleset->parent_media_rule = a_parent_media_rule;
01131                 a_parent_media_rule->kind.media_rule->rulesets =
01132                         cr_statement_append
01133                         (a_parent_media_rule->kind.media_rule->rulesets,
01134                          result);
01135         }
01136 
01137         cr_statement_set_parent_sheet (result, a_sheet);
01138 
01139         return result;
01140 }
01141 
01142 /**
01143  *Parses a buffer that contains an "@media" declaration
01144  *and builds an @media css statement.
01145  *@param a_buf the input to parse.
01146  *@param a_enc the encoding of the buffer.
01147  *@return the @media statement, or NULL if the buffer could not
01148  *be successfully parsed.
01149  */
01150 CRStatement *
01151 cr_statement_at_media_rule_parse_from_buf (const guchar * a_buf,
01152                                            enum CREncoding a_enc)
01153 {
01154         CRParser *parser = NULL;
01155         CRStatement *result = NULL;
01156         CRStatement **resultptr = NULL;
01157         CRDocHandler *sac_handler = NULL;
01158         enum CRStatus status = CR_OK;
01159 
01160         parser = cr_parser_new_from_buf ((guchar*)a_buf, strlen (a_buf), 
01161                                          a_enc, FALSE);
01162         if (!parser) {
01163                 cr_utils_trace_info ("Instanciation of the parser failed");
01164                 goto cleanup;
01165         }
01166 
01167         sac_handler = cr_doc_handler_new ();
01168         if (!sac_handler) {
01169                 cr_utils_trace_info
01170                         ("Instanciation of the sac handler failed");
01171                 goto cleanup;
01172         }
01173 
01174         sac_handler->start_media = parse_at_media_start_media_cb;
01175         sac_handler->start_selector = parse_at_media_start_selector_cb;
01176         sac_handler->property = parse_at_media_property_cb;
01177         sac_handler->end_selector = parse_at_media_end_selector_cb;
01178         sac_handler->end_media = parse_at_media_end_media_cb;
01179         sac_handler->unrecoverable_error =
01180                 parse_at_media_unrecoverable_error_cb;
01181 
01182         status = cr_parser_set_sac_handler (parser, sac_handler);
01183         if (status != CR_OK)
01184                 goto cleanup;
01185 
01186         status = cr_parser_try_to_skip_spaces_and_comments (parser);
01187         if (status != CR_OK)
01188                 goto cleanup;
01189 
01190         status = cr_parser_parse_media (parser);
01191         if (status != CR_OK)
01192                 goto cleanup;
01193 
01194         resultptr = &result;
01195         status = cr_doc_handler_get_result (sac_handler,
01196                                             (gpointer *) resultptr);
01197         if (status != CR_OK)
01198                 goto cleanup;
01199 
01200       cleanup:
01201 
01202         if (parser) {
01203                 cr_parser_destroy (parser);
01204                 parser = NULL;
01205                 sac_handler = NULL ;
01206         }
01207         if (sac_handler) {
01208                 cr_doc_handler_unref (sac_handler);
01209                 sac_handler = NULL;
01210         }
01211 
01212         return result;
01213 }
01214 
01215 /**
01216  *Instanciates an instance of #CRStatement of type
01217  *AT_MEDIA_RULE_STMT (@media ruleset).
01218  *@param a_ruleset the ruleset statements contained
01219  *in the @media rule.
01220  *@param a_media, the media string list. A list of GString pointers.
01221  */
01222 CRStatement *
01223 cr_statement_new_at_media_rule (CRStyleSheet * a_sheet,
01224                                 CRStatement * a_rulesets, GList * a_media)
01225 {
01226         CRStatement *result = NULL,
01227                 *cur = NULL;
01228 
01229         if (a_rulesets)
01230                 g_return_val_if_fail (a_rulesets->type == RULESET_STMT, NULL);
01231 
01232         result = g_try_malloc (sizeof (CRStatement));
01233 
01234         if (!result) {
01235                 cr_utils_trace_info ("Out of memory");
01236                 return NULL;
01237         }
01238 
01239         memset (result, 0, sizeof (CRStatement));
01240         result->type = AT_MEDIA_RULE_STMT;
01241 
01242         result->kind.media_rule = g_try_malloc (sizeof (CRAtMediaRule));
01243         if (!result->kind.media_rule) {
01244                 cr_utils_trace_info ("Out of memory");
01245                 g_free (result);
01246                 return NULL;
01247         }
01248         memset (result->kind.media_rule, 0, sizeof (CRAtMediaRule));
01249         result->kind.media_rule->rulesets = a_rulesets;
01250         for (cur = a_rulesets; cur; cur = cur->next) {
01251                 if (cur->type != RULESET_STMT || !cur->kind.ruleset) {
01252                         cr_utils_trace_info ("Bad parameter a_rulesets. "
01253                                              "It should be a list of "
01254                                              "correct ruleset statement only !");
01255                         goto error;
01256                 }
01257                 cur->kind.ruleset->parent_media_rule = result;
01258         }
01259 
01260         result->kind.media_rule->media_list = a_media;
01261         if (a_sheet) {
01262                 cr_statement_set_parent_sheet (result, a_sheet);
01263         }
01264 
01265         return result;
01266 
01267       error:
01268         return NULL;
01269 }
01270 
01271 /**
01272  *Creates a new instance of #CRStatment of type
01273  *#CRAtImportRule.
01274  *@param a_url the url to connect to the get the file
01275  *to be imported.
01276  *@param a_sheet the imported parsed stylesheet.
01277  *@return the newly built instance of #CRStatement.
01278  */
01279 CRStatement *
01280 cr_statement_new_at_import_rule (CRStyleSheet * a_container_sheet,
01281                                  CRString * a_url,
01282                                  GList * a_media_list,
01283                                  CRStyleSheet * a_imported_sheet)
01284 {
01285         CRStatement *result = NULL;
01286 
01287         result = g_try_malloc (sizeof (CRStatement));
01288 
01289         if (!result) {
01290                 cr_utils_trace_info ("Out of memory");
01291                 return NULL;
01292         }
01293 
01294         memset (result, 0, sizeof (CRStatement));
01295         result->type = AT_IMPORT_RULE_STMT;
01296 
01297         result->kind.import_rule = g_try_malloc (sizeof (CRAtImportRule));
01298 
01299         if (!result->kind.import_rule) {
01300                 cr_utils_trace_info ("Out of memory");
01301                 g_free (result);
01302                 return NULL;
01303         }
01304 
01305         memset (result->kind.import_rule, 0, sizeof (CRAtImportRule));
01306         result->kind.import_rule->url = a_url;
01307         result->kind.import_rule->media_list = a_media_list;
01308         result->kind.import_rule->sheet = a_imported_sheet;
01309         if (a_container_sheet)
01310                 cr_statement_set_parent_sheet (result, a_container_sheet);
01311 
01312         return result;
01313 }
01314 
01315 /**
01316  *Parses a buffer that contains an "@import" rule and
01317  *instanciate a #CRStatement of type AT_IMPORT_RULE_STMT
01318  *@param a_buf the buffer to parse.
01319  *@param a_encoding the encoding of a_buf.
01320  *@return the newly built instance of #CRStatement in case of 
01321  *a successfull parsing, NULL otherwise.
01322  */
01323 CRStatement *
01324 cr_statement_at_import_rule_parse_from_buf (const guchar * a_buf,
01325                                             enum CREncoding a_encoding)
01326 {
01327         enum CRStatus status = CR_OK;
01328         CRParser *parser = NULL;
01329         CRStatement *result = NULL;
01330         GList *media_list = NULL;
01331         CRString *import_string = NULL;
01332         CRParsingLocation location = {0} ;
01333 
01334         parser = cr_parser_new_from_buf ((guchar*)a_buf, strlen (a_buf),
01335                                          a_encoding, FALSE);
01336         if (!parser) {
01337                 cr_utils_trace_info ("Instanciation of parser failed.");
01338                 goto cleanup;
01339         }
01340 
01341         status = cr_parser_try_to_skip_spaces_and_comments (parser);
01342         if (status != CR_OK)
01343                 goto cleanup;
01344 
01345         status = cr_parser_parse_import (parser,
01346                                          &media_list, 
01347                                          &import_string,
01348                                          &location);
01349         if (status != CR_OK || !import_string)
01350                 goto cleanup;
01351 
01352         result = cr_statement_new_at_import_rule (NULL, import_string,
01353                                                   media_list, NULL);
01354         if (result) {
01355                 cr_parsing_location_copy (&result->location,
01356                                           &location) ;
01357                 import_string = NULL;
01358                 media_list = NULL;
01359         }
01360 
01361  cleanup:
01362         if (parser) {
01363                 cr_parser_destroy (parser);
01364                 parser = NULL;
01365         }
01366         if (media_list) {
01367                 GList *cur = NULL;
01368 
01369                 for (cur = media_list; media_list;
01370                      media_list = g_list_next (media_list)) {
01371                         if (media_list->data) {
01372                                 cr_string_destroy ((CRString*)media_list->data);
01373                                 media_list->data = NULL;
01374                         }
01375                 }
01376                 g_list_free (media_list);
01377                 media_list = NULL;
01378         }
01379         if (import_string) {
01380                 cr_string_destroy (import_string);
01381                 import_string = NULL;
01382         }
01383 
01384         return result;
01385 }
01386 
01387 /**
01388  *Creates a new instance of #CRStatement of type
01389  *#CRAtPageRule.
01390  *@param a_decl_list a list of instances of #CRDeclarations
01391  *which is actually the list of declarations that applies to
01392  *this page rule.
01393  *@param a_selector the page rule selector.
01394  *@return the newly built instance of #CRStatement or NULL
01395  *in case of error.
01396  */
01397 CRStatement *
01398 cr_statement_new_at_page_rule (CRStyleSheet * a_sheet,
01399                                CRDeclaration * a_decl_list,
01400                                CRString * a_name, CRString * a_pseudo)
01401 {
01402         CRStatement *result = NULL;
01403 
01404         result = g_try_malloc (sizeof (CRStatement));
01405 
01406         if (!result) {
01407                 cr_utils_trace_info ("Out of memory");
01408                 return NULL;
01409         }
01410 
01411         memset (result, 0, sizeof (CRStatement));
01412         result->type = AT_PAGE_RULE_STMT;
01413 
01414         result->kind.page_rule = g_try_malloc (sizeof (CRAtPageRule));
01415 
01416         if (!result->kind.page_rule) {
01417                 cr_utils_trace_info ("Out of memory");
01418                 g_free (result);
01419                 return NULL;
01420         }
01421 
01422         memset (result->kind.page_rule, 0, sizeof (CRAtPageRule));
01423         if (a_decl_list) {
01424                 result->kind.page_rule->decl_list = a_decl_list;
01425                 cr_declaration_ref (a_decl_list);
01426         }
01427         result->kind.page_rule->name = a_name;
01428         result->kind.page_rule->pseudo = a_pseudo;
01429         if (a_sheet)
01430                 cr_statement_set_parent_sheet (result, a_sheet);
01431 
01432         return result;
01433 }
01434 
01435 /**
01436  *Parses a buffer that contains an "@page" production and,
01437  *if the parsing succeeds, builds the page statement.
01438  *@param a_buf the character buffer to parse.
01439  *@param a_encoding the character encoding of a_buf.
01440  *@return the newly built at page statement in case of successfull parsing,
01441  *NULL otherwise.
01442  */
01443 CRStatement *
01444 cr_statement_at_page_rule_parse_from_buf (const guchar * a_buf,
01445                                           enum CREncoding a_encoding)
01446 {
01447         enum CRStatus status = CR_OK;
01448         CRParser *parser = NULL;
01449         CRDocHandler *sac_handler = NULL;
01450         CRStatement *result = NULL;
01451         CRStatement **resultptr = NULL;
01452 
01453         g_return_val_if_fail (a_buf, NULL);
01454 
01455         parser = cr_parser_new_from_buf ((guchar*)a_buf, strlen (a_buf),
01456                                          a_encoding, FALSE);
01457         if (!parser) {
01458                 cr_utils_trace_info ("Instanciation of the parser failed.");
01459                 goto cleanup;
01460         }
01461 
01462         sac_handler = cr_doc_handler_new ();
01463         if (!sac_handler) {
01464                 cr_utils_trace_info
01465                         ("Instanciation of the sac handler failed.");
01466                 goto cleanup;
01467         }
01468 
01469         sac_handler->start_page = parse_page_start_page_cb;
01470         sac_handler->property = parse_page_property_cb;
01471         sac_handler->end_page = parse_page_end_page_cb;
01472         sac_handler->unrecoverable_error = parse_page_unrecoverable_error_cb;
01473 
01474         status = cr_parser_set_sac_handler (parser, sac_handler);
01475         if (status != CR_OK)
01476                 goto cleanup;
01477 
01478         /*Now, invoke the parser to parse the "@page production" */
01479         cr_parser_try_to_skip_spaces_and_comments (parser);
01480         if (status != CR_OK)
01481                 goto cleanup;
01482         status = cr_parser_parse_page (parser);
01483         if (status != CR_OK)
01484                 goto cleanup;
01485 
01486         resultptr = &result;
01487         status = cr_doc_handler_get_result (sac_handler,
01488                                             (gpointer *) resultptr);
01489 
01490       cleanup:
01491 
01492         if (parser) {
01493                 cr_parser_destroy (parser);
01494                 parser = NULL;
01495                 sac_handler = NULL ;
01496         }
01497         if (sac_handler) {
01498                 cr_doc_handler_unref (sac_handler);
01499                 sac_handler = NULL;
01500         }
01501         return result;
01502 }
01503 
01504 /**
01505  *Creates a new instance of #CRStatement of type
01506  *#CRAtCharsetRule.
01507  *@param a_charset the string representing the charset.
01508  *Note that the newly built instance of #CRStatement becomes
01509  *the owner of a_charset. The caller must not free a_charset !!!.
01510  *@return the newly built instance of #CRStatement or NULL
01511  *if an error arises.
01512  */
01513 CRStatement *
01514 cr_statement_new_at_charset_rule (CRStyleSheet * a_sheet, 
01515                                   CRString * a_charset)
01516 {
01517         CRStatement *result = NULL;
01518 
01519         g_return_val_if_fail (a_charset, NULL);
01520 
01521         result = g_try_malloc (sizeof (CRStatement));
01522 
01523         if (!result) {
01524                 cr_utils_trace_info ("Out of memory");
01525                 return NULL;
01526         }
01527 
01528         memset (result, 0, sizeof (CRStatement));
01529         result->type = AT_CHARSET_RULE_STMT;
01530 
01531         result->kind.charset_rule = g_try_malloc (sizeof (CRAtCharsetRule));
01532 
01533         if (!result->kind.charset_rule) {
01534                 cr_utils_trace_info ("Out of memory");
01535                 g_free (result);
01536                 return NULL;
01537         }
01538         memset (result->kind.charset_rule, 0, sizeof (CRAtCharsetRule));
01539         result->kind.charset_rule->charset = a_charset;
01540         cr_statement_set_parent_sheet (result, a_sheet);
01541 
01542         return result;
01543 }
01544 
01545 /**
01546  *Parses a buffer that contains an '@charset' rule and
01547  *creates an instance of #CRStatement of type AT_CHARSET_RULE_STMT.
01548  *@param a_buf the buffer to parse.
01549  *@param the character encoding of the buffer.
01550  *@return the newly built instance of #CRStatement.
01551  */
01552 CRStatement *
01553 cr_statement_at_charset_rule_parse_from_buf (const guchar * a_buf,
01554                                              enum CREncoding a_encoding)
01555 {
01556         enum CRStatus status = CR_OK;
01557         CRParser *parser = NULL;
01558         CRStatement *result = NULL;
01559         CRString *charset = NULL;
01560 
01561         g_return_val_if_fail (a_buf, NULL);
01562 
01563         parser = cr_parser_new_from_buf ((guchar*)a_buf, strlen (a_buf),
01564                                          a_encoding, FALSE);
01565         if (!parser) {
01566                 cr_utils_trace_info ("Instanciation of the parser failed.");
01567                 goto cleanup;
01568         }
01569 
01570         /*Now, invoke the parser to parse the "@charset production" */
01571         cr_parser_try_to_skip_spaces_and_comments (parser);
01572         if (status != CR_OK)
01573                 goto cleanup;
01574         status = cr_parser_parse_charset (parser, &charset, NULL);
01575         if (status != CR_OK || !charset)
01576                 goto cleanup;
01577 
01578         result = cr_statement_new_at_charset_rule (NULL, charset);
01579         if (result)
01580                 charset = NULL;
01581 
01582       cleanup:
01583 
01584         if (parser) {
01585                 cr_parser_destroy (parser);
01586                 parser = NULL;
01587         }
01588         if (charset) {
01589                 cr_string_destroy (charset);
01590         }
01591 
01592         return result;
01593 }
01594 
01595 /**
01596  *Creates an instance of #CRStatement of type #CRAtFontFaceRule.
01597  *@param a_font_decls a list of instances of #CRDeclaration. Each declaration
01598  *is actually a font declaration.
01599  *@return the newly built instance of #CRStatement.
01600  */
01601 CRStatement *
01602 cr_statement_new_at_font_face_rule (CRStyleSheet * a_sheet,
01603                                     CRDeclaration * a_font_decls)
01604 {
01605         CRStatement *result = NULL;
01606 
01607         result = g_try_malloc (sizeof (CRStatement));
01608 
01609         if (!result) {
01610                 cr_utils_trace_info ("Out of memory");
01611                 return NULL;
01612         }
01613         memset (result, 0, sizeof (CRStatement));
01614         result->type = AT_FONT_FACE_RULE_STMT;
01615 
01616         result->kind.font_face_rule = g_try_malloc
01617                 (sizeof (CRAtFontFaceRule));
01618 
01619         if (!result->kind.font_face_rule) {
01620                 cr_utils_trace_info ("Out of memory");
01621                 g_free (result);
01622                 return NULL;
01623         }
01624         memset (result->kind.font_face_rule, 0, sizeof (CRAtFontFaceRule));
01625 
01626         result->kind.font_face_rule->decl_list = a_font_decls;
01627         if (a_sheet)
01628                 cr_statement_set_parent_sheet (result, a_sheet);
01629 
01630         return result;
01631 }
01632 
01633 /**
01634  *Parses a buffer that contains an "@font-face" rule and builds
01635  *an instance of #CRStatement of type AT_FONT_FACE_RULE_STMT out of it.
01636  *@param a_buf the buffer to parse.
01637  *@param a_encoding the character encoding of a_buf.
01638  *@return the newly built instance of #CRStatement in case of successufull
01639  *parsing, NULL otherwise.
01640  */
01641 CRStatement *
01642 cr_statement_font_face_rule_parse_from_buf (const guchar * a_buf,
01643                                             enum CREncoding a_encoding)
01644 {
01645         CRStatement *result = NULL;
01646         CRStatement **resultptr = NULL;
01647         CRParser *parser = NULL;
01648         CRDocHandler *sac_handler = NULL;
01649         enum CRStatus status = CR_OK;
01650 
01651         parser = cr_parser_new_from_buf ((guchar*)a_buf, strlen (a_buf),
01652                                          a_encoding, FALSE);
01653         if (!parser)
01654                 goto cleanup;
01655 
01656         sac_handler = cr_doc_handler_new ();
01657         if (!sac_handler)
01658                 goto cleanup;
01659 
01660         /*
01661          *set sac callbacks here
01662          */
01663         sac_handler->start_font_face = parse_font_face_start_font_face_cb;
01664         sac_handler->property = parse_font_face_property_cb;
01665         sac_handler->end_font_face = parse_font_face_end_font_face_cb;
01666         sac_handler->unrecoverable_error =
01667                 parse_font_face_unrecoverable_error_cb;
01668 
01669         status = cr_parser_set_sac_handler (parser, sac_handler);
01670         if (status != CR_OK)
01671                 goto cleanup;
01672 
01673         /*
01674          *cleanup spaces of comment that may be there before the real
01675          *"@font-face" thing.
01676          */
01677         status = cr_parser_try_to_skip_spaces_and_comments (parser);
01678         if (status != CR_OK)
01679                 goto cleanup;
01680 
01681         status = cr_parser_parse_font_face (parser);
01682         if (status != CR_OK)
01683                 goto cleanup;
01684 
01685         resultptr = &result;
01686         status = cr_doc_handler_get_result (sac_handler,
01687                                             (gpointer *) resultptr);
01688         if (status != CR_OK || !result)
01689                 goto cleanup;
01690 
01691       cleanup:
01692         if (parser) {
01693                 cr_parser_destroy (parser);
01694                 parser = NULL;
01695                 sac_handler = NULL ;
01696         }
01697         if (sac_handler) {
01698                 cr_doc_handler_unref (sac_handler);
01699                 sac_handler = NULL;
01700         }
01701         return result;
01702 }
01703 
01704 /**
01705  *Sets the container stylesheet.
01706  *@param a_this the current instance of #CRStatement.
01707  *@param a_sheet the sheet that contains the current statement.
01708  *@return CR_OK upon successfull completion, an errror code otherwise.
01709  */
01710 enum CRStatus
01711 cr_statement_set_parent_sheet (CRStatement * a_this, CRStyleSheet * a_sheet)
01712 {
01713         g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
01714         a_this->parent_sheet = a_sheet;
01715         return CR_OK;
01716 }
01717 
01718 /**
01719  *Gets the sheets that contains the current statement.
01720  *@param a_this the current #CRStatement.
01721  *@param a_sheet out parameter. A pointer to the sheets that
01722  *@return CR_OK upon successfull completion, an error code otherwise.
01723  */
01724 enum CRStatus
01725 cr_statement_get_parent_sheet (CRStatement * a_this, CRStyleSheet ** a_sheet)
01726 {
01727         g_return_val_if_fail (a_this && a_sheet, CR_BAD_PARAM_ERROR);
01728         *a_sheet = a_this->parent_sheet;
01729         return CR_OK;
01730 }
01731 
01732 /**
01733  *Appends a new statement to the statement list.
01734  *@param a_this the current instance of the statement list.
01735  *@param a_this a_new the new instance of #CRStatement to append.
01736  *@return the new list statement list, or NULL in cas of failure.
01737  */
01738 CRStatement *
01739 cr_statement_append (CRStatement * a_this, CRStatement * a_new)
01740 {
01741         CRStatement *cur = NULL;
01742 
01743         g_return_val_if_fail (a_new, NULL);
01744 
01745         if (!a_this) {
01746                 return a_new;
01747         }
01748 
01749         /*walk forward in the current list to find the tail list element */
01750         for (cur = a_this; cur && cur->next; cur = cur->next) ;
01751 
01752         cur->next = a_new;
01753         a_new->prev = cur;
01754 
01755         return a_this;
01756 }
01757 
01758 /**
01759  *Prepends the an instance of #CRStatement to
01760  *the current statement list.
01761  *@param a_this the current instance of #CRStatement.
01762  *@param a_new the new statement to prepend.
01763  *@return the new list with the new statement prepended,
01764  *or NULL in case of an error.
01765  */
01766 CRStatement *
01767 cr_statement_prepend (CRStatement * a_this, CRStatement * a_new)
01768 {
01769         CRStatement *cur = NULL;
01770 
01771         g_return_val_if_fail (a_new, NULL);
01772 
01773         if (!a_this)
01774                 return a_new;
01775 
01776         a_new->next = a_this;
01777         a_this->prev = a_new;
01778 
01779         /*walk backward in the prepended list to find the head list element */
01780         for (cur = a_new; cur && cur->prev; cur = cur->prev) ;
01781 
01782         return cur;
01783 }
01784 
01785 /**
01786  *Unlinks a statement from the statements list.
01787  *@param a_this the current statements list.
01788  *@param a_to_unlink the statement to unlink from the list.
01789  *@return the new list where a_to_unlink has been unlinked
01790  *from, or NULL in case of error.
01791  */
01792 CRStatement *
01793 cr_statement_unlink (CRStatement * a_stmt)
01794 {
01795         CRStatement *result = a_stmt;
01796 
01797         g_return_val_if_fail (result, NULL);
01798 
01799         /**
01800          *Some sanity checks first
01801          */
01802         if (a_stmt->next) {
01803                 g_return_val_if_fail (a_stmt->next->prev == a_stmt, NULL);
01804         }
01805         if (a_stmt->prev) {
01806                 g_return_val_if_fail (a_stmt->prev->next == a_stmt, NULL);
01807         }
01808 
01809         /**
01810          *Now, the real unlinking job.
01811          */
01812         if (a_stmt->next) {
01813                 a_stmt->next->prev = a_stmt->prev;
01814         }
01815         if (a_stmt->prev) {
01816                 a_stmt->prev->next = a_stmt->next;
01817         }
01818 
01819         if (a_stmt->parent_sheet
01820             && a_stmt->parent_sheet->statements == a_stmt) {
01821                 a_stmt->parent_sheet->statements =
01822                         a_stmt->parent_sheet->statements->next;
01823         }
01824 
01825         a_stmt->next = NULL;
01826         a_stmt->prev = NULL;
01827         a_stmt->parent_sheet = NULL;
01828 
01829         return result;
01830 }
01831 
01832 /**
01833  *Return the number of rules in the statement list;
01834  *@param a_this the current instance of #CRStatement.
01835  *@return number of rules in the statement list.
01836  */
01837 gint
01838 cr_statement_nr_rules (CRStatement * a_this)
01839 {
01840         CRStatement *cur = NULL;
01841         int nr = 0;
01842 
01843         g_return_val_if_fail (a_this, -1);
01844 
01845         for (cur = a_this; cur; cur = cur->next)
01846                 nr++;
01847         return nr;
01848 }
01849 
01850 /**
01851  *Use an index to get a CRStatement from the statement list.
01852  *@param a_this the current instance of #CRStatement.
01853  *@param itemnr the index into the statement list.
01854  *@return CRStatement at position itemnr, if itemnr > number of statements - 1,
01855  *it will return NULL.
01856  */
01857 CRStatement *
01858 cr_statement_get_from_list (CRStatement * a_this, int itemnr)
01859 {
01860         CRStatement *cur = NULL;
01861         int nr = 0;
01862 
01863         g_return_val_if_fail (a_this, NULL);
01864 
01865         for (cur = a_this; cur; cur = cur->next)
01866                 if (nr++ == itemnr)
01867                         return cur;
01868         return NULL;
01869 }
01870 
01871 /**
01872  *Sets a selector list to a ruleset statement.
01873  *@param a_this the current ruleset statement.
01874  *@param a_sel_list the selector list to set. Note
01875  *that this function increments the ref count of a_sel_list.
01876  *The sel list will be destroyed at the destruction of the
01877  *current instance of #CRStatement.
01878  *@return CR_OK upon successfull completion, an error code otherwise.
01879  */
01880 enum CRStatus
01881 cr_statement_ruleset_set_sel_list (CRStatement * a_this,
01882                                    CRSelector * a_sel_list)
01883 {
01884         g_return_val_if_fail (a_this && a_this->type == RULESET_STMT,
01885                               CR_BAD_PARAM_ERROR);
01886 
01887         if (a_this->kind.ruleset->sel_list)
01888                 cr_selector_unref (a_this->kind.ruleset->sel_list);
01889 
01890         a_this->kind.ruleset->sel_list = a_sel_list;
01891 
01892         if (a_sel_list)
01893                 cr_selector_ref (a_sel_list);
01894 
01895         return CR_OK;
01896 }
01897 
01898 /**
01899  *Gets a pointer to the list of declaration contained
01900  *in the ruleset statement.
01901  *@param a_this the current instance of #CRStatement.
01902  *@a_decl_list out parameter. A pointer to the the returned
01903  *list of declaration. Must not be NULL.
01904  *@return CR_OK upon successfull completion, an error code if something
01905  *bad happened.
01906  */
01907 enum CRStatus
01908 cr_statement_ruleset_get_declarations (CRStatement * a_this,
01909                                        CRDeclaration ** a_decl_list)
01910 {
01911         g_return_val_if_fail (a_this
01912                               && a_this->type == RULESET_STMT
01913                               && a_this->kind.ruleset
01914                               && a_decl_list, CR_BAD_PARAM_ERROR);
01915 
01916         *a_decl_list = a_this->kind.ruleset->decl_list;
01917 
01918         return CR_OK;
01919 }
01920 
01921 /**
01922  *Gets a pointer to the selector list contained in
01923  *the current ruleset statement.
01924  *@param a_this the current ruleset statement.
01925  *@param a_list out parameter. The returned selector list,
01926  *if and only if the function returned CR_OK.
01927  *@return CR_OK upon successfull completion, an error code otherwise.
01928  */
01929 enum CRStatus
01930 cr_statement_ruleset_get_sel_list (CRStatement * a_this, CRSelector ** a_list)
01931 {
01932         g_return_val_if_fail (a_this && a_this->type == RULESET_STMT
01933                               && a_this->kind.ruleset, CR_BAD_PARAM_ERROR);
01934 
01935         *a_list = a_this->kind.ruleset->sel_list;
01936 
01937         return CR_OK;
01938 }
01939 
01940 /**
01941  *Sets a declaration list to the current ruleset statement.
01942  *@param a_this the current ruleset statement.
01943  *@param a_list the declaration list to be added to the current
01944  *ruleset statement.
01945  *@return CR_OK upon successfull completion, an error code otherwise.
01946  */
01947 enum CRStatus
01948 cr_statement_ruleset_set_decl_list (CRStatement * a_this,
01949                                     CRDeclaration * a_list)
01950 {
01951         g_return_val_if_fail (a_this && a_this->type == RULESET_STMT
01952                               && a_this->kind.ruleset, CR_BAD_PARAM_ERROR);
01953 
01954         if (a_this->kind.ruleset->decl_list == a_list)
01955                 return CR_OK;
01956 
01957         if (a_this->kind.ruleset->sel_list) {
01958                 cr_declaration_destroy (a_this->kind.ruleset->decl_list);
01959         }
01960 
01961         a_this->kind.ruleset->sel_list = NULL;
01962 
01963         return CR_OK;
01964 }
01965 
01966 /**
01967  *Appends a declaration to the current ruleset statement.
01968  *@param a_this the current statement.
01969  *@param a_prop the property of the declaration.
01970  *@param a_value the value of the declaration.
01971  *@return CR_OK uppon successfull completion, an error code
01972  *otherwise.
01973  */
01974 enum CRStatus
01975 cr_statement_ruleset_append_decl2 (CRStatement * a_this,
01976                                    CRString * a_prop, 
01977                                    CRTerm * a_value)
01978 {
01979         CRDeclaration *new_decls = NULL;
01980 
01981         g_return_val_if_fail (a_this && a_this->type == RULESET_STMT
01982                               && a_this->kind.ruleset, CR_BAD_PARAM_ERROR);
01983 
01984         new_decls = cr_declaration_append2
01985                 (a_this->kind.ruleset->decl_list, 
01986                  a_prop, a_value);
01987         g_return_val_if_fail (new_decls, CR_ERROR);
01988         a_this->kind.ruleset->decl_list = new_decls;
01989 
01990         return CR_OK;
01991 }
01992 
01993 /**
01994  *Appends a declaration to the current statement.
01995  *@param a_this the current statement.
01996  *@param a_declaration the declaration to append.
01997  *@return CR_OK upon sucessfull completion, an error code
01998  *otherwise.
01999  */
02000 enum CRStatus
02001 cr_statement_ruleset_append_decl (CRStatement * a_this,
02002                                   CRDeclaration * a_decl)
02003 {
02004         CRDeclaration *new_decls = NULL;
02005 
02006         g_return_val_if_fail (a_this && a_this->type == RULESET_STMT
02007                               && a_this->kind.ruleset, CR_BAD_PARAM_ERROR);
02008 
02009         new_decls = cr_declaration_append
02010                 (a_this->kind.ruleset->decl_list, a_decl);
02011         g_return_val_if_fail (new_decls, CR_ERROR);
02012         a_this->kind.ruleset->decl_list = new_decls;
02013 
02014         return CR_OK;
02015 }
02016 
02017 /**
02018  *Sets a stylesheet to the current @import rule.
02019  *@param a_this the current @import rule.
02020  *@param a_sheet the stylesheet. The stylesheet is owned
02021  *by the current instance of #CRStatement, that is, the 
02022  *stylesheet will be destroyed when the current instance
02023  *of #CRStatement will be destroyed.
02024  *@return CR_OK upon successfull completion, an error code otherwise.
02025  */
02026 enum CRStatus
02027 cr_statement_at_import_rule_set_imported_sheet (CRStatement * a_this,
02028                                                 CRStyleSheet * a_sheet)
02029 {
02030         g_return_val_if_fail (a_this
02031                               && a_this->type == AT_IMPORT_RULE_STMT
02032                               && a_this->kind.import_rule,
02033                               CR_BAD_PARAM_ERROR);
02034 
02035         a_this->kind.import_rule->sheet = a_sheet;
02036 
02037         return CR_OK;
02038 }
02039 
02040 /**
02041  *Gets the stylesheet contained by the @import rule statement.
02042  *@param a_this the current @import rule statement.
02043  *@param a_sheet out parameter. The returned stylesheet if and
02044  *only if the function returns CR_OK.
02045  *@return CR_OK upon sucessfull completion, an error code otherwise.
02046  */
02047 enum CRStatus
02048 cr_statement_at_import_rule_get_imported_sheet (CRStatement * a_this,
02049                                                 CRStyleSheet ** a_sheet)
02050 {
02051         g_return_val_if_fail (a_this
02052                               && a_this->type == AT_IMPORT_RULE_STMT
02053                               && a_this->kind.import_rule,
02054                               CR_BAD_PARAM_ERROR);
02055         *a_sheet = a_this->kind.import_rule->sheet;
02056         return CR_OK;
02057 
02058 }
02059 
02060 /**
02061  *Sets an url to the current @import rule statement.
02062  *@param a_this the current @import rule statement.
02063  *@param a_url the url to set.
02064  *@return CR_OK upon successfull completion, an error code otherwise.
02065  */
02066 enum CRStatus
02067 cr_statement_at_import_rule_set_url (CRStatement * a_this, 
02068                                      CRString * a_url)
02069 {
02070         g_return_val_if_fail (a_this
02071                               && a_this->type == AT_IMPORT_RULE_STMT
02072                               && a_this->kind.import_rule,
02073                               CR_BAD_PARAM_ERROR);
02074 
02075         if (a_this->kind.import_rule->url) {
02076                 cr_string_destroy (a_this->kind.import_rule->url);
02077         }
02078 
02079         a_this->kind.import_rule->url = a_url;
02080 
02081         return CR_OK;
02082 }
02083 
02084 /**
02085  *Gets the url of the @import rule statement.
02086  *@param the current @import rule statement.
02087  *@param a_url out parameter. The returned url if
02088  *and only if the function returned CR_OK.
02089  */
02090 enum CRStatus
02091 cr_statement_at_import_rule_get_url (CRStatement * a_this, 
02092                                      CRString ** a_url)
02093 {
02094         g_return_val_if_fail (a_this
02095                               && a_this->type == AT_IMPORT_RULE_STMT
02096                               && a_this->kind.import_rule,
02097                               CR_BAD_PARAM_ERROR);
02098 
02099         *a_url = a_this->kind.import_rule->url;
02100 
02101         return CR_OK;
02102 }
02103 
02104 /**
02105  *Return the number of rules in the media rule;
02106  *@param a_this the current instance of #CRStatement.
02107  *@return number of rules in the media rule.
02108  */
02109 int
02110 cr_statement_at_media_nr_rules (CRStatement * a_this)
02111 {
02112         g_return_val_if_fail (a_this
02113                               && a_this->type == AT_MEDIA_RULE_STMT
02114                               && a_this->kind.media_rule, CR_BAD_PARAM_ERROR);
02115 
02116         return cr_statement_nr_rules (a_this->kind.media_rule->rulesets);
02117 }
02118 
02119 /**
02120  *Use an index to get a CRStatement from the media rule list of rules.
02121  *@param a_this the current instance of #CRStatement.
02122  *@param itemnr the index into the media rule list of rules.
02123  *@return CRStatement at position itemnr, if itemnr > number of rules - 1,
02124  *it will return NULL.
02125  */
02126 CRStatement *
02127 cr_statement_at_media_get_from_list (CRStatement * a_this, int itemnr)
02128 {
02129         g_return_val_if_fail (a_this
02130                               && a_this->type == AT_MEDIA_RULE_STMT
02131                               && a_this->kind.media_rule, NULL);
02132 
02133         return cr_statement_get_from_list (a_this->kind.media_rule->rulesets,
02134                                            itemnr);
02135 }
02136 
02137 /**
02138  *Sets a declaration list to the current @page rule statement.
02139  *@param a_this the current @page rule statement.
02140  *@param a_decl_list the declaration list to add. Will be freed
02141  *by the current instance of #CRStatement when it is destroyed.
02142  *@return CR_OK upon successfull completion, an error code otherwise.
02143  */
02144 enum CRStatus
02145 cr_statement_at_page_rule_set_declarations (CRStatement * a_this,
02146                                             CRDeclaration * a_decl_list)
02147 {
02148         g_return_val_if_fail (a_this
02149                               && a_this->type == AT_PAGE_RULE_STMT
02150                               && a_this->kind.page_rule, CR_BAD_PARAM_ERROR);
02151 
02152         if (a_this->kind.page_rule->decl_list) {
02153                 cr_declaration_unref (a_this->kind.page_rule->decl_list);
02154         }
02155 
02156         a_this->kind.page_rule->decl_list = a_decl_list;
02157 
02158         if (a_decl_list) {
02159                 cr_declaration_ref (a_decl_list);
02160         }
02161 
02162         return CR_OK;
02163 }
02164 
02165 /**
02166  *Gets the declaration list associated to the current @page rule
02167  *statement.
02168  *@param a_this the current  @page rule statement.
02169  *@param a_decl_list out parameter. The returned declaration list.
02170  *@return CR_OK upon successfull completion, an error code otherwise.
02171  */
02172 enum CRStatus
02173 cr_statement_at_page_rule_get_declarations (CRStatement * a_this,
02174                                             CRDeclaration ** a_decl_list)
02175 {
02176         g_return_val_if_fail (a_this
02177                               && a_this->type == AT_PAGE_RULE_STMT
02178                               && a_this->kind.page_rule, CR_BAD_PARAM_ERROR);
02179 
02180         *a_decl_list = a_this->kind.page_rule->decl_list;
02181 
02182         return CR_OK;
02183 }
02184 
02185 /**
02186  *Sets the charset of the current @charset rule statement.
02187  *@param a_this the current @charset rule statement.
02188  *@param a_charset the charset to set.
02189  *@return CR_OK upon successfull completion, an error code otherwise.
02190  */
02191 enum CRStatus
02192 cr_statement_at_charset_rule_set_charset (CRStatement * a_this,
02193                                           CRString * a_charset)
02194 {
02195         g_return_val_if_fail (a_this
02196                               && a_this->type == AT_CHARSET_RULE_STMT
02197                               && a_this->kind.charset_rule,
02198                               CR_BAD_PARAM_ERROR);
02199 
02200         if (a_this->kind.charset_rule->charset) {
02201                 cr_string_destroy (a_this->kind.charset_rule->charset);
02202         }
02203         a_this->kind.charset_rule->charset = a_charset;
02204         return CR_OK;
02205 }
02206 
02207 /**
02208  *Gets the charset string associated to the current
02209  *@charset rule statement.
02210  *@param a_this the current @charset rule statement.
02211  *@param a_charset out parameter. The returned charset string if
02212  *and only if the function returned CR_OK.
02213  */
02214 enum CRStatus
02215 cr_statement_at_charset_rule_get_charset (CRStatement * a_this,
02216                                           CRString ** a_charset)
02217 {
02218         g_return_val_if_fail (a_this
02219                               && a_this->type == AT_CHARSET_RULE_STMT
02220                               && a_this->kind.charset_rule,
02221                               CR_BAD_PARAM_ERROR);
02222 
02223         *a_charset = a_this->kind.charset_rule->charset;
02224 
02225         return CR_OK;
02226 }
02227 
02228 /**
02229  *Sets a declaration list to the current @font-face rule statement.
02230  *@param a_this the current @font-face rule statement.
02231  *@param a_decls the declarations list to set.
02232  *@return CR_OK upon successfull completion, an error code otherwise.
02233  */
02234 enum CRStatus
02235 cr_statement_at_font_face_rule_set_decls (CRStatement * a_this,
02236                                           CRDeclaration * a_decls)
02237 {
02238         g_return_val_if_fail (a_this
02239                               && a_this->type == AT_FONT_FACE_RULE_STMT
02240                               && a_this->kind.font_face_rule,
02241                               CR_BAD_PARAM_ERROR);
02242 
02243         if (a_this->kind.font_face_rule->decl_list) {
02244                 cr_declaration_unref (a_this->kind.font_face_rule->decl_list);
02245         }
02246 
02247         a_this->kind.font_face_rule->decl_list = a_decls;
02248         cr_declaration_ref (a_decls);
02249 
02250         return CR_OK;
02251 }
02252 
02253 /**
02254  *Gets the declaration list associated to the current instance
02255  *of @font-face rule statement.
02256  *@param a_this the current @font-face rule statement.
02257  *@param a_decls out parameter. The returned declaration list if
02258  *and only if this function returns CR_OK.
02259  *@return CR_OK upon successfull completion, an error code otherwise.
02260  */
02261 enum CRStatus
02262 cr_statement_at_font_face_rule_get_decls (CRStatement * a_this,
02263                                           CRDeclaration ** a_decls)
02264 {
02265         g_return_val_if_fail (a_this
02266                               && a_this->type == AT_FONT_FACE_RULE_STMT
02267                               && a_this->kind.font_face_rule,
02268                               CR_BAD_PARAM_ERROR);
02269 
02270         *a_decls = a_this->kind.font_face_rule->decl_list;
02271 
02272         return CR_OK;
02273 }
02274 
02275 /**
02276  *Adds a declaration to the current @font-face rule
02277  *statement.
02278  *@param a_this the current @font-face rule statement.
02279  *@param a_prop the property of the declaration.
02280  *@param a_value the value of the declaration.
02281  *@return CR_OK upon successfull completion, an error code otherwise.
02282  */
02283 enum CRStatus
02284 cr_statement_at_font_face_rule_add_decl (CRStatement * a_this,
02285                                          CRString * a_prop, CRTerm * a_value)
02286 {
02287         CRDeclaration *decls = NULL;
02288 
02289         g_return_val_if_fail (a_this
02290                               && a_this->type == AT_FONT_FACE_RULE_STMT
02291                               && a_this->kind.font_face_rule,
02292                               CR_BAD_PARAM_ERROR);
02293 
02294         decls = cr_declaration_append2
02295                 (a_this->kind.font_face_rule->decl_list, 
02296                  a_prop, a_value);
02297 
02298         g_return_val_if_fail (decls, CR_ERROR);
02299 
02300         if (a_this->kind.font_face_rule->decl_list == NULL)
02301                 cr_declaration_ref (decls);
02302 
02303         a_this->kind.font_face_rule->decl_list = decls;
02304 
02305         return CR_OK;
02306 }
02307 
02308 /**
02309  *Serializes a css statement into a string
02310  *@param a_this the current statement to serialize
02311  *@param a_indent the number of white space of indentation.
02312  *@return the serialized statement. Must be freed by the caller
02313  *using g_free().
02314  */
02315 gchar *
02316 cr_statement_to_string (CRStatement * a_this, gulong a_indent)
02317 {
02318         gchar *str = NULL ;
02319 
02320         if (!a_this)
02321                 return NULL;
02322 
02323         switch (a_this->type) {
02324         case RULESET_STMT:
02325                 str = cr_statement_ruleset_to_string 
02326                         (a_this, a_indent);
02327                 break;
02328 
02329         case AT_FONT_FACE_RULE_STMT:
02330                 str = cr_statement_font_face_rule_to_string 
02331                         (a_this, a_indent) ;
02332                 break;
02333 
02334         case AT_CHARSET_RULE_STMT:
02335                 str = cr_statement_charset_to_string
02336                         (a_this, a_indent);                
02337                 break;
02338 
02339         case AT_PAGE_RULE_STMT:
02340                 str = cr_statement_at_page_rule_to_string
02341                         (a_this, a_indent);
02342                 break;
02343 
02344         case AT_MEDIA_RULE_STMT:
02345                 str = cr_statement_media_rule_to_string
02346                         (a_this, a_indent);
02347                 break;
02348 
02349         case AT_IMPORT_RULE_STMT:
02350                 str = cr_statement_import_rule_to_string
02351                         (a_this, a_indent);
02352                 break;
02353 
02354         default:
02355                 cr_utils_trace_info ("Statement unrecognized");
02356                 break;
02357         }
02358         return str ;
02359 }
02360 
02361 gchar*
02362 cr_statement_list_to_string (CRStatement *a_this, gulong a_indent)
02363 {
02364         CRStatement *cur_stmt = NULL ;
02365         GString *stringue = NULL ;
02366         gchar *str = NULL ;
02367 
02368         g_return_val_if_fail (a_this, NULL) ;
02369 
02370         stringue = g_string_new (NULL) ;
02371         if (!stringue) {
02372                 cr_utils_trace_info ("Out of memory") ;
02373                 return NULL ;
02374         }
02375         for (cur_stmt = a_this ; cur_stmt;
02376              cur_stmt = cur_stmt->next) {
02377                 str = cr_statement_to_string (cur_stmt, a_indent) ;
02378                 if (str) {
02379                         if (!cur_stmt->prev) {
02380                                 g_string_append (stringue, str) ;
02381                         } else {
02382                                 g_string_append_printf 
02383                                         (stringue, "\n%s", str) ;
02384                         }
02385                         g_free (str) ;
02386                         str = NULL ;
02387                 }                
02388         }
02389         str = stringue->str ;
02390         g_string_free (stringue, FALSE) ;
02391         return str ;
02392 }
02393 
02394 /**
02395  *Dumps the css2 statement to a file.
02396  *@param a_this the current css2 statement.
02397  *@param a_fp the destination file pointer.
02398  *@param a_indent the number of white space indentation characters.
02399  */
02400 void
02401 cr_statement_dump (CRStatement * a_this, FILE * a_fp, gulong a_indent)
02402 {
02403         gchar *str = NULL ;
02404 
02405         if (!a_this)
02406                 return;
02407 
02408         str = cr_statement_to_string (a_this, a_indent) ;
02409         if (str) {
02410                 fprintf (a_fp, "%s",str) ;
02411                 g_free (str) ;
02412                 str = NULL ;
02413         }
02414 }
02415 
02416 /**
02417  *Dumps a ruleset statement to a file.
02418  *@param a_this the current instance of #CRStatement.
02419  *@param a_fp the destination file pointer.
02420  *@param a_indent the number of indentation white spaces to add.
02421  */
02422 void
02423 cr_statement_dump_ruleset (CRStatement * a_this, FILE * a_fp, glong a_indent)
02424 {
02425         guchar *str = NULL;
02426 
02427         g_return_if_fail (a_fp && a_this);
02428         str = cr_statement_ruleset_to_string (a_this, a_indent);
02429         if (str) {
02430                 fprintf (a_fp, str);
02431                 g_free (str);
02432                 str = NULL;
02433         }
02434 }
02435 
02436 /**
02437  *Dumps a font face rule statement to a file.
02438  *@param a_this the current instance of font face rule statement.
02439  *@param a_fp the destination file pointer.
02440  *@param a_indent the number of white space indentation.
02441  */
02442 void
02443 cr_statement_dump_font_face_rule (CRStatement * a_this, FILE * a_fp,
02444                                   glong a_indent)
02445 {
02446         gchar *str = NULL ;
02447         g_return_if_fail (a_this 
02448                           && a_this->type == AT_FONT_FACE_RULE_STMT);
02449 
02450         str = cr_statement_font_face_rule_to_string (a_this,
02451                                                      a_indent) ;
02452         if (str) {
02453                 fprintf (a_fp, "%s", str) ;
02454                 g_free (str) ;
02455                 str = NULL ;
02456         }
02457 }
02458 
02459 /**
02460  *Dumps an @charset rule statement to a file.
02461  *@param a_this the current instance of the @charset rule statement.
02462  *@param a_fp the destination file pointer.
02463  *@param a_indent the number of indentation white spaces.
02464  */
02465 void
02466 cr_statement_dump_charset (CRStatement * a_this, FILE * a_fp, gulong a_indent)
02467 {
02468         guchar *str = NULL;
02469 
02470         g_return_if_fail (a_this && a_this->type == AT_CHARSET_RULE_STMT);
02471 
02472         str = cr_statement_charset_to_string (a_this,
02473                                               a_indent) ;
02474         if (str) {
02475                 fprintf (a_fp, str) ;
02476                 g_free (str) ;
02477                 str = NULL ;
02478         }
02479 }
02480 
02481 
02482 /**
02483  *Dumps an @page rule statement on stdout.
02484  *@param a_this the statement to dump on stdout.
02485  *@param a_fp the destination file pointer.
02486  *@param a_indent the number of indentation white spaces.
02487  */
02488 void
02489 cr_statement_dump_page (CRStatement * a_this, FILE * a_fp, gulong a_indent)
02490 {
02491         guchar *str = NULL;
02492 
02493         g_return_if_fail (a_this
02494                           && a_this->type == AT_PAGE_RULE_STMT
02495                           && a_this->kind.page_rule);
02496 
02497         str = cr_statement_at_page_rule_to_string (a_this, a_indent) ;
02498         if (str) {
02499                 fprintf (a_fp, str);
02500                 g_free (str) ;
02501                 str = NULL ; 
02502         }
02503 }
02504 
02505 
02506 /**
02507  *Dumps an @media rule statement to a file.
02508  *@param a_this the statement to dump.
02509  *@param a_fp the destination file pointer
02510  *@param a_indent the number of white spaces indentation.
02511  */
02512 void
02513 cr_statement_dump_media_rule (CRStatement * a_this, 
02514                               FILE * a_fp,
02515                               gulong a_indent)
02516 {
02517         gchar *str = NULL ;
02518         g_return_if_fail (a_this->type == AT_MEDIA_RULE_STMT);
02519 
02520         str = cr_statement_media_rule_to_string (a_this, a_indent) ;
02521         if (str) {
02522                 fprintf (a_fp, str) ;
02523                 g_free (str) ;
02524                 str = NULL ;
02525         }
02526 }
02527 
02528 /**
02529  *Dumps an @import rule statement to a file.
02530  *@param a_fp the destination file pointer.
02531  *@param a_indent the number of white space indentations.
02532  */
02533 void
02534 cr_statement_dump_import_rule (CRStatement * a_this, FILE * a_fp,
02535                                gulong a_indent)
02536 {
02537         gchar *str = NULL ;
02538         g_return_if_fail (a_this
02539                           && a_this->type == AT_IMPORT_RULE_STMT
02540                           && a_fp
02541                           && a_this->kind.import_rule);
02542 
02543         str = cr_statement_import_rule_to_string (a_this, a_indent) ;
02544         if (str) {
02545                 fprintf (a_fp, str) ;
02546                 g_free (str) ;
02547                 str = NULL ;
02548         }
02549 }
02550 
02551 /**
02552  *Destructor of #CRStatement.
02553  */
02554 void
02555 cr_statement_destroy (CRStatement * a_this)
02556 {
02557         CRStatement *cur = NULL;
02558 
02559         g_return_if_fail (a_this);
02560 
02561         /*go get the tail of the list */
02562         for (cur = a_this; cur && cur->next; cur = cur->next) {
02563                 cr_statement_clear (cur);
02564         }
02565 
02566         if (cur)
02567                 cr_statement_clear (cur);
02568 
02569         if (cur->prev == NULL) {
02570                 g_free (a_this);
02571                 return;
02572         }
02573 
02574         /*walk backward and free next element */
02575         for (cur = cur->prev; cur && cur->prev; cur = cur->prev) {
02576                 if (cur->next) {
02577                         g_free (cur->next);
02578                         cur->next = NULL;
02579                 }
02580         }
02581 
02582         if (!cur)
02583                 return;
02584 
02585         /*free the one remaining list */
02586         if (cur->next) {
02587                 g_free (cur->next);
02588                 cur->next = NULL;
02589         }
02590 
02591         g_free (cur);
02592         cur = NULL;
02593 }

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