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