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