• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-WNDR4500-V1.0.1.40_1.0.68/ap/gpl/timemachine/gettext-0.17/gettext-tools/gnulib-lib/libcroco/
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 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 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 <config.h>
25#include <string.h>
26#include <glib.h>
27#include "cr-simple-sel.h"
28
29/**
30 * cr_simple_sel_new:
31 *
32 *The constructor of #CRSimpleSel.
33 *
34 *Returns the new instance of #CRSimpleSel.
35 */
36CRSimpleSel *
37cr_simple_sel_new (void)
38{
39        CRSimpleSel *result = NULL;
40
41        result = g_try_malloc (sizeof (CRSimpleSel));
42        if (!result) {
43                cr_utils_trace_info ("Out of memory");
44                return NULL;
45        }
46        memset (result, 0, sizeof (CRSimpleSel));
47
48        return result;
49}
50
51/**
52 * cr_simple_sel_append_simple_sel:
53 *
54 *Appends a simpe selector to the current list of simple selector.
55 *
56 *@a_this: the this pointer of the current instance of #CRSimpleSel.
57 *@a_sel: the simple selector to append.
58 *Returns: the new list upon successfull completion, an error code otherwise.
59 */
60CRSimpleSel *
61cr_simple_sel_append_simple_sel (CRSimpleSel * a_this, CRSimpleSel * a_sel)
62{
63        CRSimpleSel *cur = NULL;
64
65        g_return_val_if_fail (a_sel, NULL);
66
67        if (a_this == NULL)
68                return a_sel;
69
70        for (cur = a_this; cur->next; cur = cur->next) ;
71
72        cur->next = a_sel;
73        a_sel->prev = cur;
74
75        return a_this;
76}
77
78/**
79 * cr_simple_sel_prepend_simple_sel:
80 *
81 *@a_this: the this pointer of the current instance of #CRSimpleSel.
82 *@a_sel: the simple selector to prepend.
83 *
84 *Prepends a simple selector to the current list of simple selectors.
85 *
86 *Returns the new list upon successfull completion, an error code otherwise.
87 */
88CRSimpleSel *
89cr_simple_sel_prepend_simple_sel (CRSimpleSel * a_this, CRSimpleSel * a_sel)
90{
91        g_return_val_if_fail (a_sel, NULL);
92
93        if (a_this == NULL)
94                return a_sel;
95
96        a_sel->next = a_this;
97        a_this->prev = a_sel;
98
99        return a_sel;
100}
101
102guchar *
103cr_simple_sel_to_string (CRSimpleSel * a_this)
104{
105        GString *str_buf = NULL;
106        guchar *result = NULL;
107
108        CRSimpleSel *cur = NULL;
109
110        g_return_val_if_fail (a_this, NULL);
111
112        str_buf = g_string_new (NULL);
113        for (cur = a_this; cur; cur = cur->next) {
114                if (cur->name) {
115                        guchar *str = g_strndup (cur->name->stryng->str,
116                                                 cur->name->stryng->len);
117
118                        if (str) {
119                                switch (cur->combinator) {
120                                case COMB_WS:
121                                        g_string_append (str_buf, " ");
122                                        break;
123
124                                case COMB_PLUS:
125                                        g_string_append (str_buf, "+");
126                                        break;
127
128                                case COMB_GT:
129                                        g_string_append (str_buf, ">");
130                                        break;
131
132                                default:
133                                        break;
134                                }
135
136                                g_string_append (str_buf, str);
137                                g_free (str);
138                                str = NULL;
139                        }
140                }
141
142                if (cur->add_sel) {
143                        guchar *tmp_str = NULL;
144
145                        tmp_str = cr_additional_sel_to_string (cur->add_sel);
146                        if (tmp_str) {
147                                g_string_append (str_buf, tmp_str);
148                                g_free (tmp_str);
149                                tmp_str = NULL;
150                        }
151                }
152        }
153
154        if (str_buf) {
155                result = str_buf->str;
156                g_string_free (str_buf, FALSE);
157                str_buf = NULL;
158        }
159
160        return result;
161}
162
163
164guchar *
165cr_simple_sel_one_to_string (CRSimpleSel * a_this)
166{
167        GString *str_buf = NULL;
168        guchar *result = NULL;
169
170        g_return_val_if_fail (a_this, NULL);
171
172        str_buf = g_string_new (NULL);
173        if (a_this->name) {
174                guchar *str = g_strndup (a_this->name->stryng->str,
175                                         a_this->name->stryng->len);
176
177                if (str) {
178                        g_string_append_printf (str_buf, "%s", str);
179                        g_free (str);
180                        str = NULL;
181                }
182        }
183
184        if (a_this->add_sel) {
185                guchar *tmp_str = NULL;
186
187                tmp_str = cr_additional_sel_to_string (a_this->add_sel);
188                if (tmp_str) {
189                        g_string_append_printf
190                                (str_buf, "%s", tmp_str);
191                        g_free (tmp_str);
192                        tmp_str = NULL;
193                }
194        }
195
196        if (str_buf) {
197                result = str_buf->str;
198                g_string_free (str_buf, FALSE);
199                str_buf = NULL;
200        }
201
202        return result;
203}
204
205/**
206 * cr_simple_sel_dump:
207 *@a_this: the current instance of #CRSimpleSel.
208 *@a_fp: the destination file pointer.
209 *
210 *Dumps the selector to a file.
211 *TODO: add the support of unicode in the dump.
212 *
213 *Returns CR_OK upon successfull completion, an error code
214 *otherwise.
215 */
216enum CRStatus
217cr_simple_sel_dump (CRSimpleSel * a_this, FILE * a_fp)
218{
219        guchar *tmp_str = NULL;
220
221        g_return_val_if_fail (a_fp, CR_BAD_PARAM_ERROR);
222
223        if (a_this) {
224                tmp_str = cr_simple_sel_to_string (a_this);
225                if (tmp_str) {
226                        fprintf (a_fp, "%s", tmp_str);
227                        g_free (tmp_str);
228                        tmp_str = NULL;
229                }
230        }
231
232        return CR_OK;
233}
234
235/**
236 * cr_simple_sel_compute_specificity:
237 *
238 *@a_this: the current instance of #CRSimpleSel
239 *
240 *Computes the selector (combinator separated list of simple selectors)
241 *as defined in the css2 spec in chapter 6.4.3
242 *
243 *Returns CR_OK upon successfull completion, an error code otherwise.
244 */
245enum CRStatus
246cr_simple_sel_compute_specificity (CRSimpleSel * a_this)
247{
248        CRAdditionalSel *cur_add_sel = NULL;
249        CRSimpleSel *cur_sel = NULL;
250        gulong a = 0,
251                b = 0,
252                c = 0;
253
254        g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
255
256        for (cur_sel = a_this; cur_sel; cur_sel = cur_sel->next) {
257                if (cur_sel->type_mask | TYPE_SELECTOR) {
258                        c++;    /*hmmh, is this a new language ? */
259                } else if (!cur_sel->name
260                           || !cur_sel->name->stryng
261                           || !cur_sel->name->stryng->str) {
262                        if (cur_sel->add_sel->type ==
263                            PSEUDO_CLASS_ADD_SELECTOR) {
264                                /*
265                                 *this is a pseudo element, and
266                                 *the spec says, "ignore pseudo elements".
267                                 */
268                                continue;
269                        }
270                }
271
272                for (cur_add_sel = cur_sel->add_sel;
273                     cur_add_sel; cur_add_sel = cur_add_sel->next) {
274                        switch (cur_add_sel->type) {
275                        case ID_ADD_SELECTOR:
276                                a++;
277                                break;
278
279                        case NO_ADD_SELECTOR:
280                                continue;
281
282                        default:
283                                b++;
284                                break;
285                        }
286                }
287        }
288
289        /*we suppose a, b and c have 1 to 3 digits */
290        a_this->specificity = a * 1000000 + b * 1000 + c;
291
292        return CR_OK;
293}
294
295/**
296 * cr_simple_sel_destroy:
297 *
298 *@a_this: the this pointer of the current instance of #CRSimpleSel.
299 *
300 *The destructor of the current instance of
301 *#CRSimpleSel.
302 */
303void
304cr_simple_sel_destroy (CRSimpleSel * a_this)
305{
306        g_return_if_fail (a_this);
307
308        if (a_this->name) {
309                cr_string_destroy (a_this->name);
310                a_this->name = NULL;
311        }
312
313        if (a_this->add_sel) {
314                cr_additional_sel_destroy (a_this->add_sel);
315                a_this->add_sel = NULL;
316        }
317
318        if (a_this->next) {
319                cr_simple_sel_destroy (a_this->next);
320        }
321
322        if (a_this) {
323                g_free (a_this);
324        }
325}
326