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  * 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  *See COPYRIGHTS file for copyright information.
00021  */
00022 
00023 /*
00024  *$Id: cr-declaration.c,v 1.13 2004/03/07 13:22:47 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;
00047 
00048         g_return_if_fail (a_this);
00049 
00050         str = cr_declaration_to_string (a_this, a_indent);
00051         if (str) {
00052                 fprintf (a_fp, "%s", str);
00053                 g_free (str);
00054                 str = NULL;
00055         }
00056 }
00057 
00058 /**
00059  *Constructor of #CRDeclaration.
00060  *@param a_property the property string of the declaration
00061  *@param a_value the value expression of the declaration.
00062  *@return the newly built instance of #CRDeclaration, or NULL in
00063  *case of error.
00064  */
00065 CRDeclaration *
00066 cr_declaration_new (CRStatement * a_statement,
00067                     GString * a_property, CRTerm * a_value)
00068 {
00069         CRDeclaration *result = NULL;
00070 
00071         g_return_val_if_fail (a_property, NULL);
00072 
00073         if (a_statement)
00074                 g_return_val_if_fail (a_statement
00075                                       && ((a_statement->type == RULESET_STMT)
00076                                           || (a_statement->type
00077                                               == AT_FONT_FACE_RULE_STMT)
00078                                           || (a_statement->type
00079                                               == AT_PAGE_RULE_STMT)), NULL);
00080 
00081         result = g_try_malloc (sizeof (CRDeclaration));
00082         if (!result) {
00083                 cr_utils_trace_info ("Out of memory");
00084                 return NULL;
00085         }
00086         memset (result, 0, sizeof (CRDeclaration));
00087         result->property = a_property;
00088         result->value = a_value;
00089 
00090         if (a_value) {
00091                 cr_term_ref (a_value);
00092         }
00093         result->parent_statement = a_statement;
00094         return result;
00095 }
00096 
00097 /**
00098  *Parses a text buffer that contains
00099  *a css declaration.
00100  *
00101  *@param a_statement the parent css2 statement of this
00102  *this declaration. Must be non NULL and of type
00103  *RULESET_STMT (must be a ruleset).
00104  *@param a_str the string that contains the statement.
00105  *@param a_enc the encoding of a_str.
00106  *@return the parsed declaration, or NULL in case of error.
00107  */
00108 CRDeclaration *
00109 cr_declaration_parse_from_buf (CRStatement * a_statement,
00110                                const guchar * a_str, enum CREncoding a_enc)
00111 {
00112         enum CRStatus status = CR_OK;
00113         CRTerm *value = NULL;
00114         GString *property = NULL;
00115         CRDeclaration *result = NULL;
00116         CRParser *parser = NULL;
00117         gboolean important = FALSE;
00118 
00119         g_return_val_if_fail (a_str, NULL);
00120         if (a_statement)
00121                 g_return_val_if_fail (a_statement->type == RULESET_STMT,
00122                                       NULL);
00123 
00124         parser = cr_parser_new_from_buf ((guchar*)a_str, strlen (a_str), a_enc, FALSE);
00125         g_return_val_if_fail (parser, NULL);
00126 
00127         status = cr_parser_try_to_skip_spaces_and_comments (parser);
00128         if (status != CR_OK)
00129                 goto cleanup;
00130 
00131         status = cr_parser_parse_declaration (parser, &property,
00132                                               &value, &important);
00133         if (status != CR_OK || !property)
00134                 goto cleanup;
00135 
00136         result = cr_declaration_new (a_statement, property, value);
00137         if (result) {
00138                 property = NULL;
00139                 value = NULL;
00140                 result->important = important;
00141         }
00142 
00143       cleanup:
00144 
00145         if (parser) {
00146                 cr_parser_destroy (parser);
00147                 parser = NULL;
00148         }
00149 
00150         if (property) {
00151                 g_string_free (property, TRUE);
00152                 property = NULL;
00153         }
00154 
00155         if (value) {
00156                 cr_term_destroy (value);
00157                 value = NULL;
00158         }
00159 
00160         return result;
00161 }
00162 
00163 /**
00164  *Parses a ';' separated list of properties declaration.
00165  *@param a_str the input buffer that contains the list of declaration to
00166  *parse.
00167  *@param a_enc the encoding of a_str
00168  *@return the parsed list of declaration, NULL if parsing failed.
00169  */
00170 CRDeclaration *
00171 cr_declaration_parse_list_from_buf (const guchar * a_str,
00172                                     enum CREncoding a_enc)
00173 {
00174 
00175         enum CRStatus status = CR_OK;
00176         CRTerm *value = NULL;
00177         GString *property = NULL;
00178         CRDeclaration *result = NULL,
00179                 *cur_decl = NULL;
00180         CRParser *parser = NULL;
00181         CRTknzr *tokenizer = NULL;
00182         gboolean important = FALSE;
00183 
00184         g_return_val_if_fail (a_str, NULL);
00185 
00186         parser = cr_parser_new_from_buf ((guchar*)a_str, strlen (a_str), a_enc, FALSE);
00187         g_return_val_if_fail (parser, NULL);
00188         status = cr_parser_get_tknzr (parser, &tokenizer);
00189         if (status != CR_OK || !tokenizer) {
00190                 if (status == CR_OK)
00191                         status = CR_ERROR;
00192                 goto cleanup;
00193         }
00194         status = cr_parser_try_to_skip_spaces_and_comments (parser);
00195         if (status != CR_OK)
00196                 goto cleanup;
00197 
00198         status = cr_parser_parse_declaration (parser, &property,
00199                                               &value, &important);
00200         if (status != CR_OK || !property) {
00201                 if (status != CR_OK)
00202                         status = CR_ERROR;
00203                 goto cleanup;
00204         }
00205         result = cr_declaration_new (NULL, property, value);
00206         if (result) {
00207                 property = NULL;
00208                 value = NULL;
00209                 result->important = important;
00210         }
00211         /*now, go parse the other declarations */
00212         for (;;) {
00213                 guint32 c = 0;
00214 
00215                 cr_parser_try_to_skip_spaces_and_comments (parser);
00216                 status = cr_tknzr_peek_char (tokenizer, &c);
00217                 if (status != CR_OK) {
00218                         if (status == CR_END_OF_INPUT_ERROR)
00219                                 status = CR_OK;
00220                         goto cleanup;
00221                 }
00222                 if (c == ';') {
00223                         status = cr_tknzr_read_char (tokenizer, &c);
00224                 } else {
00225                         break;
00226                 }
00227                 important = FALSE;
00228                 cr_parser_try_to_skip_spaces_and_comments (parser);
00229                 status = cr_parser_parse_declaration (parser, &property,
00230                                                       &value, &important);
00231                 if (status != CR_OK || !property) {
00232                         if (status == CR_END_OF_INPUT_ERROR) {
00233                                 status = CR_OK;
00234                         }
00235                         break;
00236                 }
00237                 cur_decl = cr_declaration_new (NULL, property, value);
00238                 if (cur_decl) {
00239                         cur_decl->important = important;
00240                         result = cr_declaration_append (result, cur_decl);
00241                         property = NULL;
00242                         value = NULL;
00243                         cur_decl = NULL;
00244                 } else {
00245                         break;
00246                 }
00247         }
00248 
00249       cleanup:
00250 
00251         if (parser) {
00252                 cr_parser_destroy (parser);
00253                 parser = NULL;
00254         }
00255 
00256         if (property) {
00257                 g_string_free (property, TRUE);
00258                 property = NULL;
00259         }
00260 
00261         if (value) {
00262                 cr_term_destroy (value);
00263                 value = NULL;
00264         }
00265 
00266         if (status != CR_OK && result) {
00267                 cr_declaration_destroy (result);
00268                 result = NULL;
00269         }
00270         return result;
00271 }
00272 
00273 /**
00274  *Appends a new declaration to the current declarations list.
00275  *@param a_this the current declaration list.
00276  *@param a_new the declaration to append.
00277  *@return the declaration list with a_new appended to it, or NULL
00278  *in case of error.
00279  */
00280 CRDeclaration *
00281 cr_declaration_append (CRDeclaration * a_this, CRDeclaration * a_new)
00282 {
00283         CRDeclaration *cur = NULL;
00284 
00285         g_return_val_if_fail (a_new, NULL);
00286 
00287         if (!a_this)
00288                 return a_new;
00289 
00290         for (cur = a_this; cur && cur->next; cur = cur->next) ;
00291 
00292         cur->next = a_new;
00293         a_new->prev = cur;
00294 
00295         return a_this;
00296 }
00297 
00298 /**
00299  *Unlinks the declaration from the declaration list.
00300  *@param a_decl the declaration to unlink.
00301  *@return a pointer to the unlinked declaration in
00302  *case of a successfull completion, NULL otherwise.
00303  */
00304 CRDeclaration *
00305 cr_declaration_unlink (CRDeclaration * a_decl)
00306 {
00307         CRDeclaration *result = a_decl;
00308 
00309         g_return_val_if_fail (result, NULL);
00310 
00311         /*
00312          *some sanity checks first
00313          */
00314         if (a_decl->prev) {
00315                 g_return_val_if_fail (a_decl->prev->next == a_decl, NULL);
00316 
00317         }
00318         if (a_decl->next) {
00319                 g_return_val_if_fail (a_decl->next->prev == a_decl, NULL);
00320         }
00321 
00322         /*
00323          *now, the real unlinking job.
00324          */
00325         if (a_decl->prev) {
00326                 a_decl->prev->next = a_decl->next;
00327         }
00328         if (a_decl->next) {
00329                 a_decl->next->prev = a_decl->prev;
00330         }
00331         if (a_decl->parent_statement) {
00332                 CRDeclaration **children_decl_ptr = NULL;
00333 
00334                 switch (a_decl->parent_statement->type) {
00335                 case RULESET_STMT:
00336                         if (a_decl->parent_statement->kind.ruleset) {
00337                                 children_decl_ptr =
00338                                         &a_decl->parent_statement->
00339                                         kind.ruleset->decl_list;
00340                         }
00341 
00342                         break;
00343 
00344                 case AT_FONT_FACE_RULE_STMT:
00345                         if (a_decl->parent_statement->kind.font_face_rule) {
00346                                 children_decl_ptr =
00347                                         &a_decl->parent_statement->
00348                                         kind.font_face_rule->decl_list;
00349                         }
00350                         break;
00351                 case AT_PAGE_RULE_STMT:
00352                         if (a_decl->parent_statement->kind.page_rule) {
00353                                 children_decl_ptr =
00354                                         &a_decl->parent_statement->
00355                                         kind.page_rule->decl_list;
00356                         }
00357 
00358                 default:
00359                         break;
00360                 }
00361                 if (children_decl_ptr
00362                     && *children_decl_ptr && *children_decl_ptr == a_decl)
00363                         *children_decl_ptr = (*children_decl_ptr)->next;
00364         }
00365 
00366         a_decl->next = NULL;
00367         a_decl->prev = NULL;
00368         a_decl->parent_statement = NULL;
00369 
00370         return result;
00371 }
00372 
00373 /**
00374  *prepends a declaration to the current declaration list.
00375  *@param a_this the current declaration list.
00376  *@param a_new the declaration to prepend.
00377  *@return the list with a_new prepended or NULL in case of error.
00378  */
00379 CRDeclaration *
00380 cr_declaration_prepend (CRDeclaration * a_this, CRDeclaration * a_new)
00381 {
00382         CRDeclaration *cur = NULL;
00383 
00384         g_return_val_if_fail (a_new, NULL);
00385 
00386         if (!a_this)
00387                 return a_new;
00388 
00389         a_this->prev = a_new;
00390         a_new->next = a_this;
00391 
00392         for (cur = a_new; cur && cur->prev; cur = cur->prev) ;
00393 
00394         return cur;
00395 }
00396 
00397 /**
00398  *Appends a declaration to the current declaration list.
00399  *@param a_this the current declaration list.
00400  *@param a_prop the property string of the declaration to append.
00401  *@param a_value the value of the declaration to append.
00402  *@return the list with the new property appended to it, or NULL in
00403  *case of an error.
00404  */
00405 CRDeclaration *
00406 cr_declaration_append2 (CRDeclaration * a_this,
00407                         GString * a_prop, CRTerm * a_value)
00408 {
00409         CRDeclaration *new_elem = NULL;
00410 
00411         if (a_this) {
00412                 new_elem = cr_declaration_new (a_this->parent_statement,
00413                                                a_prop, a_value);
00414         } else {
00415                 new_elem = cr_declaration_new (NULL, a_prop, a_value);
00416         }
00417 
00418         g_return_val_if_fail (new_elem, NULL);
00419 
00420         return cr_declaration_append (a_this, new_elem);
00421 }
00422 
00423 /**
00424  *Dumps a declaration list to a file.
00425  *@param a_this the current instance of #CRDeclaration.
00426  *@param a_fp the destination file.
00427  *@param a_indent the number of indentation white char.
00428  */
00429 void
00430 cr_declaration_dump (CRDeclaration * a_this, FILE * a_fp, glong a_indent,
00431                      gboolean a_one_per_line)
00432 {
00433         CRDeclaration *cur = NULL;
00434 
00435         g_return_if_fail (a_this);
00436 
00437         for (cur = a_this; cur; cur = cur->next) {
00438                 if (cur->prev) {
00439                         if (a_one_per_line == TRUE)
00440                                 fprintf (a_fp, ";\n");
00441                         else
00442                                 fprintf (a_fp, "; ");
00443                 }
00444                 dump (cur, a_fp, a_indent);
00445         }
00446 }
00447 
00448 /**
00449  *Dumps the first declaration of the declaration list to a file.
00450  *@param a_this the current instance of #CRDeclaration.
00451  *@param a_fp the destination file.
00452  *@param a_indent the number of indentation white char.
00453  */
00454 void
00455 cr_declaration_dump_one (CRDeclaration * a_this, FILE * a_fp, glong a_indent)
00456 {
00457         g_return_if_fail (a_this);
00458 
00459         dump (a_this, a_fp, a_indent);
00460 }
00461 
00462 /**
00463  *Serializes the declaration into a string
00464  *@param a_this the current instance of #CRDeclaration.
00465  *@param a_indent the number of indentation white char
00466  *to put before the actual serialisation.
00467  */
00468 gchar *
00469 cr_declaration_to_string (CRDeclaration * a_this, gulong a_indent)
00470 {
00471         GString *stringue = NULL;
00472 
00473         guchar *str = NULL,
00474                 *result = NULL;
00475 
00476         g_return_val_if_fail (a_this, NULL);
00477 
00478         stringue = g_string_new (NULL);
00479 
00480         if (a_this->property && a_this->property->str) {
00481                 str = g_strndup (a_this->property->str,
00482                                  a_this->property->len);
00483                 if (str) {
00484                         cr_utils_dump_n_chars2 (' ', stringue, a_indent);
00485                         g_string_append_printf (stringue, "%s", str);
00486                         g_free (str);
00487                         str = NULL;
00488                 } else
00489                         goto error;
00490 
00491                 if (a_this->value) {
00492                         guchar *value_str = NULL;
00493 
00494                         value_str = cr_term_to_string (a_this->value);
00495                         if (value_str) {
00496                                 g_string_append_printf (stringue, " : %s",
00497                                                         value_str);
00498                                 g_free (value_str);
00499                         } else
00500                                 goto error;
00501                 }
00502                 if (a_this->important == TRUE) {
00503                         g_string_append_printf (stringue, " %s",
00504                                                 "!important");
00505                 }
00506         }
00507         if (stringue && stringue->str) {
00508                 result = stringue->str;
00509                 g_string_free (stringue, FALSE);
00510         }
00511         return result;
00512 
00513       error:
00514         if (stringue) {
00515                 g_string_free (stringue, TRUE);
00516                 stringue = NULL;
00517         }
00518         if (str) {
00519                 g_free (str);
00520                 str = NULL;
00521         }
00522 
00523         return result;
00524 }
00525 
00526 /**
00527  *Serializes the declaration list into a string
00528  *@param a_this the current instance of #CRDeclaration.
00529  *@param a_indent the number of indentation white char
00530  *to put before the actual serialisation.
00531  */
00532 guchar *
00533 cr_declaration_list_to_string (CRDeclaration * a_this, gulong a_indent)
00534 {
00535         CRDeclaration *cur = NULL;
00536         GString *stringue = NULL;
00537         guchar *str = NULL,
00538                 *result = NULL;
00539 
00540         g_return_val_if_fail (a_this, NULL);
00541 
00542         stringue = g_string_new (NULL);
00543 
00544         for (cur = a_this; cur; cur = cur->next) {
00545                 str = cr_declaration_to_string (cur, a_indent);
00546                 if (str) {
00547                         g_string_append_printf (stringue, "%s;", str);
00548                         g_free (str);
00549                 } else
00550                         break;
00551         }
00552         if (stringue && stringue->str) {
00553                 result = stringue->str;
00554                 g_string_free (stringue, FALSE);
00555         }
00556 
00557         return result;
00558 }
00559 
00560 /**
00561  *Serializes the declaration list into a string
00562  *@param a_this the current instance of #CRDeclaration.
00563  *@param a_indent the number of indentation white char
00564  *to put before the actual serialisation.
00565  */
00566 guchar *
00567 cr_declaration_list_to_string2 (CRDeclaration * a_this,
00568                                 gulong a_indent, gboolean a_one_decl_per_line)
00569 {
00570         CRDeclaration *cur = NULL;
00571         GString *stringue = NULL;
00572         guchar *str = NULL,
00573                 *result = NULL;
00574 
00575         g_return_val_if_fail (a_this, NULL);
00576 
00577         stringue = g_string_new (NULL);
00578 
00579         for (cur = a_this; cur; cur = cur->next) {
00580                 str = cr_declaration_to_string (cur, a_indent);
00581                 if (str) {
00582                         if (a_one_decl_per_line == TRUE) {
00583                                 if (cur->next)
00584                                         g_string_append_printf (stringue,
00585                                                                 "%s;\n", str);
00586                                 else
00587                                         g_string_append_printf (stringue,
00588                                                                 "%s", str);
00589                         } else {
00590                                 if (cur->next)
00591                                         g_string_append_printf (stringue,
00592                                                                 "%s;", str);
00593                                 else
00594                                         g_string_append_printf (stringue,
00595                                                                 "%s", str);
00596                         }
00597                         g_free (str);
00598                 } else
00599                         break;
00600         }
00601         if (stringue && stringue->str) {
00602                 result = stringue->str;
00603                 g_string_free (stringue, FALSE);
00604         }
00605 
00606         return result;
00607 }
00608 
00609 /**
00610  *Return the number of properties in the declaration;
00611  *@param a_this the current instance of #CRDeclaration.
00612  *@return number of properties in the declaration list.
00613  */
00614 gint
00615 cr_declaration_nr_props (CRDeclaration * a_this)
00616 {
00617         CRDeclaration *cur = NULL;
00618         int nr = 0;
00619 
00620         g_return_val_if_fail (a_this, -1);
00621 
00622         for (cur = a_this; cur; cur = cur->next)
00623                 nr++;
00624         return nr;
00625 }
00626 
00627 /**
00628  *Use an index to get a CRDeclaration from the declaration list.
00629  *@param a_this the current instance of #CRDeclaration.
00630  *@param itemnr the index into the declaration list.
00631  *@return CRDeclaration at position itemnr, if itemnr > number of declarations - 1,
00632  *it will return NULL.
00633  */
00634 CRDeclaration *
00635 cr_declaration_get_from_list (CRDeclaration * a_this, int itemnr)
00636 {
00637         CRDeclaration *cur = NULL;
00638         int nr = 0;
00639 
00640         g_return_val_if_fail (a_this, NULL);
00641 
00642         for (cur = a_this; cur; cur = cur->next)
00643                 if (nr++ == itemnr)
00644                         return cur;
00645         return NULL;
00646 }
00647 
00648 /**
00649  *Use property name to get a CRDeclaration from the declaration list.
00650  *@param a_this the current instance of #CRDeclaration.
00651  *@param a_prop the property name to search for.
00652  *@return CRDeclaration with property name a_prop, or NULL if not found.
00653  */
00654 CRDeclaration *
00655 cr_declaration_get_by_prop_name (CRDeclaration * a_this,
00656                                  const guchar * a_prop)
00657 {
00658         CRDeclaration *cur = NULL;
00659 
00660         g_return_val_if_fail (a_this, NULL);
00661         g_return_val_if_fail (a_prop, NULL);
00662 
00663         for (cur = a_this; cur; cur = cur->next)
00664                 if (!strcmp (cur->property->str, a_prop))
00665                         return cur;
00666         return NULL;
00667 }
00668 
00669 /**
00670  *Increases the ref count of the current instance of #CRDeclaration.
00671  *@param a_this the current instance of #CRDeclaration.
00672  */
00673 void
00674 cr_declaration_ref (CRDeclaration * a_this)
00675 {
00676         g_return_if_fail (a_this);
00677 
00678         a_this->ref_count++;
00679 }
00680 
00681 /**
00682  *Decrements the ref count of the current instance of #CRDeclaration.
00683  *If the ref count reaches zero, the current instance of #CRDeclaration
00684  *if destroyed.
00685  *@param a_this the current instance of #CRDeclaration.
00686  *@return TRUE if the current instance of #CRDeclaration has been destroyed
00687  *(ref count reached zero), FALSE otherwise.
00688  */
00689 gboolean
00690 cr_declaration_unref (CRDeclaration * a_this)
00691 {
00692         g_return_val_if_fail (a_this, FALSE);
00693 
00694         if (a_this->ref_count) {
00695                 a_this->ref_count--;
00696         }
00697 
00698         if (a_this->ref_count == 0) {
00699                 cr_declaration_destroy (a_this);
00700                 return TRUE;
00701         }
00702         return FALSE;
00703 }
00704 
00705 /**
00706  *Destructor of the declaration list.
00707  *@param a_this the current instance of #CRDeclaration.
00708  */
00709 void
00710 cr_declaration_destroy (CRDeclaration * a_this)
00711 {
00712         CRDeclaration *cur = NULL;
00713 
00714         g_return_if_fail (a_this);
00715 
00716         /*
00717          *Go get the tail of the list.
00718          *Meanwhile, free each property/value pair contained in the list.
00719          */
00720         for (cur = a_this; cur && cur->next; cur = cur->next) {
00721                 if (cur->property) {
00722                         g_string_free (cur->property, TRUE);
00723                         cur->property = NULL;
00724                 }
00725 
00726                 if (cur->value) {
00727                         cr_term_destroy (cur->value);
00728                         cur->value = NULL;
00729                 }
00730         }
00731 
00732         if (cur) {
00733                 if (cur->property) {
00734                         g_string_free (cur->property, TRUE);
00735                         cur->property = NULL;
00736                 }
00737 
00738                 if (cur->value) {
00739                         cr_term_destroy (cur->value);
00740                         cur->value = NULL;
00741                 }
00742         }
00743 
00744         /*in case the list contains only one element */
00745         if (cur && !cur->prev) {
00746                 g_free (cur);
00747                 return;
00748         }
00749 
00750         /*walk backward the list and free each "next" element */
00751         for (cur = cur->prev; cur && cur->prev; cur = cur->prev) {
00752                 if (cur->next) {
00753                         g_free (cur->next);
00754                         cur->next = NULL;
00755                 }
00756         }
00757 
00758         if (!cur)
00759                 return;
00760 
00761         if (cur->next) {
00762                 g_free (cur->next);
00763                 cur->next = NULL;
00764         }
00765 
00766         g_free (cur);
00767 }

Generated on Sat Mar 20 02:38:42 2004 for Libcroco by doxygen 1.3.5