PageRenderTime 31ms CodeModel.GetById 16ms app.highlight 10ms RepoModel.GetById 1ms app.codeStats 0ms

/cssed-0.4.0/libcroco/parser/cr-simple-sel.c

#
C | 308 lines | 189 code | 54 blank | 65 comment | 33 complexity | fc3476a39f52b7991a28d5cfb4a23273 MD5 | raw file
  1/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */
  2
  3/*
  4 * This file is part of The Croco Library
  5 *
  6 * This program is free software; you can redistribute it and/or
  7 * modify it under the terms of version 2.1 of the GNU Lesser General Public
  8 * License as published by the Free Software Foundation.
  9 *
 10 * This program is distributed in the hope that it will be useful,
 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 13 * GNU General Public License for more details.
 14 *
 15 * You should have received a copy of the GNU Lesser General Public License
 16 * along with this program; if not, write to the Free Software
 17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
 18 * USA
 19 *
 20 * Author: Dodji Seketeli
 21 * See COPYRIGHTS file for copyright information.
 22 */
 23
 24#include <string.h>
 25#include <glib.h>
 26#include "cr-simple-sel.h"
 27
 28/**
 29 *The constructor of #CRSimpleSel.
 30 *
 31 *@return the new instance of #CRSimpleSel.
 32 */
 33CRSimpleSel *
 34cr_simple_sel_new (void)
 35{
 36        CRSimpleSel *result = NULL;
 37
 38        result = g_try_malloc (sizeof (CRSimpleSel));
 39        if (!result) {
 40                cr_utils_trace_info ("Out of memory");
 41                return NULL;
 42        }
 43        memset (result, 0, sizeof (CRSimpleSel));
 44
 45        return result;
 46}
 47
 48/**
 49 *Appends a simpe selector to the current list of simple selector.
 50 *
 51 *@param a_this the this pointer of the current instance of #CRSimpleSel.
 52 *@param a_sel the simple selector to append.
 53 *@return the new list upon successfull completion, an error code otherwise.
 54 */
 55CRSimpleSel *
 56cr_simple_sel_append_simple_sel (CRSimpleSel * a_this, CRSimpleSel * a_sel)
 57{
 58        CRSimpleSel *cur = NULL;
 59
 60        g_return_val_if_fail (a_sel, NULL);
 61
 62        if (a_this == NULL)
 63                return a_sel;
 64
 65        for (cur = a_this; cur->next; cur = cur->next) ;
 66
 67        cur->next = a_sel;
 68        a_sel->prev = cur;
 69
 70        return a_this;
 71}
 72
 73/**
 74 *Prepends a simple selector to the current list of simple selectors.
 75 *@param a_this the this pointer of the current instance of #CRSimpleSel.
 76 *@param a_sel the simple selector to prepend.
 77 *@return the new list upon successfull completion, an error code otherwise.
 78 */
 79CRSimpleSel *
 80cr_simple_sel_prepend_simple_sel (CRSimpleSel * a_this, CRSimpleSel * a_sel)
 81{
 82        g_return_val_if_fail (a_sel, NULL);
 83
 84        if (a_this == NULL)
 85                return a_sel;
 86
 87        a_sel->next = a_this;
 88        a_this->prev = a_sel;
 89
 90        return a_sel;
 91}
 92
 93guchar *
 94cr_simple_sel_to_string (CRSimpleSel * a_this)
 95{
 96        GString *str_buf = NULL;
 97        guchar *result = NULL;
 98
 99        CRSimpleSel *cur = NULL;
100
101        g_return_val_if_fail (a_this, NULL);
102
103        str_buf = g_string_new (NULL);
104        for (cur = a_this; cur; cur = cur->next) {
105                if (cur->name) {
106                        guchar *str = g_strndup (cur->name->stryng->str,
107                                                 cur->name->stryng->len);
108
109                        if (str) {
110                                switch (cur->combinator) {
111                                case COMB_WS:
112                                        g_string_append (str_buf, " ");
113                                        break;
114
115                                case COMB_PLUS:
116                                        g_string_append (str_buf, "+");
117                                        break;
118
119                                case COMB_GT:
120                                        g_string_append (str_buf, ">");
121                                        break;
122
123                                default:
124                                        break;
125                                }
126
127                                g_string_append (str_buf, str);
128                                g_free (str);
129                                str = NULL;
130                        }
131                }
132
133                if (cur->add_sel) {
134                        guchar *tmp_str = NULL;
135
136                        tmp_str = cr_additional_sel_to_string (cur->add_sel);
137                        if (tmp_str) {
138                                g_string_append (str_buf, tmp_str);
139                                g_free (tmp_str);
140                                tmp_str = NULL;
141                        }
142                }
143        }
144
145        if (str_buf) {
146                result = str_buf->str;
147                g_string_free (str_buf, FALSE);
148                str_buf = NULL;
149        }
150
151        return result;
152}
153
154
155guchar *
156cr_simple_sel_one_to_string (CRSimpleSel * a_this)
157{
158        GString *str_buf = NULL;
159        guchar *result = NULL;
160
161        g_return_val_if_fail (a_this, NULL);
162
163        str_buf = g_string_new (NULL);
164        if (a_this->name) {
165                guchar *str = g_strndup (a_this->name->stryng->str,
166                                         a_this->name->stryng->len);
167
168                if (str) {
169                        g_string_append_printf (str_buf, "%s", str);
170                        g_free (str);
171                        str = NULL;
172                }
173        }
174
175        if (a_this->add_sel) {
176                guchar *tmp_str = NULL;
177
178                tmp_str = cr_additional_sel_to_string (a_this->add_sel);
179                if (tmp_str) {
180                        g_string_append_printf
181                                (str_buf, "%s", tmp_str);
182                        g_free (tmp_str);
183                        tmp_str = NULL;
184                }
185        }
186
187        if (str_buf) {
188                result = str_buf->str;
189                g_string_free (str_buf, FALSE);
190                str_buf = NULL;
191        }
192
193        return result;
194}
195
196/**
197 *Dumps the selector to a file.
198 *TODO: add the support of unicode in the dump.
199 *
200 *@param a_this the current instance of #CRSimpleSel.
201 *@param a_fp the destination file pointer.
202 *@return CR_OK upon successfull completion, an error code
203 *otherwise.
204 */
205enum CRStatus
206cr_simple_sel_dump (CRSimpleSel * a_this, FILE * a_fp)
207{
208        guchar *tmp_str = NULL;
209
210        g_return_val_if_fail (a_fp, CR_BAD_PARAM_ERROR);
211
212        if (a_this) {
213                tmp_str = cr_simple_sel_to_string (a_this);
214                if (tmp_str) {
215                        fprintf (a_fp, "%s", tmp_str);
216                        g_free (tmp_str);
217                        tmp_str = NULL;
218                }
219        }
220
221        return CR_OK;
222}
223
224/**
225 *Computes the selector (combinator separated list of simple selectors)
226 *as defined in the css2 spec in chapter 6.4.3
227 *@param a_this the current instance of #CRSimpleSel
228 *@return CR_OK upon successfull completion, an error code otherwise.
229 */
230enum CRStatus
231cr_simple_sel_compute_specificity (CRSimpleSel * a_this)
232{
233        CRAdditionalSel *cur_add_sel = NULL;
234        CRSimpleSel *cur_sel = NULL;
235        gulong a = 0,
236                b = 0,
237                c = 0;
238
239        g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
240
241        for (cur_sel = a_this; cur_sel; cur_sel = cur_sel->next) {
242                if (cur_sel->type_mask | TYPE_SELECTOR) {
243                        c++;    /*hmmh, is this a new language ? */
244                } else if (!cur_sel->name 
245                           || !cur_sel->name->stryng
246                           || !cur_sel->name->stryng->str) {
247                        if (cur_sel->add_sel->type ==
248                            PSEUDO_CLASS_ADD_SELECTOR) {
249                                /*
250                                 *this is a pseudo element, and
251                                 *the spec says, "ignore pseudo elements".
252                                 */
253                                continue;
254                        }
255                }
256
257                for (cur_add_sel = cur_sel->add_sel;
258                     cur_add_sel; cur_add_sel = cur_add_sel->next) {
259                        switch (cur_add_sel->type) {
260                        case ID_ADD_SELECTOR:
261                                a++;
262                                break;
263
264                        case NO_ADD_SELECTOR:
265                                continue;
266
267                        default:
268                                b++;
269                                break;
270                        }
271                }
272        }
273
274        /*we suppose a, b and c have 1 to 3 digits */
275        a_this->specificity = a * 1000000 + b * 1000 + c;
276
277        return CR_OK;
278}
279
280/**
281 *The destructor of the current instance of
282 *#CRSimpleSel.
283 *@param a_this the this pointer of the current instance of #CRSimpleSel.
284 *
285 */
286void
287cr_simple_sel_destroy (CRSimpleSel * a_this)
288{
289        g_return_if_fail (a_this);
290
291        if (a_this->name) {
292                cr_string_destroy (a_this->name);
293                a_this->name = NULL;
294        }
295
296        if (a_this->add_sel) {
297                cr_additional_sel_destroy (a_this->add_sel);
298                a_this->add_sel = NULL;
299        }
300
301        if (a_this->next) {
302                cr_simple_sel_destroy (a_this->next);
303        }
304
305        if (a_this) {
306                g_free (a_this);
307        }
308}