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

cr-declaration.c

Go to the documentation of this file.
00001 /* -*- Mode: C; indent-tabs-mode: ni; c-basic-offset: 8 -*- */
00002 
00003 /*
00004  * This file is part of The Croco Library
00005  *
00006  * Copyright (C) 2002-2003 Dodji Seketeli <dodji@seketeli.org>
00007  *
00008  * This program is free software; you can redistribute it and/or
00009  * modify it under the terms of version 2.1 of the GNU Lesser General Public
00010  * License as published by the Free Software Foundation.
00011  *
00012  * This program is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
00020  * USA
00021  */
00022 
00023 /*
00024  *$Id: cr-declaration.c,v 1.8 2003/06/20 22:08:49 dodji Exp $
00025  */
00026 
00027 #include <string.h>
00028 #include "cr-declaration.h"
00029 #include "cr-statement.h"
00030 #include "cr-parser.h"
00031 
00032 /**
00033  *@file
00034  *The definition of the #CRDeclaration class.
00035  */
00036 
00037 /**
00038  *Dumps (serializes) one css declaration to a file.
00039  *@param a_this the current instance of #CRDeclaration.
00040  *@param a_fp the destination file pointer.
00041  *@param a_indent the number of indentation white char. 
00042  */
00043 static void
00044 dump (CRDeclaration *a_this, FILE *a_fp, glong a_indent)
00045 {
00046         guchar *str = NULL, *tmp_str = NULL, *tmp_str2 = NULL;
00047         g_return_if_fail (a_this) ;
00048 
00049         if (a_this->property && a_this->property->str)
00050         {               
00051                 tmp_str = g_strndup (a_this->property->str,
00052                                      a_this->property->len) ;
00053                 if (tmp_str)
00054                 {
00055                         tmp_str2 = g_strconcat (tmp_str, " : ", NULL) ;
00056                         if (!tmp_str2) goto error ;
00057                         if (tmp_str)
00058                         {
00059                                 g_free (tmp_str) ;
00060                                 tmp_str = NULL ;
00061                         }
00062                         str = tmp_str2 ;        
00063                 }
00064 
00065                 if (str)
00066                 {
00067                         cr_utils_dump_n_chars (' ', a_fp, a_indent) ;
00068                         fprintf (a_fp,"%s", str) ;
00069                         g_free (str) ;
00070                         str = NULL ;
00071                 }
00072                 else
00073                         goto error ;
00074 
00075                 if (a_this->value)
00076                 {
00077                         cr_term_dump (a_this->value, a_fp) ;
00078                 }
00079 
00080         }
00081 
00082         
00083         return ;
00084 
00085  error:
00086         if (str)
00087         {
00088                 g_free (str) ;
00089                 str = NULL ;
00090         }
00091         if (tmp_str)
00092         {
00093                 g_free (tmp_str) ;
00094                 tmp_str = NULL ;
00095         }
00096         if (tmp_str2)
00097         {
00098                 g_free (tmp_str2) ;
00099                 tmp_str2 = NULL ;
00100         }
00101 }
00102 
00103 /**
00104  *Constructor of #CRDeclaration.
00105  *@param a_property the property string of the declaration
00106  *@param a_value the value expression of the declaration.
00107  *@return the newly built instance of #CRDeclaration, or NULL in
00108  *case of error.
00109  */
00110 CRDeclaration *
00111 cr_declaration_new (CRStatement *a_statement,
00112                     GString *a_property, 
00113                     CRTerm *a_value)
00114 {
00115         CRDeclaration *result = NULL ;
00116 
00117         g_return_val_if_fail (a_property, NULL) ;
00118 
00119         if (a_statement)
00120                 g_return_val_if_fail (a_statement 
00121                                       && ((a_statement->type 
00122                                            == RULESET_STMT) 
00123                                           || (a_statement->type 
00124                                               == AT_FONT_FACE_RULE_STMT)
00125                                           || (a_statement->type 
00126                                               == AT_PAGE_RULE_STMT)),
00127                                       NULL) ;
00128 
00129         result = g_try_malloc (sizeof (CRDeclaration)) ;
00130         if (!result)
00131         {
00132                 cr_utils_trace_info ("Out of memory") ;
00133                 return NULL ;
00134         }
00135         memset (result, 0, sizeof (CRDeclaration)) ;
00136         result->property = a_property ;
00137         result->value = a_value ;
00138 
00139         if (a_value)
00140         {
00141                 cr_term_ref (a_value) ;
00142         }
00143         result->parent_statement = a_statement ;
00144         return result ;
00145 }
00146 
00147 
00148 /**
00149  *Parses a text buffer that contains
00150  *a css declaration.
00151  *
00152  *@param a_statement the parent css2 statement of this
00153  *this declaration. Must be non NULL and of type
00154  *RULESET_STMT (must be a ruleset).
00155  *@param a_str the string that contains the statement.
00156  *@param a_enc the encoding of a_str.
00157  *@return the parsed declaration, or NULL in case of error.
00158  */
00159 CRDeclaration *
00160 cr_declaration_parse_from_buf (CRStatement *a_statement,
00161                                const guchar *a_str,
00162                                enum CREncoding a_enc)
00163 {
00164         enum CRStatus status = CR_OK ;
00165         CRTerm *value = NULL ;
00166         GString *property = NULL;
00167         CRDeclaration *result = NULL ;
00168         CRParser * parser = NULL ;
00169 
00170         g_return_val_if_fail (a_str, NULL) ;
00171         if (a_statement)
00172                 g_return_val_if_fail (a_statement->type == RULESET_STMT, 
00173                                       NULL);
00174 
00175         parser = cr_parser_new_from_buf (a_str, 
00176                                          strlen (a_str),
00177                                          a_enc, FALSE) ;
00178         g_return_val_if_fail (parser, NULL) ;
00179 
00180         status = cr_parser_try_to_skip_spaces_and_comments (parser) ;
00181         if (status != CR_OK)
00182                 goto cleanup ;
00183 
00184         status = cr_parser_parse_declaration (parser, &property,
00185                                               &value) ;
00186         if (status != CR_OK || !property)
00187                 goto cleanup ;
00188 
00189         result = cr_declaration_new (a_statement, property, value) ;
00190         if (result)
00191         {
00192                 property = NULL ;
00193                 value = NULL ;
00194         }
00195 
00196  cleanup:
00197 
00198         if (parser)
00199         {
00200                 cr_parser_destroy (parser) ;
00201                 parser = NULL ;
00202         }
00203 
00204         if (property)
00205         {
00206                 g_string_free (property, TRUE) ;
00207                 property = NULL ;
00208         }
00209 
00210         if (value)
00211         {
00212                 cr_term_destroy (value) ;
00213                 value = NULL ;
00214         }
00215 
00216         return result ;
00217 }
00218 
00219 
00220 /**
00221  *Appends a new declaration to the current declarations list.
00222  *@param a_this the current declaration list.
00223  *@param a_new the declaration to append.
00224  *@return the declaration list with a_new appended to it, or NULL
00225  *in case of error.
00226  */
00227 CRDeclaration *
00228 cr_declaration_append (CRDeclaration *a_this, CRDeclaration *a_new)
00229 {
00230         CRDeclaration *cur = NULL ;
00231 
00232         g_return_val_if_fail (a_new, NULL) ;
00233 
00234         if (!a_this)
00235                 return a_new ;
00236 
00237         for (cur = a_this ; cur && cur->next ; cur = cur->next) ;
00238         
00239         cur->next = a_new ;
00240         a_new->prev = cur ;
00241 
00242         return a_this ;
00243 }
00244 
00245 /**
00246  *Unlinks the declaration from the declaration list.
00247  *@param a_decl the declaration to unlink.
00248  *@return a pointer to the unlinked declaration in
00249  *case of a successfull completion, NULL otherwise.
00250  */
00251 CRDeclaration *
00252 cr_declaration_unlink (CRDeclaration * a_decl)
00253 {
00254         CRDeclaration *result = a_decl ;
00255 
00256         g_return_val_if_fail (result, NULL) ;
00257 
00258         /*
00259          *some sanity checks first
00260          */
00261         if (a_decl->prev)
00262         {
00263                 g_return_val_if_fail (a_decl->prev->next == a_decl, NULL) ;
00264                 
00265         }
00266         if (a_decl->next)
00267         {
00268                 g_return_val_if_fail (a_decl->next->prev == a_decl, NULL) ;
00269         }
00270 
00271         /*
00272          *now, the real unlinking job.
00273          */
00274         if (a_decl->prev)
00275         {
00276                 a_decl->prev->next = a_decl->next ;
00277         }
00278         if (a_decl->next)
00279         {
00280                 a_decl->next->prev = a_decl->prev ;
00281         }
00282         if (a_decl->parent_statement)
00283         {
00284                 CRDeclaration **children_decl_ptr = NULL ;
00285                 switch (a_decl->parent_statement->type)
00286                 {
00287                 case RULESET_STMT:
00288                         if (a_decl->parent_statement->kind.ruleset)
00289                         {
00290                                 children_decl_ptr =
00291                                         &a_decl->parent_statement->
00292                                         kind.ruleset->decl_list ;
00293                         }
00294                         
00295                         break ;
00296 
00297                 case AT_FONT_FACE_RULE_STMT:
00298                         if (a_decl->parent_statement->kind.font_face_rule)
00299                         {
00300                                 children_decl_ptr =
00301                                         &a_decl->parent_statement->
00302                                         kind.font_face_rule->decl_list ;
00303                         }
00304                         break ;
00305                 case AT_PAGE_RULE_STMT:
00306                         if (a_decl->parent_statement->kind.page_rule)
00307                         {
00308                                 children_decl_ptr =
00309                                         &a_decl->parent_statement->
00310                                         kind.page_rule->decl_list ;
00311                         }
00312 
00313                 default:
00314                         break ;
00315                 }
00316                 if (children_decl_ptr && *children_decl_ptr)
00317                         *children_decl_ptr = 
00318                                 (*children_decl_ptr)->next ;
00319         }
00320 
00321         a_decl->next = NULL ;
00322         a_decl->prev = NULL ;
00323         a_decl->parent_statement = NULL ;
00324 
00325         return result ;
00326 }
00327 
00328 /**
00329  *prepends a declaration to the current declaration list.
00330  *@param a_this the current declaration list.
00331  *@param a_new the declaration to prepend.
00332  *@return the list with a_new prepended or NULL in case of error.
00333  */
00334 CRDeclaration *
00335 cr_declaration_prepend (CRDeclaration *a_this, CRDeclaration *a_new)
00336 {
00337         CRDeclaration *cur = NULL ;
00338 
00339         g_return_val_if_fail (a_new, NULL) ;
00340 
00341         if (!a_this)
00342                 return a_new ;
00343 
00344         a_this->prev = a_new ;
00345         a_new->next = a_this ;
00346 
00347         for (cur = a_new ; cur && cur->prev ; cur = cur->prev) ;
00348 
00349         return cur ;
00350 }
00351 
00352 /**
00353  *Appends a declaration to the current declaration list.
00354  *@param a_this the current declaration list.
00355  *@param a_prop the property string of the declaration to append.
00356  *@param a_value the value of the declaration to append.
00357  *@return the list with the new property appended to it, or NULL in
00358  *case of an error.
00359  */
00360 CRDeclaration *
00361 cr_declaration_append2 (CRDeclaration *a_this,
00362                         GString *a_prop,
00363                         CRTerm *a_value)
00364 {
00365         CRDeclaration *new_elem = NULL ;
00366 
00367         if (a_this)
00368         {
00369                 new_elem = cr_declaration_new (a_this->parent_statement,
00370                                                a_prop, a_value) ;
00371         }
00372         else
00373         {
00374                 new_elem = cr_declaration_new (NULL, a_prop, a_value) ;
00375         }
00376 
00377         g_return_val_if_fail (new_elem, NULL) ;
00378         
00379         return cr_declaration_append (a_this, new_elem) ;
00380 }
00381 
00382 /**
00383  *Dumps a declaration list to a file.
00384  *@param a_this the current instance of #CRDeclaration.
00385  *@param a_fp the destination file.
00386  *@param a_indent the number of indentation white char.
00387  */
00388 void
00389 cr_declaration_dump (CRDeclaration *a_this, FILE *a_fp, glong a_indent,
00390                      gboolean a_one_per_line)
00391 {
00392         CRDeclaration *cur = NULL ;
00393 
00394         g_return_if_fail (a_this) ;
00395 
00396         for (cur = a_this ; cur ; cur = cur->next)
00397         {
00398                 if (cur->prev)
00399                 {
00400                         if (a_one_per_line == TRUE)
00401                                 fprintf (a_fp,";\n") ;
00402                         else
00403                                 fprintf (a_fp,"; ") ;
00404                 }
00405                 dump (cur, a_fp, a_indent) ;
00406         }
00407 }
00408 
00409 /**
00410  *Serializes the declaration into a string
00411  *@param a_this the current instance of #CRDeclaration.
00412  *@param a_indent the number of indentation white char
00413  *to put before the actual serialisation.
00414  */
00415 guchar *
00416 cr_declaration_to_string (CRDeclaration *a_this,
00417                           gulong a_indent)
00418 {
00419         GString *stringue = NULL ;
00420 
00421         guchar *str = NULL, *result = NULL ;
00422         g_return_val_if_fail (a_this, NULL) ;
00423 
00424         stringue = g_string_new (NULL) ;
00425 
00426         if (a_this->property && a_this->property->str)
00427         {
00428                 str = g_strndup (a_this->property->str,
00429                                  a_this->property->len) ;
00430                 if (str)
00431                 {
00432                         cr_utils_dump_n_chars2 (' ', stringue, 
00433                                                 a_indent) ;
00434                         g_string_append_printf (stringue, "%s",
00435                                                 str) ;
00436                         g_free (str) ;
00437                         str = NULL ;
00438                 }
00439                 else
00440                         goto error ;
00441 
00442                 if (a_this->value)
00443                 {
00444                         guchar *value_str = NULL ;
00445 
00446                         value_str = cr_term_to_string (a_this->value) ;
00447                         if (value_str)
00448                         {
00449                                 g_string_append_printf (stringue, " : %s",
00450                                                         value_str) ;
00451                                 g_free (value_str) ;
00452                         }
00453                         else
00454                                 goto error ;
00455                 }               
00456         }
00457 
00458         if (stringue && stringue->str)
00459         {
00460                 result = stringue->str ;
00461                 g_string_free (stringue, FALSE) ;
00462         }
00463 
00464         return result ;
00465 
00466  error:
00467         if (stringue)
00468         {
00469                 g_string_free (stringue, TRUE) ;
00470                 stringue = NULL ;
00471         }
00472         if (str)
00473         {
00474                 g_free (str) ;
00475                 str = NULL ;
00476         }
00477 
00478         return result ;
00479 }
00480 
00481 /**
00482  *Increases the ref count of the current instance of #CRDeclaration.
00483  *@param a_this the current instance of #CRDeclaration.
00484  */
00485 void 
00486 cr_declaration_ref (CRDeclaration *a_this)
00487 {
00488         g_return_if_fail (a_this) ;
00489 
00490         a_this->ref_count ++ ;
00491 }
00492 
00493 /**
00494  *Decrements the ref count of the current instance of #CRDeclaration.
00495  *If the ref count reaches zero, the current instance of #CRDeclaration
00496  *if destroyed.
00497  *@param a_this the current instance of #CRDeclaration.
00498  *@return TRUE if the current instance of #CRDeclaration has been destroyed
00499  *(ref count reached zero), FALSE otherwise.
00500  */
00501 gboolean
00502 cr_declaration_unref (CRDeclaration *a_this)
00503 {
00504         g_return_val_if_fail (a_this, FALSE) ;
00505 
00506         if (a_this->ref_count)
00507         {
00508                 a_this->ref_count -- ;
00509         }
00510 
00511         if (a_this->ref_count == 0)
00512         {
00513                 cr_declaration_destroy (a_this) ;
00514                 return TRUE ;
00515         }
00516         return FALSE ;
00517 }
00518 
00519 
00520 /**
00521  *Destructor of the declaration list.
00522  *@param a_this the current instance of #CRDeclaration.
00523  */
00524 void
00525 cr_declaration_destroy (CRDeclaration *a_this)
00526 {
00527         CRDeclaration *cur = NULL ;
00528         g_return_if_fail (a_this) ;
00529 
00530         /*
00531          *Go get the tail of the list.
00532          *Meanwhile, free each property/value pair contained in the list.
00533          */
00534         for (cur = a_this ; cur && cur->next; cur = cur->next)
00535         {
00536                 if (cur->property)
00537                 {
00538                         g_string_free (cur->property, TRUE) ;
00539                         cur->property = NULL ;
00540                 }
00541                 
00542                 if (cur->value)
00543                 {
00544                         cr_term_destroy (cur->value) ;
00545                         cur->value = NULL ;
00546                 }
00547         }
00548 
00549         if (cur)
00550         {
00551                 if (cur->property)
00552                 {
00553                         g_string_free (cur->property, TRUE) ;
00554                         cur->property = NULL ;
00555                 }
00556                 
00557                 if (cur->value)
00558                 {
00559                         cr_term_destroy (cur->value) ;
00560                         cur->value = NULL ;
00561                 }
00562         }
00563 
00564         /*in case the list contains only one element*/
00565         if (cur && !cur->prev)
00566         {
00567                 g_free (cur) ;
00568                 return ;
00569         }
00570 
00571         /*walk backward the list and free each "next" element*/
00572         for (cur = cur->prev ; cur && cur->prev ; cur = cur->prev)
00573         {
00574                 if (cur->next)
00575                 {
00576                         g_free (cur->next) ;
00577                         cur->next = NULL ;
00578                 }
00579         }
00580         
00581         if (!cur)
00582                 return ;
00583 
00584         if (cur->next)
00585         {
00586                 g_free (cur->next) ;
00587                 cur->next = NULL ;
00588         }
00589 
00590         g_free (cur) ;
00591 }

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