~valavanisalex/ubuntu/precise/inkscape/fix-943984

« back to all changes in this revision

Viewing changes to inkscape-0.47pre1/src/libcroco/cr-term.c

  • Committer: Bazaar Package Importer
  • Author(s): Bryce Harrington
  • Date: 2009-07-02 17:09:45 UTC
  • mfrom: (1.1.9 upstream)
  • Revision ID: james.westby@ubuntu.com-20090702170945-nn6d6zswovbwju1t
Tags: 0.47~pre1-0ubuntu1
* New upstream release.
  - Don't constrain maximization on small resolution devices (pre0)
    (LP: #348842)
  - Fixes segfault on startup (pre0)
    (LP: #391149)

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 <stdio.h>
 
25
#include <string.h>
 
26
#include "cr-term.h"
 
27
#include "cr-num.h"
 
28
#include "cr-parser.h"
 
29
 
 
30
/**
 
31
 *@file
 
32
 *Definition of the #CRTem class.
 
33
 */
 
34
 
 
35
static void
 
36
cr_term_clear (CRTerm * a_this)
 
37
{
 
38
        g_return_if_fail (a_this);
 
39
 
 
40
        switch (a_this->type) {
 
41
        case TERM_NUMBER:
 
42
                if (a_this->content.num) {
 
43
                        cr_num_destroy (a_this->content.num);
 
44
                        a_this->content.num = NULL;
 
45
                }
 
46
                break;
 
47
 
 
48
        case TERM_FUNCTION:
 
49
                if (a_this->ext_content.func_param) {
 
50
                        cr_term_destroy (a_this->ext_content.func_param);
 
51
                        a_this->ext_content.func_param = NULL;
 
52
                }
 
53
        case TERM_STRING:
 
54
        case TERM_IDENT:
 
55
        case TERM_URI:
 
56
        case TERM_HASH:
 
57
                if (a_this->content.str) {
 
58
                        cr_string_destroy (a_this->content.str);
 
59
                        a_this->content.str = NULL;
 
60
                }
 
61
                break;
 
62
 
 
63
        case TERM_RGB:
 
64
                if (a_this->content.rgb) {
 
65
                        cr_rgb_destroy (a_this->content.rgb);
 
66
                        a_this->content.rgb = NULL;
 
67
                }
 
68
                break;
 
69
 
 
70
        case TERM_UNICODERANGE:
 
71
        case TERM_NO_TYPE:
 
72
        default:
 
73
                break;
 
74
        }
 
75
 
 
76
        a_this->type = TERM_NO_TYPE;
 
77
}
 
78
 
 
79
/**
 
80
 *Instanciate a #CRTerm.
 
81
 *@return the newly build instance
 
82
 *of #CRTerm.
 
83
 */
 
84
CRTerm *
 
85
cr_term_new (void)
 
86
{
 
87
        CRTerm *result = (CRTerm *)g_try_malloc (sizeof (CRTerm));
 
88
        if (!result) {
 
89
                cr_utils_trace_info ("Out of memory");
 
90
                return NULL;
 
91
        }
 
92
        memset (result, 0, sizeof (CRTerm));
 
93
        return result;
 
94
}
 
95
 
 
96
/**
 
97
 *Parses an expresion as defined by the css2 spec
 
98
 *and builds the expression as a list of terms.
 
99
 *@param a_buf the buffer to parse.
 
100
 *@return a pointer to the first term of the expression or
 
101
 *NULL if parsing failed.
 
102
 */
 
103
CRTerm *
 
104
cr_term_parse_expression_from_buf (const guchar * a_buf,
 
105
                                   enum CREncoding a_encoding)
 
106
{
 
107
        CRTerm *result = NULL;
 
108
        enum CRStatus status = CR_OK;
 
109
 
 
110
        g_return_val_if_fail (a_buf, NULL);
 
111
 
 
112
        CRParser *parser = cr_parser_new_from_buf (
 
113
                                                 (guchar*)a_buf,
 
114
                                                                                  strlen ((char *)a_buf),
 
115
                                          a_encoding, FALSE);
 
116
        g_return_val_if_fail (parser, NULL);
 
117
 
 
118
        status = cr_parser_try_to_skip_spaces_and_comments (parser);
 
119
        if (status != CR_OK) {
 
120
                goto cleanup;
 
121
        }
 
122
        status = cr_parser_parse_expr (parser, &result);
 
123
        if (status != CR_OK) {
 
124
                if (result) {
 
125
                        cr_term_destroy (result);
 
126
                        result = NULL;
 
127
                }
 
128
        }
 
129
 
 
130
      cleanup:
 
131
        if (parser) {
 
132
                cr_parser_destroy (parser);
 
133
                parser = NULL;
 
134
        }
 
135
 
 
136
        return result;
 
137
}
 
138
 
 
139
enum CRStatus
 
140
cr_term_set_number (CRTerm * a_this, CRNum * a_num)
 
141
{
 
142
        g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
 
143
 
 
144
        cr_term_clear (a_this);
 
145
 
 
146
        a_this->type = TERM_NUMBER;
 
147
        a_this->content.num = a_num;
 
148
        return CR_OK;
 
149
}
 
150
 
 
151
enum CRStatus
 
152
cr_term_set_function (CRTerm * a_this, CRString * a_func_name,
 
153
                      CRTerm * a_func_param)
 
154
{
 
155
        g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
 
156
 
 
157
        cr_term_clear (a_this);
 
158
 
 
159
        a_this->type = TERM_FUNCTION;
 
160
        a_this->content.str = a_func_name;
 
161
        a_this->ext_content.func_param = a_func_param;
 
162
        return CR_OK;
 
163
}
 
164
 
 
165
enum CRStatus
 
166
cr_term_set_string (CRTerm * a_this, CRString * a_str)
 
167
{
 
168
        g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
 
169
 
 
170
        cr_term_clear (a_this);
 
171
 
 
172
        a_this->type = TERM_STRING;
 
173
        a_this->content.str = a_str;
 
174
        return CR_OK;
 
175
}
 
176
 
 
177
enum CRStatus
 
178
cr_term_set_ident (CRTerm * a_this, CRString * a_str)
 
179
{
 
180
        g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
 
181
 
 
182
        cr_term_clear (a_this);
 
183
 
 
184
        a_this->type = TERM_IDENT;
 
185
        a_this->content.str = a_str;
 
186
        return CR_OK;
 
187
}
 
188
 
 
189
enum CRStatus
 
190
cr_term_set_uri (CRTerm * a_this, CRString * a_str)
 
191
{
 
192
        g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
 
193
 
 
194
        cr_term_clear (a_this);
 
195
 
 
196
        a_this->type = TERM_URI;
 
197
        a_this->content.str = a_str;
 
198
        return CR_OK;
 
199
}
 
200
 
 
201
enum CRStatus
 
202
cr_term_set_rgb (CRTerm * a_this, CRRgb * a_rgb)
 
203
{
 
204
        g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
 
205
 
 
206
        cr_term_clear (a_this);
 
207
 
 
208
        a_this->type = TERM_RGB;
 
209
        a_this->content.rgb = a_rgb;
 
210
        return CR_OK;
 
211
}
 
212
 
 
213
enum CRStatus
 
214
cr_term_set_hash (CRTerm * a_this, CRString * a_str)
 
215
{
 
216
        g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
 
217
 
 
218
        cr_term_clear (a_this);
 
219
 
 
220
        a_this->type = TERM_HASH;
 
221
        a_this->content.str = a_str;
 
222
        return CR_OK;
 
223
}
 
224
 
 
225
/**
 
226
 *Appends a new term to the current list of #CRTerm.
 
227
 *
 
228
 *@param a_this the "this pointer" of the current instance
 
229
 *of #CRTerm .
 
230
 *@param a_new_term the term to append.
 
231
 *@return the list of terms with the a_new_term appended to it.
 
232
 */
 
233
CRTerm *
 
234
cr_term_append_term (CRTerm * a_this, CRTerm * a_new_term)
 
235
{
 
236
        CRTerm *cur = NULL;
 
237
 
 
238
        g_return_val_if_fail (a_new_term, NULL);
 
239
 
 
240
        if (a_this == NULL)
 
241
                return a_new_term;
 
242
 
 
243
        for (cur = a_this; cur->next; cur = cur->next) ;
 
244
 
 
245
        cur->next = a_new_term;
 
246
        a_new_term->prev = cur;
 
247
 
 
248
        return a_this;
 
249
}
 
250
 
 
251
/**
 
252
 *Prepends a term to the list of terms represented by a_this.
 
253
 *
 
254
 *@param a_this the "this pointer" of the current instance of
 
255
 *#CRTerm .
 
256
 *@param a_new_term the term to prepend.
 
257
 *@return the head of the new list.
 
258
 */
 
259
CRTerm *
 
260
cr_term_prepend_term (CRTerm * a_this, CRTerm * a_new_term)
 
261
{
 
262
        g_return_val_if_fail (a_this && a_new_term, NULL);
 
263
 
 
264
        a_new_term->next = a_this;
 
265
        a_this->prev = a_new_term;
 
266
 
 
267
        return a_new_term;
 
268
}
 
269
 
 
270
/**
 
271
 *Serializes the expression represented by
 
272
 *the chained instances of #CRterm.
 
273
 *@param a_this the current instance of #CRTerm
 
274
 *@return the zero terminated string containing the serialized
 
275
 *form of #CRTerm. MUST BE FREED BY THE CALLER using g_free().
 
276
 */
 
277
guchar *
 
278
cr_term_to_string (CRTerm * a_this)
 
279
{
 
280
        GString *str_buf = NULL;
 
281
        CRTerm *cur = NULL;
 
282
        guchar *result = NULL;
 
283
        gchar *content = NULL;
 
284
 
 
285
        g_return_val_if_fail (a_this, NULL);
 
286
 
 
287
        str_buf = g_string_new (NULL);
 
288
        g_return_val_if_fail (str_buf, NULL);
 
289
 
 
290
        for (cur = a_this; cur; cur = cur->next) {
 
291
                if ((cur->content.str == NULL)
 
292
                    && (cur->content.num == NULL)
 
293
                    && (cur->content.str == NULL)
 
294
                    && (cur->content.rgb == NULL))
 
295
                        continue;
 
296
 
 
297
                switch (cur->the_operator) {
 
298
                case DIVIDE:
 
299
                        g_string_append (str_buf, " / ");
 
300
                        break;
 
301
 
 
302
                case COMMA:
 
303
                        g_string_append (str_buf, ", ");
 
304
                        break;
 
305
 
 
306
                case NO_OP:
 
307
                        if (cur->prev) {
 
308
                                g_string_append (str_buf, " ");
 
309
                        }
 
310
                        break;
 
311
                default:
 
312
 
 
313
                        break;
 
314
                }
 
315
 
 
316
                switch (cur->unary_op) {
 
317
                case PLUS_UOP:
 
318
                        g_string_append (str_buf, "+");
 
319
                        break;
 
320
 
 
321
                case MINUS_UOP:
 
322
                        g_string_append (str_buf, "-");
 
323
                        break;
 
324
 
 
325
                default:
 
326
                        break;
 
327
                }
 
328
 
 
329
                switch (cur->type) {
 
330
                case TERM_NUMBER:
 
331
                        if (cur->content.num) {
 
332
                                content = (gchar *)cr_num_to_string (cur->content.num);
 
333
                        }
 
334
 
 
335
                        if (content) {
 
336
                                g_string_append (str_buf, content);
 
337
                                g_free (content);
 
338
                                content = NULL;
 
339
                        }
 
340
 
 
341
                        break;
 
342
 
 
343
                case TERM_FUNCTION:
 
344
                        if (cur->content.str) {
 
345
                                content = g_strndup
 
346
                                        (cur->content.str->stryng->str,
 
347
                                         cur->content.str->stryng->len);
 
348
                        }
 
349
 
 
350
                        if (content) {
 
351
                                g_string_append_printf (str_buf, "%s(",
 
352
                                                        content);
 
353
 
 
354
                                if (cur->ext_content.func_param) {
 
355
                                        guchar *tmp_str = NULL;
 
356
 
 
357
                                        tmp_str = cr_term_to_string
 
358
                                                (cur->
 
359
                                                 ext_content.func_param);
 
360
 
 
361
                                        if (tmp_str) {
 
362
                                                g_string_append (str_buf, 
 
363
                                                                                    (gchar *)tmp_str);
 
364
                                                g_free (tmp_str);
 
365
                                                tmp_str = NULL;
 
366
                                        }
 
367
 
 
368
                                        g_free (content);
 
369
                                        content = NULL;
 
370
                                }
 
371
                                g_string_append (str_buf, ")");
 
372
                        }
 
373
 
 
374
                        break;
 
375
 
 
376
                case TERM_STRING:
 
377
                        if (cur->content.str) {
 
378
                                content = g_strndup
 
379
                                        (cur->content.str->stryng->str,
 
380
                                         cur->content.str->stryng->len);
 
381
                        }
 
382
 
 
383
                        if (content) {
 
384
                                g_string_append_printf (str_buf,
 
385
                                                        "\"%s\"", content);
 
386
                                g_free (content);
 
387
                                content = NULL;
 
388
                        }
 
389
                        break;
 
390
 
 
391
                case TERM_IDENT:
 
392
                        if (cur->content.str) {
 
393
                                content = g_strndup
 
394
                                        (cur->content.str->stryng->str,
 
395
                                         cur->content.str->stryng->len);
 
396
                        }
 
397
 
 
398
                        if (content) {
 
399
                                g_string_append (str_buf, content);
 
400
                                g_free (content);
 
401
                                content = NULL;
 
402
                        }
 
403
                        break;
 
404
 
 
405
                case TERM_URI:
 
406
                        if (cur->content.str) {
 
407
                                content = g_strndup
 
408
                                          (cur->content.str->stryng->str,
 
409
                                           cur->content.str->stryng->len);
 
410
                        }
 
411
 
 
412
                        if (content) {
 
413
                                g_string_append_printf
 
414
                                        (str_buf, "url(%s)", content);
 
415
                                g_free (content);
 
416
                                content = NULL;
 
417
                        }
 
418
                        break;
 
419
 
 
420
                case TERM_RGB:
 
421
                        if (cur->content.rgb) {
 
422
                                guchar *tmp_str = NULL;
 
423
 
 
424
                                g_string_append (str_buf, "rgb(");
 
425
                                tmp_str = cr_rgb_to_string (cur->content.rgb);
 
426
 
 
427
                                if (tmp_str) {
 
428
                                        g_string_append (str_buf, (gchar *)tmp_str);
 
429
                                        g_free (tmp_str);
 
430
                                        tmp_str = NULL;
 
431
                                }
 
432
                                g_string_append (str_buf, ")");
 
433
                        }
 
434
 
 
435
                        break;
 
436
 
 
437
                case TERM_UNICODERANGE:
 
438
                        g_string_append
 
439
                                (str_buf,
 
440
                                 "?found unicoderange: dump not supported yet?");
 
441
                        break;
 
442
 
 
443
                case TERM_HASH:
 
444
                        if (cur->content.str) {
 
445
                                content = g_strndup
 
446
                                        (cur->content.str->stryng->str,
 
447
                                         cur->content.str->stryng->len);
 
448
                        }
 
449
 
 
450
                        if (content) {
 
451
                                g_string_append_printf (str_buf,
 
452
                                                        "#%s", content);
 
453
                                g_free (content);
 
454
                                content = NULL;
 
455
                        }
 
456
                        break;
 
457
 
 
458
                default:
 
459
                        g_string_append (str_buf,
 
460
                                         "Unrecognized Term type");
 
461
                        break;
 
462
                }
 
463
        }
 
464
 
 
465
        if (str_buf) {
 
466
                result = (guchar *)str_buf->str;
 
467
                g_string_free (str_buf, FALSE);
 
468
                str_buf = NULL;
 
469
        }
 
470
 
 
471
        return result;
 
472
}
 
473
 
 
474
guchar *
 
475
cr_term_one_to_string (CRTerm * a_this)
 
476
{
 
477
        GString *str_buf = NULL;
 
478
        guchar *result = NULL;
 
479
        gchar *content = NULL;
 
480
 
 
481
        g_return_val_if_fail (a_this, NULL);
 
482
 
 
483
        str_buf = g_string_new (NULL);
 
484
        g_return_val_if_fail (str_buf, NULL);
 
485
 
 
486
        if ((a_this->content.str == NULL)
 
487
            && (a_this->content.num == NULL)
 
488
            && (a_this->content.str == NULL)
 
489
            && (a_this->content.rgb == NULL))
 
490
                return NULL ;
 
491
 
 
492
        switch (a_this->the_operator) {
 
493
        case DIVIDE:
 
494
                g_string_append_printf (str_buf, " / ");
 
495
                break;
 
496
 
 
497
        case COMMA:
 
498
                g_string_append_printf (str_buf, ", ");
 
499
                break;
 
500
 
 
501
        case NO_OP:
 
502
                if (a_this->prev) {
 
503
                        g_string_append_printf (str_buf, " ");
 
504
                }
 
505
                break;
 
506
        default:
 
507
 
 
508
                break;
 
509
        }
 
510
 
 
511
        switch (a_this->unary_op) {
 
512
        case PLUS_UOP:
 
513
                g_string_append_printf (str_buf, "+");
 
514
                break;
 
515
 
 
516
        case MINUS_UOP:
 
517
                g_string_append_printf (str_buf, "-");
 
518
                break;
 
519
 
 
520
        default:
 
521
                break;
 
522
        }
 
523
 
 
524
        switch (a_this->type) {
 
525
        case TERM_NUMBER:
 
526
                if (a_this->content.num) {
 
527
                        content = (gchar *)cr_num_to_string (a_this->content.num);
 
528
                }
 
529
 
 
530
                if (content) {
 
531
                        g_string_append (str_buf, content);
 
532
                        g_free (content);
 
533
                        content = NULL;
 
534
                }
 
535
 
 
536
                break;
 
537
 
 
538
        case TERM_FUNCTION:
 
539
                if (a_this->content.str) {
 
540
                        content = g_strndup
 
541
                                (a_this->content.str->stryng->str,
 
542
                                 a_this->content.str->stryng->len);
 
543
                }
 
544
 
 
545
                if (content) {
 
546
                        g_string_append_printf (str_buf, "%s(",
 
547
                                                content);
 
548
 
 
549
                        if (a_this->ext_content.func_param) {
 
550
                                guchar *tmp_str = NULL;
 
551
 
 
552
                                tmp_str = cr_term_to_string
 
553
                                        (a_this->
 
554
                                         ext_content.func_param);
 
555
 
 
556
                                if (tmp_str) {
 
557
                                        g_string_append_printf
 
558
                                                (str_buf,
 
559
                                                 "%s", tmp_str);
 
560
                                        g_free (tmp_str);
 
561
                                        tmp_str = NULL;
 
562
                                }
 
563
 
 
564
                                g_string_append_printf (str_buf, ")");
 
565
                                g_free (content);
 
566
                                content = NULL;
 
567
                        }
 
568
                }
 
569
 
 
570
                break;
 
571
 
 
572
        case TERM_STRING:
 
573
                if (a_this->content.str) {
 
574
                        content = g_strndup
 
575
                                (a_this->content.str->stryng->str,
 
576
                                 a_this->content.str->stryng->len);
 
577
                }
 
578
 
 
579
                if (content) {
 
580
                        g_string_append_printf (str_buf,
 
581
                                                "\"%s\"", content);
 
582
                        g_free (content);
 
583
                        content = NULL;
 
584
                }
 
585
                break;
 
586
 
 
587
        case TERM_IDENT:
 
588
                if (a_this->content.str) {
 
589
                        content = g_strndup
 
590
                                (a_this->content.str->stryng->str,
 
591
                                 a_this->content.str->stryng->len);
 
592
                }
 
593
 
 
594
                if (content) {
 
595
                        g_string_append (str_buf, content);
 
596
                        g_free (content);
 
597
                        content = NULL;
 
598
                }
 
599
                break;
 
600
 
 
601
        case TERM_URI:
 
602
                if (a_this->content.str) {
 
603
                        content = g_strndup
 
604
                                (a_this->content.str->stryng->str,
 
605
                                 a_this->content.str->stryng->len);
 
606
                }
 
607
 
 
608
                if (content) {
 
609
                        g_string_append_printf
 
610
                                (str_buf, "url(%s)", content);
 
611
                        g_free (content);
 
612
                        content = NULL;
 
613
                }
 
614
                break;
 
615
 
 
616
        case TERM_RGB:
 
617
                if (a_this->content.rgb) {
 
618
 
 
619
                        g_string_append_printf (str_buf, "rgb(");
 
620
                        gchar *tmp_str = (gchar *)cr_rgb_to_string (a_this->content.rgb);
 
621
 
 
622
                        if (tmp_str) {
 
623
                                g_string_append (str_buf, tmp_str);
 
624
                                g_free (tmp_str);
 
625
                                tmp_str = NULL;
 
626
                        }
 
627
                        g_string_append_printf (str_buf, ")");
 
628
                }
 
629
 
 
630
                break;
 
631
 
 
632
        case TERM_UNICODERANGE:
 
633
                g_string_append_printf
 
634
                        (str_buf,
 
635
                         "?found unicoderange: dump not supported yet?");
 
636
                break;
 
637
 
 
638
        case TERM_HASH:
 
639
                if (a_this->content.str) {
 
640
                        content = g_strndup
 
641
                                (a_this->content.str->stryng->str,
 
642
                                 a_this->content.str->stryng->len);
 
643
                }
 
644
 
 
645
                if (content) {
 
646
                        g_string_append_printf (str_buf,
 
647
                                                "#%s", content);
 
648
                        g_free (content);
 
649
                        content = NULL;
 
650
                }
 
651
                break;
 
652
 
 
653
        default:
 
654
                g_string_append_printf (str_buf,
 
655
                                        "%s",
 
656
                                        "Unrecognized Term type");
 
657
                break;
 
658
        }
 
659
 
 
660
        if (str_buf) {
 
661
                result = (guchar *)str_buf->str;
 
662
                g_string_free (str_buf, FALSE);
 
663
                str_buf = NULL;
 
664
        }
 
665
 
 
666
        return result;
 
667
}
 
668
 
 
669
/**
 
670
 *Dumps the expression (a list of terms connected by operators)
 
671
 *to a file.
 
672
 *TODO: finish the dump. The dump of some type of terms have not yet been
 
673
 *implemented.
 
674
 *@param a_this the current instance of #CRTerm.
 
675
 *@param a_fp the destination file pointer.
 
676
 */
 
677
void
 
678
cr_term_dump (CRTerm * a_this, FILE * a_fp)
 
679
{
 
680
        guchar *content = NULL;
 
681
 
 
682
        g_return_if_fail (a_this);
 
683
 
 
684
        content = cr_term_to_string (a_this);
 
685
 
 
686
        if (content) {
 
687
                fprintf (a_fp, "%s", content);
 
688
                g_free (content);
 
689
        }
 
690
}
 
691
 
 
692
/**
 
693
 *Return the number of terms in the expression.
 
694
 *@param a_this the current instance of #CRTerm.
 
695
 *@return number of terms in the expression.
 
696
 */
 
697
int
 
698
cr_term_nr_values (CRTerm *a_this)
 
699
{
 
700
        CRTerm *cur = NULL ;
 
701
        int nr = 0;
 
702
 
 
703
        g_return_val_if_fail (a_this, -1) ;
 
704
 
 
705
        for (cur = a_this ; cur ; cur = cur->next)
 
706
                nr ++;
 
707
        return nr;
 
708
}
 
709
 
 
710
/**
 
711
 *Use an index to get a CRTerm from the expression.
 
712
 *@param a_this the current instance of #CRTerm.
 
713
 *@param itemnr the index into the expression.
 
714
 *@return CRTerm at position itemnr, if itemnr > number of terms - 1,
 
715
 *it will return NULL.
 
716
 */
 
717
CRTerm *
 
718
cr_term_get_from_list (CRTerm *a_this, int itemnr)
 
719
{
 
720
        CRTerm *cur = NULL ;
 
721
        int nr = 0;
 
722
 
 
723
        g_return_val_if_fail (a_this, NULL) ;
 
724
 
 
725
        for (cur = a_this ; cur ; cur = cur->next)
 
726
                if (nr++ == itemnr)
 
727
                        return cur;
 
728
        return NULL;
 
729
}
 
730
 
 
731
/**
 
732
 *Increments the reference counter of the current instance
 
733
 *of #CRTerm.*
 
734
 *@param a_this the current instance of #CRTerm.
 
735
 */
 
736
void
 
737
cr_term_ref (CRTerm * a_this)
 
738
{
 
739
        g_return_if_fail (a_this);
 
740
 
 
741
        a_this->ref_count++;
 
742
}
 
743
 
 
744
/**
 
745
 *Decrements the ref count of the current instance of
 
746
 *#CRTerm. If the ref count reaches zero, the instance is
 
747
 *destroyed.
 
748
 *@param a_this the current instance of #CRTerm.
 
749
 *@return TRUE if the current instance has been destroyed, FALSE otherwise.
 
750
 */
 
751
gboolean
 
752
cr_term_unref (CRTerm * a_this)
 
753
{
 
754
        g_return_val_if_fail (a_this, FALSE);
 
755
 
 
756
        if (a_this->ref_count) {
 
757
                a_this->ref_count--;
 
758
        }
 
759
 
 
760
        if (a_this->ref_count == 0) {
 
761
                cr_term_destroy (a_this);
 
762
                return TRUE;
 
763
        }
 
764
 
 
765
        return FALSE;
 
766
}
 
767
 
 
768
/**
 
769
 *The destructor of the the #CRTerm class.
 
770
 *@param a_this the "this pointer" of the current instance
 
771
 *of #CRTerm.
 
772
 */
 
773
void
 
774
cr_term_destroy (CRTerm * a_this)
 
775
{
 
776
        g_return_if_fail (a_this);
 
777
 
 
778
        cr_term_clear (a_this);
 
779
 
 
780
        if (a_this->next) {
 
781
                cr_term_destroy (a_this->next);
 
782
                a_this->next = NULL;
 
783
        }
 
784
 
 
785
        if (a_this) {
 
786
                g_free (a_this);
 
787
        }
 
788
 
 
789
}