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