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