Libcroco
|
00001 /* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */ 00002 00003 /* 00004 * This file is part of The Croco Library 00005 * 00006 * This program is free software; you can redistribute it and/or 00007 * modify it under the terms of version 2.1 of the GNU Lesser General Public 00008 * License as published by the Free Software Foundation. 00009 * 00010 * This program is distributed in the hope that it will be useful, 00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 * GNU General Public License for more details. 00014 * 00015 * You should have received a copy of the GNU Lesser General Public License 00016 * along with this program; if not, write to the Free Software 00017 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 00018 * USA 00019 * 00020 * Author: Dodji Seketeli 00021 * See COPYRIGHTS file for copyright information. 00022 */ 00023 00024 #include <string.h> 00025 #include <glib.h> 00026 #include "cr-simple-sel.h" 00027 00028 /** 00029 * cr_simple_sel_new: 00030 * 00031 *The constructor of #CRSimpleSel. 00032 * 00033 *Returns the new instance of #CRSimpleSel. 00034 */ 00035 CRSimpleSel * 00036 cr_simple_sel_new (void) 00037 { 00038 CRSimpleSel *result = NULL; 00039 00040 result = g_try_malloc (sizeof (CRSimpleSel)); 00041 if (!result) { 00042 cr_utils_trace_info ("Out of memory"); 00043 return NULL; 00044 } 00045 memset (result, 0, sizeof (CRSimpleSel)); 00046 00047 return result; 00048 } 00049 00050 /** 00051 * cr_simple_sel_append_simple_sel: 00052 * 00053 *Appends a simpe selector to the current list of simple selector. 00054 * 00055 *@a_this: the this pointer of the current instance of #CRSimpleSel. 00056 *@a_sel: the simple selector to append. 00057 * 00058 *Returns: the new list upon successfull completion, an error code otherwise. 00059 */ 00060 CRSimpleSel * 00061 cr_simple_sel_append_simple_sel (CRSimpleSel * a_this, CRSimpleSel * a_sel) 00062 { 00063 CRSimpleSel *cur = NULL; 00064 00065 g_return_val_if_fail (a_sel, NULL); 00066 00067 if (a_this == NULL) 00068 return a_sel; 00069 00070 for (cur = a_this; cur->next; cur = cur->next) ; 00071 00072 cur->next = a_sel; 00073 a_sel->prev = cur; 00074 00075 return a_this; 00076 } 00077 00078 /** 00079 * cr_simple_sel_prepend_simple_sel: 00080 * 00081 *@a_this: the this pointer of the current instance of #CRSimpleSel. 00082 *@a_sel: the simple selector to prepend. 00083 * 00084 *Prepends a simple selector to the current list of simple selectors. 00085 * 00086 *Returns the new list upon successfull completion, an error code otherwise. 00087 */ 00088 CRSimpleSel * 00089 cr_simple_sel_prepend_simple_sel (CRSimpleSel * a_this, CRSimpleSel * a_sel) 00090 { 00091 g_return_val_if_fail (a_sel, NULL); 00092 00093 if (a_this == NULL) 00094 return a_sel; 00095 00096 a_sel->next = a_this; 00097 a_this->prev = a_sel; 00098 00099 return a_sel; 00100 } 00101 00102 guchar * 00103 cr_simple_sel_to_string (CRSimpleSel const * a_this) 00104 { 00105 GString *str_buf = NULL; 00106 guchar *result = NULL; 00107 00108 CRSimpleSel const *cur = NULL; 00109 00110 g_return_val_if_fail (a_this, NULL); 00111 00112 str_buf = g_string_new (NULL); 00113 for (cur = a_this; cur; cur = cur->next) { 00114 if (cur->name) { 00115 guchar *str = (guchar *) g_strndup (cur->name->stryng->str, 00116 cur->name->stryng->len); 00117 00118 if (str) { 00119 switch (cur->combinator) { 00120 case COMB_WS: 00121 g_string_append (str_buf, " "); 00122 break; 00123 00124 case COMB_PLUS: 00125 g_string_append (str_buf, "+"); 00126 break; 00127 00128 case COMB_GT: 00129 g_string_append (str_buf, ">"); 00130 break; 00131 00132 default: 00133 break; 00134 } 00135 00136 g_string_append (str_buf, (const gchar *) str); 00137 g_free (str); 00138 str = NULL; 00139 } 00140 } 00141 00142 if (cur->add_sel) { 00143 guchar *tmp_str = NULL; 00144 00145 tmp_str = cr_additional_sel_to_string (cur->add_sel); 00146 if (tmp_str) { 00147 g_string_append (str_buf, (const gchar *) tmp_str); 00148 g_free (tmp_str); 00149 tmp_str = NULL; 00150 } 00151 } 00152 } 00153 00154 if (str_buf) { 00155 result = (guchar *) str_buf->str; 00156 g_string_free (str_buf, FALSE); 00157 str_buf = NULL; 00158 } 00159 00160 return result; 00161 } 00162 00163 00164 guchar * 00165 cr_simple_sel_one_to_string (CRSimpleSel const * a_this) 00166 { 00167 GString *str_buf = NULL; 00168 guchar *result = NULL; 00169 00170 g_return_val_if_fail (a_this, NULL); 00171 00172 str_buf = g_string_new (NULL); 00173 if (a_this->name) { 00174 guchar *str = (guchar *) g_strndup (a_this->name->stryng->str, 00175 a_this->name->stryng->len); 00176 00177 if (str) { 00178 g_string_append_printf (str_buf, "%s", str); 00179 g_free (str); 00180 str = NULL; 00181 } 00182 } 00183 00184 if (a_this->add_sel) { 00185 guchar *tmp_str = NULL; 00186 00187 tmp_str = cr_additional_sel_to_string (a_this->add_sel); 00188 if (tmp_str) { 00189 g_string_append_printf 00190 (str_buf, "%s", tmp_str); 00191 g_free (tmp_str); 00192 tmp_str = NULL; 00193 } 00194 } 00195 00196 if (str_buf) { 00197 result = (guchar *) str_buf->str; 00198 g_string_free (str_buf, FALSE); 00199 str_buf = NULL; 00200 } 00201 00202 return result; 00203 } 00204 00205 /** 00206 * cr_simple_sel_dump: 00207 *@a_this: the current instance of #CRSimpleSel. 00208 *@a_fp: the destination file pointer. 00209 * 00210 *Dumps the selector to a file. 00211 *TODO: add the support of unicode in the dump. 00212 * 00213 *Returns CR_OK upon successfull completion, an error code 00214 *otherwise. 00215 */ 00216 enum CRStatus 00217 cr_simple_sel_dump (CRSimpleSel const * a_this, FILE * a_fp) 00218 { 00219 guchar *tmp_str = NULL; 00220 00221 g_return_val_if_fail (a_fp, CR_BAD_PARAM_ERROR); 00222 00223 if (a_this) { 00224 tmp_str = cr_simple_sel_to_string (a_this); 00225 if (tmp_str) { 00226 fprintf (a_fp, "%s", tmp_str); 00227 g_free (tmp_str); 00228 tmp_str = NULL; 00229 } 00230 } 00231 00232 return CR_OK; 00233 } 00234 00235 /** 00236 * cr_simple_sel_compute_specificity: 00237 * 00238 *@a_this: the current instance of #CRSimpleSel 00239 * 00240 *Computes the selector (combinator separated list of simple selectors) 00241 *as defined in the css2 spec in chapter 6.4.3 00242 * 00243 *Returns CR_OK upon successfull completion, an error code otherwise. 00244 */ 00245 enum CRStatus 00246 cr_simple_sel_compute_specificity (CRSimpleSel * a_this) 00247 { 00248 CRAdditionalSel const *cur_add_sel = NULL; 00249 CRSimpleSel const *cur_sel = NULL; 00250 gulong a = 0, 00251 b = 0, 00252 c = 0; 00253 00254 g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR); 00255 00256 for (cur_sel = a_this; cur_sel; cur_sel = cur_sel->next) { 00257 if (cur_sel->type_mask & TYPE_SELECTOR) { 00258 c++; /*hmmh, is this a new language ? */ 00259 } else if (!cur_sel->name 00260 || !cur_sel->name->stryng 00261 || !cur_sel->name->stryng->str) { 00262 if (cur_sel->add_sel->type == 00263 PSEUDO_CLASS_ADD_SELECTOR) { 00264 /* 00265 *this is a pseudo element, and 00266 *the spec says, "ignore pseudo elements". 00267 */ 00268 continue; 00269 } 00270 } 00271 00272 for (cur_add_sel = cur_sel->add_sel; 00273 cur_add_sel; cur_add_sel = cur_add_sel->next) { 00274 switch (cur_add_sel->type) { 00275 case ID_ADD_SELECTOR: 00276 a++; 00277 break; 00278 00279 case NO_ADD_SELECTOR: 00280 continue; 00281 00282 default: 00283 b++; 00284 break; 00285 } 00286 } 00287 } 00288 00289 /*we suppose a, b and c have 1 to 3 digits */ 00290 a_this->specificity = a * 1000000 + b * 1000 + c; 00291 00292 return CR_OK; 00293 } 00294 00295 /** 00296 * cr_simple_sel_destroy: 00297 * 00298 *@a_this: the this pointer of the current instance of #CRSimpleSel. 00299 * 00300 *The destructor of the current instance of 00301 *#CRSimpleSel. 00302 */ 00303 void 00304 cr_simple_sel_destroy (CRSimpleSel * a_this) 00305 { 00306 g_return_if_fail (a_this); 00307 00308 if (a_this->name) { 00309 cr_string_destroy (a_this->name); 00310 a_this->name = NULL; 00311 } 00312 00313 if (a_this->add_sel) { 00314 cr_additional_sel_destroy (a_this->add_sel); 00315 a_this->add_sel = NULL; 00316 } 00317 00318 if (a_this->next) { 00319 cr_simple_sel_destroy (a_this->next); 00320 } 00321 00322 if (a_this) { 00323 g_free (a_this); 00324 } 00325 }