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