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, *tmp_str = NULL, *tmp_str2 = NULL;
00047 g_return_if_fail (a_this) ;
00048
00049 if (a_this->property && a_this->property->str)
00050 {
00051 tmp_str = g_strndup (a_this->property->str,
00052 a_this->property->len) ;
00053 if (tmp_str)
00054 {
00055 tmp_str2 = g_strconcat (tmp_str, " : ", NULL) ;
00056 if (!tmp_str2) goto error ;
00057 if (tmp_str)
00058 {
00059 g_free (tmp_str) ;
00060 tmp_str = NULL ;
00061 }
00062 str = tmp_str2 ;
00063 }
00064
00065 if (str)
00066 {
00067 cr_utils_dump_n_chars (' ', a_fp, a_indent) ;
00068 fprintf (a_fp,"%s", str) ;
00069 g_free (str) ;
00070 str = NULL ;
00071 }
00072 else
00073 goto error ;
00074
00075 if (a_this->value)
00076 {
00077 cr_term_dump (a_this->value, a_fp) ;
00078 }
00079
00080 }
00081
00082
00083 return ;
00084
00085 error:
00086 if (str)
00087 {
00088 g_free (str) ;
00089 str = NULL ;
00090 }
00091 if (tmp_str)
00092 {
00093 g_free (tmp_str) ;
00094 tmp_str = NULL ;
00095 }
00096 if (tmp_str2)
00097 {
00098 g_free (tmp_str2) ;
00099 tmp_str2 = NULL ;
00100 }
00101 }
00102
00103
00104
00105
00106
00107
00108
00109
00110 CRDeclaration *
00111 cr_declaration_new (CRStatement *a_statement,
00112 GString *a_property,
00113 CRTerm *a_value)
00114 {
00115 CRDeclaration *result = NULL ;
00116
00117 g_return_val_if_fail (a_property, NULL) ;
00118
00119 if (a_statement)
00120 g_return_val_if_fail (a_statement
00121 && ((a_statement->type
00122 == RULESET_STMT)
00123 || (a_statement->type
00124 == AT_FONT_FACE_RULE_STMT)
00125 || (a_statement->type
00126 == AT_PAGE_RULE_STMT)),
00127 NULL) ;
00128
00129 result = g_try_malloc (sizeof (CRDeclaration)) ;
00130 if (!result)
00131 {
00132 cr_utils_trace_info ("Out of memory") ;
00133 return NULL ;
00134 }
00135 memset (result, 0, sizeof (CRDeclaration)) ;
00136 result->property = a_property ;
00137 result->value = a_value ;
00138
00139 if (a_value)
00140 {
00141 cr_term_ref (a_value) ;
00142 }
00143 result->parent_statement = a_statement ;
00144 return result ;
00145 }
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159 CRDeclaration *
00160 cr_declaration_parse_from_buf (CRStatement *a_statement,
00161 const guchar *a_str,
00162 enum CREncoding a_enc)
00163 {
00164 enum CRStatus status = CR_OK ;
00165 CRTerm *value = NULL ;
00166 GString *property = NULL;
00167 CRDeclaration *result = NULL ;
00168 CRParser * parser = NULL ;
00169
00170 g_return_val_if_fail (a_str, NULL) ;
00171 if (a_statement)
00172 g_return_val_if_fail (a_statement->type == RULESET_STMT,
00173 NULL);
00174
00175 parser = cr_parser_new_from_buf (a_str,
00176 strlen (a_str),
00177 a_enc, FALSE) ;
00178 g_return_val_if_fail (parser, NULL) ;
00179
00180 status = cr_parser_try_to_skip_spaces_and_comments (parser) ;
00181 if (status != CR_OK)
00182 goto cleanup ;
00183
00184 status = cr_parser_parse_declaration (parser, &property,
00185 &value) ;
00186 if (status != CR_OK || !property)
00187 goto cleanup ;
00188
00189 result = cr_declaration_new (a_statement, property, value) ;
00190 if (result)
00191 {
00192 property = NULL ;
00193 value = NULL ;
00194 }
00195
00196 cleanup:
00197
00198 if (parser)
00199 {
00200 cr_parser_destroy (parser) ;
00201 parser = NULL ;
00202 }
00203
00204 if (property)
00205 {
00206 g_string_free (property, TRUE) ;
00207 property = NULL ;
00208 }
00209
00210 if (value)
00211 {
00212 cr_term_destroy (value) ;
00213 value = NULL ;
00214 }
00215
00216 return result ;
00217 }
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227 CRDeclaration *
00228 cr_declaration_append (CRDeclaration *a_this, CRDeclaration *a_new)
00229 {
00230 CRDeclaration *cur = NULL ;
00231
00232 g_return_val_if_fail (a_new, NULL) ;
00233
00234 if (!a_this)
00235 return a_new ;
00236
00237 for (cur = a_this ; cur && cur->next ; cur = cur->next) ;
00238
00239 cur->next = a_new ;
00240 a_new->prev = cur ;
00241
00242 return a_this ;
00243 }
00244
00245
00246
00247
00248
00249
00250
00251 CRDeclaration *
00252 cr_declaration_unlink (CRDeclaration * a_decl)
00253 {
00254 CRDeclaration *result = a_decl ;
00255
00256 g_return_val_if_fail (result, NULL) ;
00257
00258
00259
00260
00261 if (a_decl->prev)
00262 {
00263 g_return_val_if_fail (a_decl->prev->next == a_decl, NULL) ;
00264
00265 }
00266 if (a_decl->next)
00267 {
00268 g_return_val_if_fail (a_decl->next->prev == a_decl, NULL) ;
00269 }
00270
00271
00272
00273
00274 if (a_decl->prev)
00275 {
00276 a_decl->prev->next = a_decl->next ;
00277 }
00278 if (a_decl->next)
00279 {
00280 a_decl->next->prev = a_decl->prev ;
00281 }
00282 if (a_decl->parent_statement)
00283 {
00284 CRDeclaration **children_decl_ptr = NULL ;
00285 switch (a_decl->parent_statement->type)
00286 {
00287 case RULESET_STMT:
00288 if (a_decl->parent_statement->kind.ruleset)
00289 {
00290 children_decl_ptr =
00291 &a_decl->parent_statement->
00292 kind.ruleset->decl_list ;
00293 }
00294
00295 break ;
00296
00297 case AT_FONT_FACE_RULE_STMT:
00298 if (a_decl->parent_statement->kind.font_face_rule)
00299 {
00300 children_decl_ptr =
00301 &a_decl->parent_statement->
00302 kind.font_face_rule->decl_list ;
00303 }
00304 break ;
00305 case AT_PAGE_RULE_STMT:
00306 if (a_decl->parent_statement->kind.page_rule)
00307 {
00308 children_decl_ptr =
00309 &a_decl->parent_statement->
00310 kind.page_rule->decl_list ;
00311 }
00312
00313 default:
00314 break ;
00315 }
00316 if (children_decl_ptr && *children_decl_ptr)
00317 *children_decl_ptr =
00318 (*children_decl_ptr)->next ;
00319 }
00320
00321 a_decl->next = NULL ;
00322 a_decl->prev = NULL ;
00323 a_decl->parent_statement = NULL ;
00324
00325 return result ;
00326 }
00327
00328
00329
00330
00331
00332
00333
00334 CRDeclaration *
00335 cr_declaration_prepend (CRDeclaration *a_this, CRDeclaration *a_new)
00336 {
00337 CRDeclaration *cur = NULL ;
00338
00339 g_return_val_if_fail (a_new, NULL) ;
00340
00341 if (!a_this)
00342 return a_new ;
00343
00344 a_this->prev = a_new ;
00345 a_new->next = a_this ;
00346
00347 for (cur = a_new ; cur && cur->prev ; cur = cur->prev) ;
00348
00349 return cur ;
00350 }
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360 CRDeclaration *
00361 cr_declaration_append2 (CRDeclaration *a_this,
00362 GString *a_prop,
00363 CRTerm *a_value)
00364 {
00365 CRDeclaration *new_elem = NULL ;
00366
00367 if (a_this)
00368 {
00369 new_elem = cr_declaration_new (a_this->parent_statement,
00370 a_prop, a_value) ;
00371 }
00372 else
00373 {
00374 new_elem = cr_declaration_new (NULL, a_prop, a_value) ;
00375 }
00376
00377 g_return_val_if_fail (new_elem, NULL) ;
00378
00379 return cr_declaration_append (a_this, new_elem) ;
00380 }
00381
00382
00383
00384
00385
00386
00387
00388 void
00389 cr_declaration_dump (CRDeclaration *a_this, FILE *a_fp, glong a_indent,
00390 gboolean a_one_per_line)
00391 {
00392 CRDeclaration *cur = NULL ;
00393
00394 g_return_if_fail (a_this) ;
00395
00396 for (cur = a_this ; cur ; cur = cur->next)
00397 {
00398 if (cur->prev)
00399 {
00400 if (a_one_per_line == TRUE)
00401 fprintf (a_fp,";\n") ;
00402 else
00403 fprintf (a_fp,"; ") ;
00404 }
00405 dump (cur, a_fp, a_indent) ;
00406 }
00407 }
00408
00409
00410
00411
00412
00413
00414
00415 guchar *
00416 cr_declaration_to_string (CRDeclaration *a_this,
00417 gulong a_indent)
00418 {
00419 GString *stringue = NULL ;
00420
00421 guchar *str = NULL, *result = NULL ;
00422 g_return_val_if_fail (a_this, NULL) ;
00423
00424 stringue = g_string_new (NULL) ;
00425
00426 if (a_this->property && a_this->property->str)
00427 {
00428 str = g_strndup (a_this->property->str,
00429 a_this->property->len) ;
00430 if (str)
00431 {
00432 cr_utils_dump_n_chars2 (' ', stringue,
00433 a_indent) ;
00434 g_string_append_printf (stringue, "%s",
00435 str) ;
00436 g_free (str) ;
00437 str = NULL ;
00438 }
00439 else
00440 goto error ;
00441
00442 if (a_this->value)
00443 {
00444 guchar *value_str = NULL ;
00445
00446 value_str = cr_term_to_string (a_this->value) ;
00447 if (value_str)
00448 {
00449 g_string_append_printf (stringue, " : %s",
00450 value_str) ;
00451 g_free (value_str) ;
00452 }
00453 else
00454 goto error ;
00455 }
00456 }
00457
00458 if (stringue && stringue->str)
00459 {
00460 result = stringue->str ;
00461 g_string_free (stringue, FALSE) ;
00462 }
00463
00464 return result ;
00465
00466 error:
00467 if (stringue)
00468 {
00469 g_string_free (stringue, TRUE) ;
00470 stringue = NULL ;
00471 }
00472 if (str)
00473 {
00474 g_free (str) ;
00475 str = NULL ;
00476 }
00477
00478 return result ;
00479 }
00480
00481
00482
00483
00484
00485 void
00486 cr_declaration_ref (CRDeclaration *a_this)
00487 {
00488 g_return_if_fail (a_this) ;
00489
00490 a_this->ref_count ++ ;
00491 }
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501 gboolean
00502 cr_declaration_unref (CRDeclaration *a_this)
00503 {
00504 g_return_val_if_fail (a_this, FALSE) ;
00505
00506 if (a_this->ref_count)
00507 {
00508 a_this->ref_count -- ;
00509 }
00510
00511 if (a_this->ref_count == 0)
00512 {
00513 cr_declaration_destroy (a_this) ;
00514 return TRUE ;
00515 }
00516 return FALSE ;
00517 }
00518
00519
00520
00521
00522
00523
00524 void
00525 cr_declaration_destroy (CRDeclaration *a_this)
00526 {
00527 CRDeclaration *cur = NULL ;
00528 g_return_if_fail (a_this) ;
00529
00530
00531
00532
00533
00534 for (cur = a_this ; cur && cur->next; cur = cur->next)
00535 {
00536 if (cur->property)
00537 {
00538 g_string_free (cur->property, TRUE) ;
00539 cur->property = NULL ;
00540 }
00541
00542 if (cur->value)
00543 {
00544 cr_term_destroy (cur->value) ;
00545 cur->value = NULL ;
00546 }
00547 }
00548
00549 if (cur)
00550 {
00551 if (cur->property)
00552 {
00553 g_string_free (cur->property, TRUE) ;
00554 cur->property = NULL ;
00555 }
00556
00557 if (cur->value)
00558 {
00559 cr_term_destroy (cur->value) ;
00560 cur->value = NULL ;
00561 }
00562 }
00563
00564
00565 if (cur && !cur->prev)
00566 {
00567 g_free (cur) ;
00568 return ;
00569 }
00570
00571
00572 for (cur = cur->prev ; cur && cur->prev ; cur = cur->prev)
00573 {
00574 if (cur->next)
00575 {
00576 g_free (cur->next) ;
00577 cur->next = NULL ;
00578 }
00579 }
00580
00581 if (!cur)
00582 return ;
00583
00584 if (cur->next)
00585 {
00586 g_free (cur->next) ;
00587 cur->next = NULL ;
00588 }
00589
00590 g_free (cur) ;
00591 }