• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-WNDR4500v2-V1.0.0.60_1.0.38/ap/gpl/timemachine/gettext-0.17/gnulib-local/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 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 <config.h>
25#include <string.h>
26#include "cr-utils.h"
27#include "cr-om-parser.h"
28
29/**
30 *@CROMParser:
31 *
32 *The definition of the CSS Object Model Parser.
33 *This parser uses (and sits) the SAC api of libcroco defined
34 *in cr-parser.h and cr-doc-handler.h
35 */
36
37struct _CROMParserPriv {
38        CRParser *parser;
39};
40
41#define PRIVATE(a_this) ((a_this)->priv)
42
43/*
44 *Forward declaration of a type defined later
45 *in this file.
46 */
47struct _ParsingContext;
48typedef struct _ParsingContext ParsingContext;
49
50static ParsingContext *new_parsing_context (void);
51
52static void destroy_context (ParsingContext * a_ctxt);
53
54static void unrecoverable_error (CRDocHandler * a_this);
55
56static void error (CRDocHandler * a_this);
57
58static void property (CRDocHandler * a_this,
59                      CRString * a_name,
60                      CRTerm * a_expression,
61                      gboolean a_important);
62
63static void end_selector (CRDocHandler * a_this,
64                          CRSelector * a_selector_list);
65
66static void start_selector (CRDocHandler * a_this,
67                            CRSelector * a_selector_list);
68
69static void start_font_face (CRDocHandler * a_this,
70                             CRParsingLocation *a_location);
71
72static void end_font_face (CRDocHandler * a_this);
73
74static void end_document (CRDocHandler * a_this);
75
76static void start_document (CRDocHandler * a_this);
77
78static void charset (CRDocHandler * a_this,
79                     CRString * a_charset,
80                     CRParsingLocation *a_location);
81
82static void start_page (CRDocHandler * a_this, CRString * a_page,
83                        CRString * a_pseudo_page,
84                        CRParsingLocation *a_location);
85
86static void end_page (CRDocHandler * a_this, CRString * a_page,
87                      CRString * a_pseudo_page);
88
89static void start_media (CRDocHandler * a_this,
90                         GList * a_media_list,
91                         CRParsingLocation *a_location);
92
93static void end_media (CRDocHandler * a_this,
94                       GList * a_media_list);
95
96static void import_style (CRDocHandler * a_this,
97                          GList * a_media_list,
98                          CRString * a_uri,
99                          CRString * a_uri_default_ns,
100                          CRParsingLocation *a_location);
101
102struct _ParsingContext {
103        CRStyleSheet *stylesheet;
104        CRStatement *cur_stmt;
105        CRStatement *cur_media_stmt;
106};
107
108/********************************************
109 *Private methods
110 ********************************************/
111
112static ParsingContext *
113new_parsing_context (void)
114{
115        ParsingContext *result = NULL;
116
117        result = g_try_malloc (sizeof (ParsingContext));
118        if (!result) {
119                cr_utils_trace_info ("Out of Memory");
120                return NULL;
121        }
122        memset (result, 0, sizeof (ParsingContext));
123        return result;
124}
125
126static void
127destroy_context (ParsingContext * a_ctxt)
128{
129        g_return_if_fail (a_ctxt);
130
131        if (a_ctxt->stylesheet) {
132                cr_stylesheet_destroy (a_ctxt->stylesheet);
133                a_ctxt->stylesheet = NULL;
134        }
135        if (a_ctxt->cur_stmt) {
136                cr_statement_destroy (a_ctxt->cur_stmt);
137                a_ctxt->cur_stmt = NULL;
138        }
139        g_free (a_ctxt);
140}
141
142static enum CRStatus
143cr_om_parser_init_default_sac_handler (CROMParser * a_this)
144{
145        CRDocHandler *sac_handler = NULL;
146        gboolean free_hdlr_if_error = FALSE;
147        enum CRStatus status = CR_OK;
148
149        g_return_val_if_fail (a_this && PRIVATE (a_this)
150                              && PRIVATE (a_this)->parser,
151                              CR_BAD_PARAM_ERROR);
152
153        status = cr_parser_get_sac_handler (PRIVATE (a_this)->parser,
154                                            &sac_handler);
155        g_return_val_if_fail (status == CR_OK, status);
156
157        if (!sac_handler) {
158                sac_handler = cr_doc_handler_new ();
159                free_hdlr_if_error = TRUE;
160        }
161
162        /*
163         *initialyze here the sac handler.
164         */
165        sac_handler->start_document = start_document;
166        sac_handler->end_document = end_document;
167        sac_handler->start_selector = start_selector;
168        sac_handler->end_selector = end_selector;
169        sac_handler->property = property;
170        sac_handler->start_font_face = start_font_face;
171        sac_handler->end_font_face = end_font_face;
172        sac_handler->error = error;
173        sac_handler->unrecoverable_error = unrecoverable_error;
174        sac_handler->charset = charset;
175        sac_handler->start_page = start_page;
176        sac_handler->end_page = end_page;
177        sac_handler->start_media = start_media;
178        sac_handler->end_media = end_media;
179        sac_handler->import_style = import_style;
180
181        status = cr_parser_set_sac_handler (PRIVATE (a_this)->parser,
182                                            sac_handler);
183        if (status == CR_OK) {
184                return CR_OK;
185        }
186
187        if (sac_handler && free_hdlr_if_error == TRUE) {
188                cr_doc_handler_destroy (sac_handler);
189                sac_handler = NULL;
190        }
191
192        return status;
193
194}
195
196static void
197start_document (CRDocHandler * a_this)
198{
199        ParsingContext *ctxt = NULL;
200        CRStyleSheet *stylesheet = NULL;
201
202        g_return_if_fail (a_this);
203
204        ctxt = new_parsing_context ();
205        g_return_if_fail (ctxt);
206
207        stylesheet = cr_stylesheet_new (NULL);
208        ctxt->stylesheet = stylesheet;
209        cr_doc_handler_set_ctxt (a_this, ctxt);
210}
211
212static void
213start_font_face (CRDocHandler * a_this,
214                 CRParsingLocation *a_location)
215{
216        enum CRStatus status = CR_OK;
217        ParsingContext *ctxt = NULL;
218        ParsingContext **ctxtptr = NULL;
219
220        g_return_if_fail (a_this);
221
222        g_return_if_fail (a_this);
223	ctxtptr = &ctxt;
224        status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr);
225        g_return_if_fail (status == CR_OK && ctxt);
226        g_return_if_fail (ctxt->cur_stmt == NULL);
227
228        ctxt->cur_stmt =
229                cr_statement_new_at_font_face_rule (ctxt->stylesheet, NULL);
230
231        g_return_if_fail (ctxt->cur_stmt);
232}
233
234static void
235end_font_face (CRDocHandler * a_this)
236{
237        enum CRStatus status = CR_OK;
238        ParsingContext *ctxt = NULL;
239        ParsingContext **ctxtptr = NULL;
240        CRStatement *stmts = NULL;
241
242        g_return_if_fail (a_this);
243
244        g_return_if_fail (a_this);
245	ctxtptr = &ctxt;
246        status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr);
247        g_return_if_fail (status == CR_OK && ctxt);
248        g_return_if_fail
249                (ctxt->cur_stmt
250                 && ctxt->cur_stmt->type == AT_FONT_FACE_RULE_STMT
251                 && ctxt->stylesheet);
252
253        stmts = cr_statement_append (ctxt->stylesheet->statements,
254                                     ctxt->cur_stmt);
255        if (!stmts)
256                goto error;
257
258        ctxt->stylesheet->statements = stmts;
259        stmts = NULL;
260        ctxt->cur_stmt = NULL;
261
262        return;
263
264      error:
265
266        if (ctxt->cur_stmt) {
267                cr_statement_destroy (ctxt->cur_stmt);
268                ctxt->cur_stmt = NULL;
269        }
270
271        if (!stmts) {
272                cr_statement_destroy (stmts);
273                stmts = NULL;
274        }
275}
276
277static void
278end_document (CRDocHandler * a_this)
279{
280        enum CRStatus status = CR_OK;
281        ParsingContext *ctxt = NULL;
282        ParsingContext **ctxtptr = NULL;
283
284        g_return_if_fail (a_this);
285	ctxtptr = &ctxt;
286        status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr);
287        g_return_if_fail (status == CR_OK && ctxt);
288
289        if (!ctxt->stylesheet || ctxt->cur_stmt)
290                goto error;
291
292        status = cr_doc_handler_set_result (a_this, ctxt->stylesheet);
293        g_return_if_fail (status == CR_OK);
294
295        ctxt->stylesheet = NULL;
296        destroy_context (ctxt);
297        cr_doc_handler_set_ctxt (a_this, NULL);
298
299        return;
300
301      error:
302        if (ctxt) {
303                destroy_context (ctxt);
304        }
305}
306
307static void
308charset (CRDocHandler * a_this, CRString * a_charset,
309         CRParsingLocation *a_location)
310{
311        enum CRStatus status = CR_OK;
312        CRStatement *stmt = NULL,
313                *stmt2 = NULL;
314        CRString *charset = NULL;
315
316        ParsingContext *ctxt = NULL;
317        ParsingContext **ctxtptr = NULL;
318
319        g_return_if_fail (a_this);
320	ctxtptr = &ctxt;
321        status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr);
322        g_return_if_fail (status == CR_OK && ctxt);
323        g_return_if_fail (ctxt->stylesheet);
324
325        charset = cr_string_dup (a_charset) ;
326        stmt = cr_statement_new_at_charset_rule (ctxt->stylesheet, charset);
327        g_return_if_fail (stmt);
328        stmt2 = cr_statement_append (ctxt->stylesheet->statements, stmt);
329        if (!stmt2) {
330                if (stmt) {
331                        cr_statement_destroy (stmt);
332                        stmt = NULL;
333                }
334                if (charset) {
335                        cr_string_destroy (charset);
336                }
337                return;
338        }
339        ctxt->stylesheet->statements = stmt2;
340        stmt2 = NULL;
341}
342
343static void
344start_page (CRDocHandler * a_this,
345            CRString * a_page,
346            CRString * a_pseudo,
347            CRParsingLocation *a_location)
348{
349        enum CRStatus status = CR_OK;
350        ParsingContext *ctxt = NULL;
351        ParsingContext **ctxtptr = NULL;
352
353        g_return_if_fail (a_this);
354	ctxtptr = &ctxt;
355        status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr);
356        g_return_if_fail (status == CR_OK && ctxt);
357        g_return_if_fail (ctxt->cur_stmt == NULL);
358
359        ctxt->cur_stmt = cr_statement_new_at_page_rule
360                (ctxt->stylesheet, NULL, NULL, NULL);
361        if (a_page) {
362                ctxt->cur_stmt->kind.page_rule->name =
363                        cr_string_dup (a_page) ;
364
365                if (!ctxt->cur_stmt->kind.page_rule->name) {
366                        goto error;
367                }
368        }
369        if (a_pseudo) {
370                ctxt->cur_stmt->kind.page_rule->pseudo =
371                        cr_string_dup (a_pseudo) ;
372                if (!ctxt->cur_stmt->kind.page_rule->pseudo) {
373                        goto error;
374                }
375        }
376        return;
377
378 error:
379        if (ctxt->cur_stmt) {
380                cr_statement_destroy (ctxt->cur_stmt);
381                ctxt->cur_stmt = NULL;
382        }
383}
384
385static void
386end_page (CRDocHandler * a_this,
387          CRString * a_page,
388          CRString * a_pseudo_page)
389{
390        enum CRStatus status = CR_OK;
391        ParsingContext *ctxt = NULL;
392        ParsingContext **ctxtptr = NULL;
393        CRStatement *stmt = NULL;
394
395        g_return_if_fail (a_this);
396	ctxtptr = &ctxt;
397        status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr);
398        g_return_if_fail (status == CR_OK && ctxt);
399        g_return_if_fail (ctxt->cur_stmt
400                          && ctxt->cur_stmt->type == AT_PAGE_RULE_STMT
401                          && ctxt->stylesheet);
402
403        stmt = cr_statement_append (ctxt->stylesheet->statements,
404                                    ctxt->cur_stmt);
405
406        if (stmt) {
407                ctxt->stylesheet->statements = stmt;
408                stmt = NULL;
409                ctxt->cur_stmt = NULL;
410        }
411
412        if (ctxt->cur_stmt) {
413                cr_statement_destroy (ctxt->cur_stmt);
414                ctxt->cur_stmt = NULL;
415        }
416        a_page = NULL;          /*keep compiler happy */
417        a_pseudo_page = NULL;   /*keep compiler happy */
418}
419
420static void
421start_media (CRDocHandler * a_this,
422             GList * a_media_list,
423             CRParsingLocation *a_location)
424{
425        enum CRStatus status = CR_OK;
426        ParsingContext *ctxt = NULL;
427        ParsingContext **ctxtptr = NULL;
428        GList *media_list = NULL;
429
430        g_return_if_fail (a_this);
431	ctxtptr = &ctxt;
432        status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr);
433        g_return_if_fail (status == CR_OK && ctxt);
434
435        g_return_if_fail (ctxt
436                          && ctxt->cur_stmt == NULL
437                          && ctxt->cur_media_stmt == NULL
438                          && ctxt->stylesheet);
439        if (a_media_list) {
440                /*duplicate the media_list */
441                media_list = cr_utils_dup_glist_of_cr_string
442                        (a_media_list);
443        }
444        ctxt->cur_media_stmt =
445                cr_statement_new_at_media_rule
446                (ctxt->stylesheet, NULL, media_list);
447
448}
449
450static void
451end_media (CRDocHandler * a_this, GList * a_media_list)
452{
453        enum CRStatus status = CR_OK;
454        ParsingContext *ctxt = NULL;
455        ParsingContext **ctxtptr = NULL;
456        CRStatement *stmts = NULL;
457
458        g_return_if_fail (a_this);
459	ctxtptr = &ctxt;
460        status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr);
461        g_return_if_fail (status == CR_OK && ctxt);
462        g_return_if_fail (ctxt
463                          && ctxt->cur_media_stmt
464                          && ctxt->cur_media_stmt->type == AT_MEDIA_RULE_STMT
465                          && ctxt->stylesheet);
466
467        stmts = cr_statement_append (ctxt->stylesheet->statements,
468                                     ctxt->cur_media_stmt);
469        if (!stmts) {
470                cr_statement_destroy (ctxt->cur_media_stmt);
471                ctxt->cur_media_stmt = NULL;
472        }
473
474        ctxt->stylesheet->statements = stmts;
475        stmts = NULL;
476
477        ctxt->cur_stmt = NULL ;
478        ctxt->cur_media_stmt = NULL ;
479        a_media_list = NULL;
480}
481
482static void
483import_style (CRDocHandler * a_this,
484              GList * a_media_list,
485              CRString * a_uri,
486              CRString * a_uri_default_ns,
487              CRParsingLocation *a_location)
488{
489        enum CRStatus status = CR_OK;
490        CRString *uri = NULL;
491        CRStatement *stmt = NULL,
492                *stmt2 = NULL;
493        ParsingContext *ctxt = NULL;
494        ParsingContext **ctxtptr = NULL;
495        GList *media_list = NULL ;
496
497        g_return_if_fail (a_this);
498	ctxtptr = &ctxt;
499        status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr);
500        g_return_if_fail (status == CR_OK && ctxt);
501        g_return_if_fail (ctxt->stylesheet);
502
503        uri = cr_string_dup (a_uri) ;
504        if (a_media_list)
505                media_list = cr_utils_dup_glist_of_cr_string (a_media_list) ;
506        stmt = cr_statement_new_at_import_rule
507                (ctxt->stylesheet, uri, media_list, NULL);
508        if (!stmt)
509                goto error;
510
511        if (ctxt->cur_stmt) {
512                stmt2 = cr_statement_append (ctxt->cur_stmt, stmt);
513                if (!stmt2)
514                        goto error;
515                ctxt->cur_stmt = stmt2;
516                stmt2 = NULL;
517                stmt = NULL;
518        } else {
519                stmt2 = cr_statement_append (ctxt->stylesheet->statements,
520                                             stmt);
521                if (!stmt2)
522                        goto error;
523                ctxt->stylesheet->statements = stmt2;
524                stmt2 = NULL;
525                stmt = NULL;
526        }
527
528        return;
529
530      error:
531        if (uri) {
532                cr_string_destroy (uri);
533        }
534
535        if (stmt) {
536                cr_statement_destroy (stmt);
537                stmt = NULL;
538        }
539        a_uri_default_ns = NULL; /*keep compiler happy */
540}
541
542static void
543start_selector (CRDocHandler * a_this, CRSelector * a_selector_list)
544{
545        enum CRStatus status = CR_OK ;
546        ParsingContext *ctxt = NULL;
547        ParsingContext **ctxtptr = NULL;
548
549        g_return_if_fail (a_this);
550	ctxtptr = &ctxt;
551        status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr);
552        g_return_if_fail (status == CR_OK && ctxt);
553        if (ctxt->cur_stmt) {
554                /*hmm, this should be NULL so free it */
555                cr_statement_destroy (ctxt->cur_stmt);
556                ctxt->cur_stmt = NULL;
557        }
558
559        ctxt->cur_stmt = cr_statement_new_ruleset
560                (ctxt->stylesheet, a_selector_list, NULL, NULL);
561}
562
563static void
564end_selector (CRDocHandler * a_this, CRSelector * a_selector_list)
565{
566        enum CRStatus status = CR_OK;
567        ParsingContext *ctxt = NULL;
568        ParsingContext **ctxtptr = NULL;
569
570        g_return_if_fail (a_this);
571	ctxtptr = &ctxt;
572        status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr);
573        g_return_if_fail (status == CR_OK && ctxt);
574        g_return_if_fail (ctxt->cur_stmt && ctxt->stylesheet);
575
576        if (ctxt->cur_stmt) {
577                CRStatement *stmts = NULL;
578
579                if (ctxt->cur_media_stmt) {
580                        CRAtMediaRule *media_rule = NULL;
581
582                        media_rule = ctxt->cur_media_stmt->kind.media_rule;
583
584                        stmts = cr_statement_append
585                                (media_rule->rulesets, ctxt->cur_stmt);
586
587                        if (!stmts) {
588                                cr_utils_trace_info
589                                        ("Could not append a new statement");
590                                cr_statement_destroy (media_rule->rulesets);
591                                ctxt->cur_media_stmt->
592                                        kind.media_rule->rulesets = NULL;
593                                return;
594                        }
595                        media_rule->rulesets = stmts;
596                        ctxt->cur_stmt = NULL;
597                } else {
598                        stmts = cr_statement_append
599                                (ctxt->stylesheet->statements,
600                                 ctxt->cur_stmt);
601                        if (!stmts) {
602                                cr_utils_trace_info
603                                        ("Could not append a new statement");
604                                cr_statement_destroy (ctxt->cur_stmt);
605                                ctxt->cur_stmt = NULL;
606                                return;
607                        }
608                        ctxt->stylesheet->statements = stmts;
609                        ctxt->cur_stmt = NULL;
610                }
611
612        }
613        a_selector_list = NULL; /*keep compiler happy */
614}
615
616static void
617property (CRDocHandler * a_this,
618          CRString * a_name,
619          CRTerm * a_expression,
620          gboolean a_important)
621{
622        enum CRStatus status = CR_OK;
623        ParsingContext *ctxt = NULL;
624        ParsingContext **ctxtptr = NULL;
625        CRDeclaration *decl = NULL,
626                *decl2 = NULL;
627        CRString *str = NULL;
628
629        g_return_if_fail (a_this);
630	ctxtptr = &ctxt;
631        status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr);
632        g_return_if_fail (status == CR_OK && ctxt);
633
634        /*
635         *make sure a current ruleset statement has been allocated
636         *already.
637         */
638        g_return_if_fail
639                (ctxt->cur_stmt
640                 &&
641                 (ctxt->cur_stmt->type == RULESET_STMT
642                  || ctxt->cur_stmt->type == AT_FONT_FACE_RULE_STMT
643                  || ctxt->cur_stmt->type == AT_PAGE_RULE_STMT));
644
645        if (a_name) {
646                str = cr_string_dup (a_name);
647                g_return_if_fail (str);
648        }
649
650        /*instanciates a new declaration */
651        decl = cr_declaration_new (ctxt->cur_stmt, str, a_expression);
652        g_return_if_fail (decl);
653        str = NULL;
654        decl->important = a_important;
655        /*
656         *add the new declaration to the current statement
657         *being build.
658         */
659        switch (ctxt->cur_stmt->type) {
660        case RULESET_STMT:
661                decl2 = cr_declaration_append
662                        (ctxt->cur_stmt->kind.ruleset->decl_list, decl);
663                if (!decl2) {
664                        cr_declaration_destroy (decl);
665                        cr_utils_trace_info
666                                ("Could not append decl to ruleset");
667                        goto error;
668                }
669                ctxt->cur_stmt->kind.ruleset->decl_list = decl2;
670                decl = NULL;
671                decl2 = NULL;
672                break;
673
674        case AT_FONT_FACE_RULE_STMT:
675                decl2 = cr_declaration_append
676                        (ctxt->cur_stmt->kind.font_face_rule->decl_list,
677                         decl);
678                if (!decl2) {
679                        cr_declaration_destroy (decl);
680                        cr_utils_trace_info
681                                ("Could not append decl to ruleset");
682                        goto error;
683                }
684                ctxt->cur_stmt->kind.font_face_rule->decl_list = decl2;
685                decl = NULL;
686                decl2 = NULL;
687                break;
688        case AT_PAGE_RULE_STMT:
689                decl2 = cr_declaration_append
690                        (ctxt->cur_stmt->kind.page_rule->decl_list, decl);
691                if (!decl2) {
692                        cr_declaration_destroy (decl);
693                        cr_utils_trace_info
694                                ("Could not append decl to ruleset");
695                        goto error;
696                }
697                ctxt->cur_stmt->kind.page_rule->decl_list = decl2;
698                decl = NULL;
699                decl2 = NULL;
700                break;
701
702        default:
703                goto error;
704                break;
705        }
706
707        return;
708
709      error:
710        if (str) {
711                g_free (str);
712                str = NULL;
713        }
714
715        if (decl) {
716                cr_declaration_destroy (decl);
717                decl = NULL;
718        }
719}
720
721static void
722error (CRDocHandler * a_this)
723{
724        enum CRStatus status = CR_OK;
725        ParsingContext *ctxt = NULL;
726        ParsingContext **ctxtptr = NULL;
727
728        g_return_if_fail (a_this);
729	ctxtptr = &ctxt;
730        status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr);
731        g_return_if_fail (status == CR_OK && ctxt);
732
733        if (ctxt->cur_stmt) {
734                cr_statement_destroy (ctxt->cur_stmt);
735                ctxt->cur_stmt = NULL;
736        }
737}
738
739static void
740unrecoverable_error (CRDocHandler * a_this)
741{
742        enum CRStatus status = CR_OK;
743        ParsingContext *ctxt = NULL;
744        ParsingContext **ctxtptr = NULL;
745
746	ctxtptr = &ctxt;
747        status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr);
748        g_return_if_fail (status == CR_OK);
749
750        if (ctxt) {
751                if (ctxt->stylesheet) {
752                        status = cr_doc_handler_set_result
753                                (a_this, ctxt->stylesheet);
754                        g_return_if_fail (status == CR_OK);
755                }
756                g_free (ctxt);
757                cr_doc_handler_set_ctxt (a_this, NULL);
758        }
759}
760
761/********************************************
762 *Public methods
763 ********************************************/
764
765/**
766 * cr_om_parser_new:
767 *@a_input: the input stream.
768 *
769 *Constructor of the CROMParser.
770 *Returns the newly built instance of #CROMParser.
771 */
772CROMParser *
773cr_om_parser_new (CRInput * a_input)
774{
775        CROMParser *result = NULL;
776        enum CRStatus status = CR_OK;
777
778        result = g_try_malloc (sizeof (CROMParser));
779
780        if (!result) {
781                cr_utils_trace_info ("Out of memory");
782                return NULL;
783        }
784
785        memset (result, 0, sizeof (CROMParser));
786        PRIVATE (result) = g_try_malloc (sizeof (CROMParserPriv));
787
788        if (!PRIVATE (result)) {
789                cr_utils_trace_info ("Out of memory");
790                goto error;
791        }
792
793        memset (PRIVATE (result), 0, sizeof (CROMParserPriv));
794
795        PRIVATE (result)->parser = cr_parser_new_from_input (a_input);
796
797        if (!PRIVATE (result)->parser) {
798                cr_utils_trace_info ("parsing instanciation failed");
799                goto error;
800        }
801
802        status = cr_om_parser_init_default_sac_handler (result);
803
804        if (status != CR_OK) {
805                goto error;
806        }
807
808        return result;
809
810      error:
811
812        if (result) {
813                cr_om_parser_destroy (result);
814        }
815
816        return NULL;
817}
818
819/**
820 * cr_om_parser_parse_buf:
821 *@a_this: the current instance of #CROMParser.
822 *@a_buf: the in memory buffer to parse.
823 *@a_len: the length of the in memory buffer in number of bytes.
824 *@a_enc: the encoding of the in memory buffer.
825 *@a_result: out parameter the resulting style sheet
826 *
827 *Parses the content of an in memory  buffer.
828 *
829 *Returns CR_OK upon successfull completion, an error code otherwise.
830 */
831enum CRStatus
832cr_om_parser_parse_buf (CROMParser * a_this,
833                        const guchar * a_buf,
834                        gulong a_len,
835                        enum CREncoding a_enc, CRStyleSheet ** a_result)
836{
837
838        enum CRStatus status = CR_OK;
839
840        g_return_val_if_fail (a_this && a_result, CR_BAD_PARAM_ERROR);
841
842        if (!PRIVATE (a_this)->parser) {
843                PRIVATE (a_this)->parser = cr_parser_new (NULL);
844        }
845
846        status = cr_parser_parse_buf (PRIVATE (a_this)->parser,
847                                      a_buf, a_len, a_enc);
848
849        if (status == CR_OK) {
850                CRStyleSheet *result = NULL;
851                CRStyleSheet **resultptr = NULL;
852                CRDocHandler *sac_handler = NULL;
853
854                cr_parser_get_sac_handler (PRIVATE (a_this)->parser,
855                                           &sac_handler);
856                g_return_val_if_fail (sac_handler, CR_ERROR);
857		resultptr = &result;
858                status = cr_doc_handler_get_result (sac_handler,
859                                                    (gpointer *) resultptr);
860                g_return_val_if_fail (status == CR_OK, status);
861
862                if (result)
863                        *a_result = result;
864        }
865
866        return status;
867}
868
869/**
870 * cr_om_parser_simply_parse_buf:
871 *@a_buf: the css2 in memory buffer.
872 *@a_len: the length of the in memory buffer.
873 *@a_enc: the encoding of the in memory buffer.
874 *@a_result: out parameter. The resulting css2 style sheet.
875 *
876 *The simpler way to parse an in memory css2 buffer.
877 *
878 *Returns CR_OK upon successfull completion, an error code otherwise.
879 */
880enum CRStatus
881cr_om_parser_simply_parse_buf (const guchar * a_buf,
882                               gulong a_len,
883                               enum CREncoding a_enc,
884                               CRStyleSheet ** a_result)
885{
886        CROMParser *parser = NULL;
887        enum CRStatus status = CR_OK;
888
889        parser = cr_om_parser_new (NULL);
890        if (!parser) {
891                cr_utils_trace_info ("Could not create om parser");
892                cr_utils_trace_info ("System possibly out of memory");
893                return CR_ERROR;
894        }
895
896        status = cr_om_parser_parse_buf (parser, a_buf, a_len,
897                                         a_enc, a_result);
898
899        if (parser) {
900                cr_om_parser_destroy (parser);
901                parser = NULL;
902        }
903
904        return status;
905}
906
907/**
908 * cr_om_parser_parse_file:
909 *@a_this: the current instance of the cssom parser.
910 *@a_file_uri: the uri of the file.
911 *(only local file paths are suppported so far)
912 *@a_enc: the encoding of the file.
913 *@a_result: out parameter. A pointer
914 *the build css object model.
915 *
916 *Parses a css2 stylesheet contained
917 *in a file.
918 *
919 * Returns CR_OK upon succesful completion, an error code otherwise.
920 */
921enum CRStatus
922cr_om_parser_parse_file (CROMParser * a_this,
923                         const guchar * a_file_uri,
924                         enum CREncoding a_enc, CRStyleSheet ** a_result)
925{
926        enum CRStatus status = CR_OK;
927
928        g_return_val_if_fail (a_this && a_file_uri && a_result,
929                              CR_BAD_PARAM_ERROR);
930
931        if (!PRIVATE (a_this)->parser) {
932                PRIVATE (a_this)->parser = cr_parser_new_from_file
933                        (a_file_uri, a_enc);
934        }
935
936        status = cr_parser_parse_file (PRIVATE (a_this)->parser,
937                                       a_file_uri, a_enc);
938
939        if (status == CR_OK) {
940                CRStyleSheet *result = NULL;
941                CRStyleSheet **resultptr = NULL;
942                CRDocHandler *sac_handler = NULL;
943
944                cr_parser_get_sac_handler (PRIVATE (a_this)->parser,
945                                           &sac_handler);
946                g_return_val_if_fail (sac_handler, CR_ERROR);
947		resultptr = &result;
948                status = cr_doc_handler_get_result
949                        (sac_handler, (gpointer *) resultptr);
950                g_return_val_if_fail (status == CR_OK, status);
951                if (result)
952                        *a_result = result;
953        }
954
955        return status;
956}
957
958/**
959 * cr_om_parser_simply_parse_file:
960 *@a_file_path: the css2 local file path.
961 *@a_enc: the file encoding.
962 *@a_result: out parameter. The returned css stylesheet.
963 *Must be freed by the caller using cr_stylesheet_destroy.
964 *
965 *The simpler method to parse a css2 file.
966 *
967 *Returns CR_OK upon successfull completion, an error code otherwise.
968 *Note that this method uses cr_om_parser_parse_file() so both methods
969 *have the same return values.
970 */
971enum CRStatus
972cr_om_parser_simply_parse_file (const guchar * a_file_path,
973                                enum CREncoding a_enc,
974                                CRStyleSheet ** a_result)
975{
976        CROMParser *parser = NULL;
977        enum CRStatus status = CR_OK;
978
979        parser = cr_om_parser_new (NULL);
980        if (!parser) {
981                cr_utils_trace_info ("Could not allocate om parser");
982                cr_utils_trace_info ("System may be out of memory");
983                return CR_ERROR;
984        }
985
986        status = cr_om_parser_parse_file (parser, a_file_path,
987                                          a_enc, a_result);
988        if (parser) {
989                cr_om_parser_destroy (parser);
990                parser = NULL;
991        }
992
993        return status;
994}
995
996/**
997 * cr_om_parser_parse_paths_to_cascade:
998 *@a_this: the current instance of #CROMParser
999 *@a_author_path: the path to the author stylesheet
1000 *@a_user_path: the path to the user stylesheet
1001 *@a_ua_path: the path to the User Agent stylesheet
1002 *@a_encoding: the encoding of the sheets.
1003 *@a_result: out parameter. The resulting cascade if the parsing
1004 *was okay
1005 *
1006 *Parses three sheets located by their paths and build a cascade
1007 *
1008 *Returns CR_OK upon successful completion, an error code otherwise
1009 */
1010enum CRStatus
1011cr_om_parser_parse_paths_to_cascade (CROMParser * a_this,
1012                                     const guchar * a_author_path,
1013                                     const guchar * a_user_path,
1014                                     const guchar * a_ua_path,
1015                                     enum CREncoding a_encoding,
1016                                     CRCascade ** a_result)
1017{
1018        enum CRStatus status = CR_OK;
1019
1020        /*0->author sheet, 1->user sheet, 2->UA sheet */
1021        CRStyleSheet *sheets[3];
1022        guchar *paths[3];
1023        CRCascade *result = NULL;
1024        gint i = 0;
1025
1026        g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
1027
1028        memset (sheets, 0, sizeof (CRStyleSheet*) * 3);
1029        paths[0] = (guchar *) a_author_path;
1030        paths[1] = (guchar *) a_user_path;
1031        paths[2] = (guchar *) a_ua_path;
1032
1033        for (i = 0; i < 3; i++) {
1034                status = cr_om_parser_parse_file (a_this, paths[i],
1035                                                  a_encoding, &sheets[i]);
1036                if (status != CR_OK) {
1037                        if (sheets[i]) {
1038                                cr_stylesheet_unref (sheets[i]);
1039                                sheets[i] = NULL;
1040                        }
1041                        continue;
1042                }
1043        }
1044        result = cr_cascade_new (sheets[0], sheets[1], sheets[2]);
1045        if (!result) {
1046                for (i = 0; i < 3; i++) {
1047                        cr_stylesheet_unref (sheets[i]);
1048                        sheets[i] = 0;
1049                }
1050                return CR_ERROR;
1051        }
1052        *a_result = result;
1053        return CR_OK;
1054}
1055
1056/**
1057 * cr_om_parser_simply_parse_paths_to_cascade:
1058 *@a_author_path: the path to the author stylesheet
1059 *@a_user_path: the path to the user stylesheet
1060 *@a_ua_path: the path to the User Agent stylesheet
1061 *@a_encoding: the encoding of the sheets.
1062 *@a_result: out parameter. The resulting cascade if the parsing
1063 *was okay
1064 *
1065 *Parses three sheets located by their paths and build a cascade
1066 *
1067 *Returns CR_OK upon successful completion, an error code otherwise
1068 */
1069enum CRStatus
1070cr_om_parser_simply_parse_paths_to_cascade (const guchar * a_author_path,
1071                                            const guchar * a_user_path,
1072                                            const guchar * a_ua_path,
1073                                            enum CREncoding a_encoding,
1074                                            CRCascade ** a_result)
1075{
1076        enum CRStatus status = CR_OK;
1077        CROMParser *parser = NULL;
1078
1079        parser = cr_om_parser_new (NULL);
1080        if (!parser) {
1081                cr_utils_trace_info ("could not allocated om parser");
1082                cr_utils_trace_info ("System may be out of memory");
1083                return CR_ERROR;
1084        }
1085        status = cr_om_parser_parse_paths_to_cascade (parser,
1086                                                      a_author_path,
1087                                                      a_user_path,
1088                                                      a_ua_path,
1089                                                      a_encoding, a_result);
1090        if (parser) {
1091                cr_om_parser_destroy (parser);
1092                parser = NULL;
1093        }
1094        return status;
1095}
1096
1097/**
1098 * cr_om_parser_destroy:
1099 *@a_this: the current instance of #CROMParser.
1100 *
1101 *Destructor of the #CROMParser.
1102 */
1103void
1104cr_om_parser_destroy (CROMParser * a_this)
1105{
1106        g_return_if_fail (a_this && PRIVATE (a_this));
1107
1108        if (PRIVATE (a_this)->parser) {
1109                cr_parser_destroy (PRIVATE (a_this)->parser);
1110                PRIVATE (a_this)->parser = NULL;
1111        }
1112
1113        if (PRIVATE (a_this)) {
1114                g_free (PRIVATE (a_this));
1115                PRIVATE (a_this) = NULL;
1116        }
1117
1118        if (a_this) {
1119                g_free (a_this);
1120                a_this = NULL;
1121        }
1122}
1123