~vaifrax/inkscape/bugfix170049

« back to all changes in this revision

Viewing changes to src/libcroco/cr-simple-sel.c

  • Committer: mental
  • Date: 2006-01-16 02:36:01 UTC
  • Revision ID: mental@users.sourceforge.net-20060116023601-wkr0h7edl5veyudq
moving trunk for module inkscape

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 */
 
33
CRSimpleSel *
 
34
cr_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
 */
 
55
CRSimpleSel *
 
56
cr_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
 */
 
79
CRSimpleSel *
 
80
cr_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
 
 
93
guchar *
 
94
cr_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
 
 
155
guchar *
 
156
cr_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
 */
 
205
enum CRStatus
 
206
cr_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
 */
 
230
enum CRStatus
 
231
cr_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
 */
 
286
void
 
287
cr_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
}