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-sel-eng.h"
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 #define PRIVATE(a_this) (a_this)->priv
00037
00038 static gboolean
00039 class_add_sel_matches_node (CRAdditionalSel *a_add_sel,
00040 xmlNode *a_node) ;
00041
00042 static gboolean
00043 id_add_sel_matches_node (CRAdditionalSel *a_add_sel,
00044 xmlNode *a_node) ;
00045
00046 static gboolean
00047 attr_add_sel_matches_node (CRAdditionalSel *a_add_sel,
00048 xmlNode *a_node) ;
00049
00050 static enum CRStatus
00051 sel_matches_node_real (CRSelEng *a_this, CRSimpleSel *a_sel,
00052 xmlNode *a_node, gboolean *a_result,
00053 gboolean a_recurse) ;
00054
00055 static enum CRStatus
00056 cr_sel_eng_get_matched_rulesets_real (CRSelEng *a_this,
00057 CRStyleSheet *a_stylesheet,
00058 xmlNode *a_node,
00059 CRStatement **a_rulesets,
00060 gulong *a_len) ;
00061
00062 static enum CRStatus
00063 put_css_properties_in_hashtable (GHashTable **a_props_hashtable,
00064 CRStatement *a_ruleset) ;
00065
00066 static void
00067 set_style_from_props_hash_hr_func (gpointer a_prop, gpointer a_decl,
00068 gpointer a_style) ;
00069
00070 struct _CRSelEngPriv
00071 {
00072
00073 gboolean case_sensitive ;
00074
00075 CRStyleSheet *sheet ;
00076
00077
00078
00079
00080
00081
00082 CRStatement *cur_stmt ;
00083 };
00084
00085
00086
00087
00088
00089
00090
00091 static gboolean
00092 class_add_sel_matches_node (CRAdditionalSel *a_add_sel,
00093 xmlNode *a_node)
00094 {
00095 gboolean result = FALSE ;
00096 xmlChar *class = NULL ;
00097
00098 g_return_val_if_fail (a_add_sel
00099 && a_add_sel->type == CLASS_ADD_SELECTOR
00100 && a_add_sel->content.class_name
00101 && a_add_sel->content.class_name->str
00102 && a_node, FALSE) ;
00103
00104 if (xmlHasProp (a_node, "class"))
00105 {
00106 class = xmlGetProp (a_node, "class") ;
00107 if (!strncmp (class, a_add_sel->content.class_name->str,
00108 a_add_sel->content.class_name->len))
00109 {
00110 result = TRUE ;
00111 }
00112 }
00113
00114 if (class)
00115 {
00116 xmlFree (class) ;
00117 class = NULL ;
00118 }
00119 return result ;
00120
00121 }
00122
00123
00124
00125
00126
00127
00128
00129 static gboolean
00130 id_add_sel_matches_node (CRAdditionalSel *a_add_sel,
00131 xmlNode *a_node)
00132 {
00133 g_return_val_if_fail (a_add_sel
00134 && a_add_sel->type == ID_ADD_SELECTOR
00135 && a_add_sel->content.id_name
00136 && a_add_sel->content.id_name->str
00137 && a_node, FALSE) ;
00138
00139 gboolean result = FALSE ;
00140 xmlChar *id = NULL ;
00141
00142 g_return_val_if_fail (a_add_sel
00143 && a_add_sel->type == ID_ADD_SELECTOR
00144 && a_node, FALSE) ;
00145
00146 if (xmlHasProp (a_node, "id"))
00147 {
00148 id = xmlGetProp (a_node, "id") ;
00149 if (!strncmp (id, a_add_sel->content.id_name->str,
00150 a_add_sel->content.id_name->len))
00151 {
00152 result = TRUE ;
00153 }
00154 }
00155
00156 if (id)
00157 {
00158 xmlFree (id) ;
00159 id = NULL ;
00160 }
00161 return result ;
00162 }
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173 static gboolean
00174 attr_add_sel_matches_node (CRAdditionalSel *a_add_sel,
00175 xmlNode *a_node)
00176 {
00177 CRAttrSel *cur_sel = NULL ;
00178
00179 g_return_val_if_fail (a_add_sel
00180 && a_add_sel->type == ATTRIBUTE_ADD_SELECTOR
00181 && a_node, FALSE) ;
00182
00183 for (cur_sel = a_add_sel->content.attr_sel ;
00184 cur_sel ; cur_sel = cur_sel->next)
00185 {
00186 switch (cur_sel->match_way)
00187 {
00188 case SET:
00189 if (!cur_sel->name || !cur_sel->name->str)
00190 return FALSE ;
00191
00192 if (!xmlHasProp (a_node, cur_sel->name->str))
00193 return FALSE ;
00194 break ;
00195
00196 case EQUALS:
00197 {
00198 xmlChar *value = NULL ;
00199
00200 if (!cur_sel->name || !cur_sel->name->str
00201 || !cur_sel->value || !cur_sel->value->str)
00202 return FALSE ;
00203
00204 if (!xmlHasProp (a_node, cur_sel->name->str))
00205 return FALSE ;
00206
00207 value = xmlGetProp (a_node, cur_sel->name->str) ;
00208
00209 if (value && strncmp (value, cur_sel->value->str,
00210 cur_sel->value->len))
00211 {
00212 xmlFree (value) ;
00213 return FALSE ;
00214 }
00215 xmlFree (value);
00216 }
00217 break ;
00218
00219 case INCLUDES:
00220 {
00221 xmlChar *value = NULL, *ptr1 = NULL, *ptr2 = NULL,
00222 *cur = NULL;
00223 gboolean found = FALSE ;
00224
00225 if (!xmlHasProp (a_node, cur_sel->name->str))
00226 return FALSE ;
00227 value = xmlGetProp (a_node, cur_sel->name->str) ;
00228
00229 if (!value)
00230 return FALSE;
00231
00232
00233
00234
00235
00236
00237 for (cur = value ; *cur ; cur++)
00238 {
00239
00240
00241
00242
00243 while (cr_utils_is_white_space
00244 (*cur) == TRUE && *cur)
00245 cur ++ ;
00246 if (!*cur)
00247 break ;
00248 ptr1 = cur ;
00249
00250
00251
00252
00253 while (cr_utils_is_white_space
00254 (*cur) == FALSE && *cur)
00255 cur++ ;
00256 if (!*cur)
00257 break ;
00258 cur-- ;
00259 ptr2 = cur ;
00260
00261 if (!strncmp (ptr1, cur_sel->value->str,
00262 ptr2 - ptr1 + 1))
00263 {
00264 found = TRUE ;
00265 break ;
00266 }
00267 ptr1 = ptr2 = NULL ;
00268 }
00269
00270 if (found == FALSE)
00271 {
00272 xmlFree (value) ;
00273 return FALSE ;
00274 }
00275 xmlFree (value) ;
00276 }
00277 break ;
00278
00279 case DASHMATCH:
00280 {
00281 xmlChar *value = NULL, *ptr1 = NULL, *ptr2 = NULL,
00282 *cur = NULL;
00283 gboolean found = FALSE ;
00284
00285 if (!xmlHasProp (a_node, cur_sel->name->str))
00286 return FALSE ;
00287 value = xmlGetProp (a_node, cur_sel->name->str) ;
00288
00289
00290
00291
00292
00293
00294 for (cur = value ; *cur ; cur++)
00295 {
00296 if (*cur == '-')
00297 cur ++ ;
00298 ptr1 = cur ;
00299
00300 while (*cur != '-' && *cur)
00301 cur ++ ;
00302 if (!*cur)
00303 break ;
00304 cur-- ;
00305 ptr2 = cur ;
00306
00307 if (g_strstr_len (ptr1, ptr2 - ptr1 + 1,
00308 cur_sel->value->str)
00309 == (gchar*)ptr1)
00310 {
00311 found = TRUE ;
00312 break ;
00313 }
00314 }
00315
00316 if (found == FALSE)
00317 {
00318 xmlFree (value) ;
00319 return FALSE ;
00320 }
00321 xmlFree (value) ;
00322 }
00323 break ;
00324 default:
00325 return FALSE ;
00326 }
00327 }
00328
00329 return TRUE ;
00330 }
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350 static enum CRStatus
00351 sel_matches_node_real (CRSelEng *a_this, CRSimpleSel *a_sel,
00352 xmlNode *a_node, gboolean *a_result,
00353 gboolean a_recurse)
00354 {
00355 CRSimpleSel *cur_sel = NULL ;
00356 xmlNode *cur_node = NULL ;
00357
00358 g_return_val_if_fail (a_this && PRIVATE (a_this)
00359 && a_this && a_node
00360 && a_result,
00361 CR_BAD_PARAM_ERROR) ;
00362
00363 *a_result = FALSE ;
00364
00365 if (a_node->type != XML_ELEMENT_NODE)
00366 return CR_OK ;
00367
00368
00369 if (a_recurse == TRUE)
00370 {
00371
00372 for (cur_sel = a_sel ;
00373 cur_sel && cur_sel->next ;
00374 cur_sel = cur_sel->next) ;
00375 }
00376 else
00377 {
00378 cur_sel = a_sel ;
00379 }
00380
00381 for (cur_node = a_node ; cur_sel ; cur_sel = cur_sel->prev)
00382 {
00383 if (cur_sel->type_mask & UNIVERSAL_SELECTOR)
00384 {
00385 goto walk_a_step_in_expr ;
00386 }
00387 else if (cur_sel->type_mask & TYPE_SELECTOR)
00388 {
00389 if (cur_sel && cur_sel->name && cur_sel->name->str)
00390 {
00391 if (!strcmp (cur_sel->name->str,
00392 cur_node->name))
00393 {
00394
00395
00396
00397
00398
00399
00400
00401 goto walk_a_step_in_expr ;
00402 }
00403 goto done ;
00404 }
00405 else
00406 {
00407 goto done ;
00408 }
00409 }
00410
00411 if (!cur_sel->add_sel)
00412 {
00413 goto done ;
00414 }
00415
00416 if (cur_sel->add_sel->type == NO_ADD_SELECTOR)
00417 {
00418 goto done ;
00419 }
00420
00421 if (cur_sel->add_sel->type == CLASS_ADD_SELECTOR
00422 && cur_sel->add_sel->content.class_name
00423 && cur_sel->add_sel->content.class_name->str)
00424 {
00425 if (class_add_sel_matches_node
00426 (cur_sel->add_sel, cur_node) == FALSE)
00427 {
00428 goto done ;
00429 }
00430 goto walk_a_step_in_expr ;
00431 }
00432 else if (cur_sel->add_sel->type == ID_ADD_SELECTOR
00433 && cur_sel->add_sel->content.id_name
00434 && cur_sel->add_sel->content.id_name->str)
00435 {
00436 if (id_add_sel_matches_node
00437 (cur_sel->add_sel, cur_node) == FALSE)
00438 {
00439 goto done;
00440 }
00441 goto walk_a_step_in_expr ;
00442 }
00443 else if (cur_sel->add_sel->type == ATTRIBUTE_ADD_SELECTOR
00444 && cur_sel->add_sel->content.attr_sel)
00445 {
00446
00447
00448
00449
00450
00451 if (attr_add_sel_matches_node
00452 (cur_sel->add_sel, cur_node)
00453 == FALSE)
00454 {
00455 goto done ;
00456 }
00457 goto walk_a_step_in_expr ;
00458 }
00459
00460 walk_a_step_in_expr:
00461 if (a_recurse == FALSE)
00462 {
00463 *a_result = TRUE ;
00464 goto done ;
00465 }
00466
00467
00468
00469
00470
00471
00472 if (!cur_sel->prev)
00473 break ;
00474
00475 switch (cur_sel->combinator)
00476 {
00477 case NO_COMBINATOR:
00478 break ;
00479
00480 case COMB_WS:
00481 {
00482 xmlNode *n = NULL ;
00483 enum CRStatus status = CR_OK ;
00484 gboolean matches= FALSE ;
00485
00486
00487
00488
00489
00490 for (n = cur_node->parent ; n ; n = n->parent)
00491 {
00492 status =
00493 sel_matches_node_real (a_this,
00494 cur_sel->prev,
00495 n,
00496 &matches,
00497 FALSE) ;
00498 if (status != CR_OK)
00499 goto done ;
00500
00501 if (matches == TRUE)
00502 {
00503 cur_node = n ;
00504 break ;
00505 }
00506 }
00507
00508 if (!n)
00509 {
00510
00511
00512
00513
00514 goto done ;
00515 }
00516
00517
00518
00519
00520
00521
00522
00523
00524 break ;
00525 }
00526
00527 case COMB_PLUS:
00528 {
00529 if (!cur_node->prev)
00530 goto done ;
00531 cur_node = cur_node->prev ;
00532 }
00533 break ;
00534
00535 case COMB_GT:
00536 if (!cur_node->parent)
00537 goto done ;
00538 cur_node = cur_node->parent ;
00539 break ;
00540
00541 default:
00542 goto done ;
00543 }
00544 continue ;
00545
00546 }
00547
00548
00549
00550
00551
00552 *a_result = TRUE ;
00553
00554 done:
00555 return CR_OK ;
00556 }
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596 static enum CRStatus
00597 cr_sel_eng_get_matched_rulesets_real (CRSelEng *a_this,
00598 CRStyleSheet *a_stylesheet,
00599 xmlNode *a_node,
00600 CRStatement **a_rulesets,
00601 gulong *a_len)
00602 {
00603 CRStatement *cur_stmt = NULL ;
00604 CRSelector *sel_list = NULL, *cur_sel = NULL ;
00605 gboolean matches = FALSE ;
00606 enum CRStatus status = CR_OK ;
00607 gulong i = 0;
00608
00609 g_return_val_if_fail (a_this
00610 && a_stylesheet
00611 && a_stylesheet->statements
00612 && a_node
00613 && a_rulesets,
00614 CR_BAD_PARAM_ERROR) ;
00615
00616
00617
00618
00619
00620 if (PRIVATE (a_this)->sheet != a_stylesheet)
00621 {
00622 PRIVATE (a_this)->sheet = a_stylesheet ;
00623 PRIVATE (a_this)->cur_stmt = a_stylesheet->statements ;
00624 }
00625
00626
00627
00628
00629
00630
00631
00632 for (cur_stmt = PRIVATE (a_this)->cur_stmt, i = 0 ;
00633 (PRIVATE (a_this)->cur_stmt = cur_stmt);
00634 cur_stmt = cur_stmt->next)
00635 {
00636
00637
00638
00639
00640 sel_list = NULL ;
00641
00642
00643
00644
00645
00646 switch (cur_stmt->type)
00647 {
00648 case RULESET_STMT:
00649 if (cur_stmt->kind.ruleset
00650 && cur_stmt->kind.ruleset->sel_list)
00651 {
00652 sel_list = cur_stmt->kind.ruleset->sel_list ;
00653 }
00654 break ;
00655
00656 case AT_MEDIA_RULE_STMT:
00657 if (cur_stmt->kind.media_rule
00658 && cur_stmt->kind.media_rule->rulesets
00659 && cur_stmt->kind.media_rule->rulesets->
00660 kind.ruleset
00661 &&cur_stmt->kind.media_rule->rulesets->
00662 kind.ruleset->sel_list)
00663 {
00664 sel_list =
00665 cur_stmt->kind.media_rule->
00666 rulesets->kind.ruleset->sel_list ;
00667 }
00668 break ;
00669
00670 case AT_IMPORT_RULE_STMT:
00671
00672
00673
00674
00675 break ;
00676 default:
00677 break ;
00678 }
00679
00680 if (!sel_list)
00681 continue ;
00682
00683
00684
00685
00686
00687
00688 for (cur_sel = sel_list ; cur_sel ; cur_sel = cur_sel->next)
00689 {
00690 if (!cur_sel->simple_sel)
00691 continue ;
00692
00693 status = cr_sel_eng_matches_node
00694 (a_this, cur_sel->simple_sel,
00695 a_node, &matches) ;
00696
00697 if (status == CR_OK && matches == TRUE)
00698 {
00699
00700
00701
00702
00703
00704
00705 if (i < *a_len)
00706 {
00707 a_rulesets[i] = cur_stmt ;
00708 i++ ;
00709
00710
00711
00712
00713
00714
00715
00716
00717
00718
00719 status =
00720 cr_simple_sel_compute_specificity
00721 (cur_sel->simple_sel) ;
00722
00723 g_return_val_if_fail (status == CR_OK,
00724 CR_ERROR) ;
00725 cur_stmt->specificity =
00726 cur_sel->simple_sel->specificity;
00727 }
00728 else
00729
00730 {
00731 *a_len = i ;
00732 return CR_OUTPUT_TOO_SHORT_ERROR ;
00733 }
00734 }
00735 }
00736 }
00737
00738
00739
00740
00741
00742
00743
00744 g_return_val_if_fail (!PRIVATE (a_this)->cur_stmt, CR_ERROR) ;
00745 PRIVATE (a_this)->sheet = NULL ;
00746 *a_len = i ;
00747 return CR_OK ;
00748 }
00749
00750
00751
00752
00753
00754
00755
00756
00757
00758
00759
00760
00761
00762
00763
00764
00765
00766
00767 static enum CRStatus
00768 put_css_properties_in_hashtable (GHashTable **a_props_hashtable,
00769 CRStatement *a_stmt)
00770 {
00771 GHashTable *props_hash = NULL ;
00772 CRDeclaration *cur_decl = NULL ;
00773
00774 g_return_val_if_fail (a_props_hashtable && a_stmt
00775 && a_stmt->type == RULESET_STMT
00776 && a_stmt->kind.ruleset,
00777 CR_BAD_PARAM_ERROR) ;
00778
00779 if (!*a_props_hashtable)
00780 {
00781 *a_props_hashtable = g_hash_table_new (g_str_hash,
00782 g_str_equal) ;
00783 }
00784 props_hash = *a_props_hashtable ;
00785
00786 for (cur_decl = a_stmt->kind.ruleset->decl_list ;
00787 cur_decl ; cur_decl = cur_decl->next)
00788 {
00789 if (!cur_decl->property || !cur_decl->property->str)
00790 continue ;
00791
00792 CRDeclaration *decl = NULL ;
00793
00794
00795
00796
00797
00798
00799
00800
00801 decl = g_hash_table_lookup
00802 (props_hash, cur_decl->property->str) ;
00803
00804 if (!decl)
00805 {
00806 g_hash_table_replace
00807 (props_hash,
00808 cur_decl->property->str,
00809 cur_decl) ;
00810 continue ;
00811 }
00812
00813
00814
00815
00816
00817
00818
00819
00820
00821
00822
00823
00824
00825
00826
00827
00828 if (decl->parent_statement
00829 && decl->parent_statement->parent_sheet
00830 && (decl->parent_statement->parent_sheet->origin
00831 <
00832 a_stmt->parent_sheet->origin))
00833 {
00834 g_hash_table_insert
00835 (props_hash,
00836 cur_decl->property->str,
00837 cur_decl) ;
00838 continue ;
00839 }
00840 else if (decl->parent_statement
00841 && decl->parent_statement->parent_sheet
00842 && (decl->parent_statement->
00843 parent_sheet->origin
00844 >
00845 a_stmt->parent_sheet->origin))
00846 {
00847
00848 continue ;
00849 }
00850
00851
00852
00853
00854
00855
00856
00857
00858
00859
00860
00861
00862
00863 if (a_stmt->specificity
00864 >= decl->parent_statement->specificity)
00865 {
00866 g_hash_table_insert
00867 (props_hash,
00868 cur_decl->property->str,
00869 cur_decl) ;
00870 }
00871 }
00872
00873
00874 return CR_OK ;
00875 }
00876
00877
00878
00879 static void
00880 set_style_from_props_hash_hr_func (gpointer a_prop, gpointer a_decl,
00881 gpointer a_style)
00882 {
00883 CRDeclaration *decl = a_decl ;
00884 CRStyle *style = a_style ;
00885
00886 g_return_if_fail (a_decl && a_prop && a_style) ;
00887
00888 cr_style_set_style_from_decl (style, decl) ;
00889 }
00890
00891
00892
00893
00894
00895
00896
00897
00898
00899
00900
00901 CRSelEng *
00902 cr_sel_eng_new (void)
00903 {
00904 CRSelEng *result = NULL;
00905
00906 result = g_try_malloc (sizeof (CRSelEng)) ;
00907 if (!result)
00908 {
00909 cr_utils_trace_info ("Out of memory") ;
00910 return NULL ;
00911 }
00912 memset (result, 0, sizeof (CRSelEng)) ;
00913
00914 PRIVATE (result) = g_try_malloc (sizeof (CRSelEngPriv)) ;
00915 if (!PRIVATE (result))
00916 {
00917 cr_utils_trace_info ("Out of memory") ;
00918 g_free (result) ;
00919 return NULL ;
00920 }
00921 memset (PRIVATE (result), 0, sizeof (CRSelEngPriv)) ;
00922
00923 return result ;
00924 }
00925
00926
00927
00928
00929
00930
00931
00932
00933
00934
00935
00936
00937
00938
00939
00940 enum CRStatus
00941 cr_sel_eng_matches_node (CRSelEng *a_this, CRSimpleSel *a_sel,
00942 xmlNode *a_node, gboolean *a_result)
00943 {
00944 g_return_val_if_fail (a_this && PRIVATE (a_this)
00945 && a_this && a_node
00946 && a_result,
00947 CR_BAD_PARAM_ERROR) ;
00948
00949 if (a_node->type != XML_ELEMENT_NODE)
00950 {
00951 *a_result = FALSE ;
00952 return CR_OK ;
00953 }
00954
00955 return sel_matches_node_real (a_this, a_sel, a_node,
00956 a_result, TRUE) ;
00957 }
00958
00959
00960
00961
00962
00963
00964
00965
00966
00967
00968
00969
00970
00971
00972
00973
00974
00975 enum CRStatus
00976 cr_sel_eng_get_matched_rulesets (CRSelEng *a_this,
00977 CRStyleSheet *a_sheet,
00978 xmlNode *a_node,
00979 CRStatement ***a_rulesets,
00980 gulong *a_len)
00981 {
00982 CRStatement ** stmts_tab = NULL ;
00983 enum CRStatus status = CR_OK ;
00984 gulong tab_size = 0, tab_len = 0, index = 0 ;
00985 gushort stmts_chunck_size = 8 ;
00986
00987 g_return_val_if_fail (a_this
00988 && a_sheet
00989 && a_node
00990 && a_rulesets && *a_rulesets == NULL
00991 && a_len,
00992 CR_BAD_PARAM_ERROR) ;
00993
00994 stmts_tab = g_try_malloc (stmts_chunck_size *
00995 sizeof (CRStatement *)) ;
00996
00997 if (!stmts_tab)
00998 {
00999 cr_utils_trace_info ("Out of memory") ;
01000 status = CR_ERROR ;
01001 goto error ;
01002 }
01003 memset (stmts_tab, 0, stmts_chunck_size * sizeof (CRStatement*)) ;
01004
01005 tab_size = stmts_chunck_size ;
01006 tab_len = tab_size ;
01007
01008 while ((status = cr_sel_eng_get_matched_rulesets_real
01009 (a_this, a_sheet, a_node, stmts_tab + index, &tab_len))
01010 == CR_OUTPUT_TOO_SHORT_ERROR)
01011 {
01012 stmts_tab = g_try_realloc (stmts_tab,
01013 (tab_size + stmts_chunck_size)
01014 * sizeof (CRStatement*)) ;
01015 if (!stmts_tab)
01016 {
01017 cr_utils_trace_info ("Out of memory") ;
01018 status = CR_ERROR ;
01019 goto error ;
01020 }
01021 tab_size += stmts_chunck_size ;
01022 index += tab_len ;
01023 tab_len = tab_size - index ;
01024 }
01025
01026
01027 tab_len = tab_size - stmts_chunck_size +tab_len ;
01028 *a_rulesets = stmts_tab ;
01029 *a_len = tab_len ;
01030
01031 return CR_OK ;
01032
01033 error:
01034
01035 if (stmts_tab)
01036 {
01037 g_free (stmts_tab) ;
01038 stmts_tab = NULL ;
01039
01040 }
01041
01042 *a_len = 0 ;
01043 return status ;
01044 }
01045
01046 enum CRStatus
01047 cr_sel_eng_get_matched_properties_from_cascade (CRSelEng *a_this,
01048 CRCascade *a_cascade,
01049 xmlNode *a_node,
01050 GHashTable **a_props_hashtable)
01051 {
01052 CRStatement ** stmts_tab = NULL ;
01053 enum CRStatus status = CR_OK ;
01054 gulong tab_size = 0, tab_len = 0, index = 0, i = 0 ;
01055 enum CRStyleOrigin origin = 0 ;
01056 gushort stmts_chunck_size = 8 ;
01057 CRStyleSheet *sheet = NULL ;
01058
01059 g_return_val_if_fail (a_this
01060 && a_cascade
01061 && a_node
01062 && a_props_hashtable,
01063 CR_BAD_PARAM_ERROR) ;
01064
01065 stmts_tab = g_try_malloc (stmts_chunck_size *
01066 sizeof (CRStatement *)) ;
01067
01068 if (!stmts_tab)
01069 {
01070 cr_utils_trace_info ("Out of memory") ;
01071 status = CR_ERROR ;
01072 goto error ;
01073 }
01074 memset (stmts_tab, 0, stmts_chunck_size * sizeof (CRStatement*)) ;
01075 tab_size = stmts_chunck_size ;
01076 tab_len = tab_size ;
01077
01078 for (origin = ORIGIN_UA ; origin < NB_ORIGINS ; origin++)
01079 {
01080 sheet = cr_cascade_get_sheet (a_cascade, origin) ;
01081 if (!sheet)
01082 continue ;
01083
01084 while ((status = cr_sel_eng_get_matched_rulesets_real
01085 (a_this, sheet, a_node, stmts_tab + index, &tab_len))
01086 == CR_OUTPUT_TOO_SHORT_ERROR)
01087 {
01088 stmts_tab = g_try_realloc
01089 (stmts_tab,
01090 (tab_size + stmts_chunck_size)
01091 * sizeof (CRStatement*)) ;
01092 if (!stmts_tab)
01093 {
01094 cr_utils_trace_info ("Out of memory") ;
01095 status = CR_ERROR ;
01096 goto error ;
01097 }
01098 tab_size += stmts_chunck_size ;
01099 index += tab_len ;
01100 tab_len = tab_size - index ;
01101 }
01102 if (status != CR_OK)
01103 {
01104 cr_utils_trace_info ("Error while running "
01105 "selector engine") ;
01106 goto error ;
01107 }
01108
01109 }
01110
01111
01112
01113
01114
01115
01116
01117 for (i = 0 ; i < tab_len ; i ++)
01118 {
01119 CRStatement *stmt = stmts_tab[i] ;
01120
01121 if (!stmt)
01122 continue ;
01123
01124 switch (stmt->type)
01125 {
01126 case RULESET_STMT:
01127 if (!stmt->parent_sheet)
01128 continue ;
01129 status = put_css_properties_in_hashtable
01130 (a_props_hashtable,
01131 stmt) ;
01132 break ;
01133
01134 default:
01135 break ;
01136 }
01137
01138 }
01139
01140 return CR_OK ;
01141 error:
01142
01143 if (stmts_tab)
01144 {
01145 g_free (stmts_tab) ;
01146 stmts_tab = NULL ;
01147
01148 }
01149
01150 return status ;
01151 }
01152
01153
01154 enum CRStatus
01155 cr_sel_eng_get_matched_style (CRSelEng *a_this,
01156 CRCascade *a_cascade,
01157 xmlNode *a_node,
01158 CRStyle *a_parent_style,
01159 CRStyle **a_style)
01160 {
01161 enum CRStatus status = CR_OK ;
01162 GHashTable *props_hash = NULL ;
01163
01164 g_return_val_if_fail (a_this && a_cascade
01165 && a_node && a_style
01166 && (*a_style == NULL),
01167 CR_BAD_PARAM_ERROR) ;
01168
01169 status = cr_sel_eng_get_matched_properties_from_cascade
01170 (a_this, a_cascade, a_node, &props_hash) ;
01171 g_return_val_if_fail (status == CR_OK, status) ;
01172
01173 if (props_hash && g_hash_table_size (props_hash))
01174 {
01175
01176 if (!*a_style)
01177 {
01178 *a_style = cr_style_new () ;
01179 g_return_val_if_fail (*a_style, CR_ERROR) ;
01180 }
01181 (*a_style)->parent_style = a_parent_style ;
01182
01183 g_hash_table_foreach (props_hash,
01184 ((GHFunc)
01185 set_style_from_props_hash_hr_func),
01186 *a_style) ;
01187 }
01188
01189 if (props_hash)
01190 {
01191 g_hash_table_destroy (props_hash) ;
01192 props_hash = NULL ;
01193 }
01194
01195 return CR_OK ;
01196 }
01197
01198
01199
01200
01201
01202 void
01203 cr_sel_eng_destroy (CRSelEng *a_this)
01204 {
01205 g_return_if_fail (a_this) ;
01206
01207 if (PRIVATE (a_this))
01208 {
01209 g_free (PRIVATE (a_this)) ;
01210 PRIVATE (a_this) = NULL ;
01211 }
01212
01213 if (a_this)
01214 {
01215 g_free (a_this) ;
01216 }
01217 }
01218