1143 lines
34 KiB
C
1143 lines
34 KiB
C
/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */
|
|
|
|
/*
|
|
* This file is part of The Croco Library
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of version 2.1 of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
|
* USA
|
|
*
|
|
* Author: Dodji Seketeli
|
|
* See COPYRIGHTS file for copyright information.
|
|
*/
|
|
|
|
#include <string.h>
|
|
#include "cr-utils.h"
|
|
#include "cr-om-parser.h"
|
|
|
|
/**
|
|
*@CROMParser:
|
|
*
|
|
*The definition of the CSS Object Model Parser.
|
|
*This parser uses (and sits) the SAC api of libcroco defined
|
|
*in cr-parser.h and cr-doc-handler.h
|
|
*/
|
|
|
|
struct _CROMParserPriv {
|
|
CRParser *parser;
|
|
};
|
|
|
|
#define PRIVATE(a_this) ((a_this)->priv)
|
|
|
|
/*
|
|
*Forward declaration of a type defined later
|
|
*in this file.
|
|
*/
|
|
struct _ParsingContext;
|
|
typedef struct _ParsingContext ParsingContext;
|
|
|
|
static ParsingContext *new_parsing_context (void);
|
|
|
|
static void destroy_context (ParsingContext * a_ctxt);
|
|
|
|
static void unrecoverable_error (CRDocHandler * a_this);
|
|
|
|
static void error (CRDocHandler * a_this);
|
|
|
|
static void property (CRDocHandler * a_this,
|
|
CRString * a_name,
|
|
CRTerm * a_expression,
|
|
gboolean a_important);
|
|
|
|
static void end_selector (CRDocHandler * a_this,
|
|
CRSelector * a_selector_list);
|
|
|
|
static void start_selector (CRDocHandler * a_this,
|
|
CRSelector * a_selector_list);
|
|
|
|
static void start_font_face (CRDocHandler * a_this,
|
|
CRParsingLocation *a_location);
|
|
|
|
static void end_font_face (CRDocHandler * a_this);
|
|
|
|
static void end_document (CRDocHandler * a_this);
|
|
|
|
static void start_document (CRDocHandler * a_this);
|
|
|
|
static void charset (CRDocHandler * a_this,
|
|
CRString * a_charset,
|
|
CRParsingLocation *a_location);
|
|
|
|
static void start_page (CRDocHandler * a_this, CRString * a_page,
|
|
CRString * a_pseudo_page,
|
|
CRParsingLocation *a_location);
|
|
|
|
static void end_page (CRDocHandler * a_this, CRString * a_page,
|
|
CRString * a_pseudo_page);
|
|
|
|
static void start_media (CRDocHandler * a_this,
|
|
GList * a_media_list,
|
|
CRParsingLocation *a_location);
|
|
|
|
static void end_media (CRDocHandler * a_this,
|
|
GList * a_media_list);
|
|
|
|
static void import_style (CRDocHandler * a_this,
|
|
GList * a_media_list,
|
|
CRString * a_uri,
|
|
CRString * a_uri_default_ns,
|
|
CRParsingLocation *a_location);
|
|
|
|
struct _ParsingContext {
|
|
CRStyleSheet *stylesheet;
|
|
CRStatement *cur_stmt;
|
|
CRStatement *cur_media_stmt;
|
|
};
|
|
|
|
/********************************************
|
|
*Private methods
|
|
********************************************/
|
|
|
|
static ParsingContext *
|
|
new_parsing_context (void)
|
|
{
|
|
ParsingContext *result = NULL;
|
|
|
|
result = g_try_malloc (sizeof (ParsingContext));
|
|
if (!result) {
|
|
cr_utils_trace_info ("Out of Memory");
|
|
return NULL;
|
|
}
|
|
memset (result, 0, sizeof (ParsingContext));
|
|
return result;
|
|
}
|
|
|
|
static void
|
|
destroy_context (ParsingContext * a_ctxt)
|
|
{
|
|
g_return_if_fail (a_ctxt);
|
|
|
|
if (a_ctxt->stylesheet) {
|
|
cr_stylesheet_destroy (a_ctxt->stylesheet);
|
|
a_ctxt->stylesheet = NULL;
|
|
}
|
|
if (a_ctxt->cur_stmt) {
|
|
cr_statement_destroy (a_ctxt->cur_stmt);
|
|
a_ctxt->cur_stmt = NULL;
|
|
}
|
|
g_free (a_ctxt);
|
|
}
|
|
|
|
static enum CRStatus
|
|
cr_om_parser_init_default_sac_handler (CROMParser * a_this)
|
|
{
|
|
CRDocHandler *sac_handler = NULL;
|
|
gboolean created_handler = FALSE;
|
|
enum CRStatus status = CR_OK;
|
|
|
|
g_return_val_if_fail (a_this && PRIVATE (a_this)
|
|
&& PRIVATE (a_this)->parser,
|
|
CR_BAD_PARAM_ERROR);
|
|
|
|
status = cr_parser_get_sac_handler (PRIVATE (a_this)->parser,
|
|
&sac_handler);
|
|
g_return_val_if_fail (status == CR_OK, status);
|
|
|
|
if (!sac_handler) {
|
|
sac_handler = cr_doc_handler_new ();
|
|
created_handler = TRUE;
|
|
}
|
|
|
|
/*
|
|
*initialize here the sac handler.
|
|
*/
|
|
sac_handler->start_document = start_document;
|
|
sac_handler->end_document = end_document;
|
|
sac_handler->start_selector = start_selector;
|
|
sac_handler->end_selector = end_selector;
|
|
sac_handler->property = property;
|
|
sac_handler->start_font_face = start_font_face;
|
|
sac_handler->end_font_face = end_font_face;
|
|
sac_handler->error = error;
|
|
sac_handler->unrecoverable_error = unrecoverable_error;
|
|
sac_handler->charset = charset;
|
|
sac_handler->start_page = start_page;
|
|
sac_handler->end_page = end_page;
|
|
sac_handler->start_media = start_media;
|
|
sac_handler->end_media = end_media;
|
|
sac_handler->import_style = import_style;
|
|
|
|
if (created_handler) {
|
|
status = cr_parser_set_sac_handler (PRIVATE (a_this)->parser,
|
|
sac_handler);
|
|
cr_doc_handler_unref (sac_handler);
|
|
}
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
static void
|
|
start_document (CRDocHandler * a_this)
|
|
{
|
|
ParsingContext *ctxt = NULL;
|
|
CRStyleSheet *stylesheet = NULL;
|
|
|
|
g_return_if_fail (a_this);
|
|
|
|
ctxt = new_parsing_context ();
|
|
g_return_if_fail (ctxt);
|
|
|
|
stylesheet = cr_stylesheet_new (NULL);
|
|
ctxt->stylesheet = stylesheet;
|
|
cr_doc_handler_set_ctxt (a_this, ctxt);
|
|
}
|
|
|
|
static void
|
|
start_font_face (CRDocHandler * a_this,
|
|
CRParsingLocation *a_location)
|
|
{
|
|
enum CRStatus status = CR_OK;
|
|
ParsingContext *ctxt = NULL;
|
|
ParsingContext **ctxtptr = NULL;
|
|
|
|
g_return_if_fail (a_this);
|
|
|
|
g_return_if_fail (a_this);
|
|
ctxtptr = &ctxt;
|
|
status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr);
|
|
g_return_if_fail (status == CR_OK && ctxt);
|
|
g_return_if_fail (ctxt->cur_stmt == NULL);
|
|
|
|
ctxt->cur_stmt =
|
|
cr_statement_new_at_font_face_rule (ctxt->stylesheet, NULL);
|
|
|
|
g_return_if_fail (ctxt->cur_stmt);
|
|
}
|
|
|
|
static void
|
|
end_font_face (CRDocHandler * a_this)
|
|
{
|
|
enum CRStatus status = CR_OK;
|
|
ParsingContext *ctxt = NULL;
|
|
ParsingContext **ctxtptr = NULL;
|
|
CRStatement *stmts = NULL;
|
|
|
|
g_return_if_fail (a_this);
|
|
|
|
g_return_if_fail (a_this);
|
|
ctxtptr = &ctxt;
|
|
status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr);
|
|
g_return_if_fail (status == CR_OK && ctxt);
|
|
g_return_if_fail
|
|
(ctxt->cur_stmt
|
|
&& ctxt->cur_stmt->type == AT_FONT_FACE_RULE_STMT
|
|
&& ctxt->stylesheet);
|
|
|
|
stmts = cr_statement_append (ctxt->stylesheet->statements,
|
|
ctxt->cur_stmt);
|
|
if (!stmts)
|
|
goto error;
|
|
|
|
ctxt->stylesheet->statements = stmts;
|
|
stmts = NULL;
|
|
ctxt->cur_stmt = NULL;
|
|
|
|
return;
|
|
|
|
error:
|
|
|
|
if (ctxt->cur_stmt) {
|
|
cr_statement_destroy (ctxt->cur_stmt);
|
|
ctxt->cur_stmt = NULL;
|
|
}
|
|
|
|
if (!stmts) {
|
|
cr_statement_destroy (stmts);
|
|
stmts = NULL;
|
|
}
|
|
}
|
|
|
|
static void
|
|
end_document (CRDocHandler * a_this)
|
|
{
|
|
enum CRStatus status = CR_OK;
|
|
ParsingContext *ctxt = NULL;
|
|
ParsingContext **ctxtptr = NULL;
|
|
|
|
g_return_if_fail (a_this);
|
|
ctxtptr = &ctxt;
|
|
status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr);
|
|
g_return_if_fail (status == CR_OK && ctxt);
|
|
|
|
if (!ctxt->stylesheet || ctxt->cur_stmt)
|
|
goto error;
|
|
|
|
status = cr_doc_handler_set_result (a_this, ctxt->stylesheet);
|
|
g_return_if_fail (status == CR_OK);
|
|
|
|
ctxt->stylesheet = NULL;
|
|
destroy_context (ctxt);
|
|
cr_doc_handler_set_ctxt (a_this, NULL);
|
|
|
|
return;
|
|
|
|
error:
|
|
if (ctxt) {
|
|
destroy_context (ctxt);
|
|
}
|
|
}
|
|
|
|
static void
|
|
charset (CRDocHandler * a_this, CRString * a_charset,
|
|
CRParsingLocation *a_location)
|
|
{
|
|
enum CRStatus status = CR_OK;
|
|
CRStatement *stmt = NULL,
|
|
*stmt2 = NULL;
|
|
CRString *charset = NULL;
|
|
|
|
ParsingContext *ctxt = NULL;
|
|
ParsingContext **ctxtptr = NULL;
|
|
|
|
g_return_if_fail (a_this);
|
|
ctxtptr = &ctxt;
|
|
status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr);
|
|
g_return_if_fail (status == CR_OK && ctxt);
|
|
g_return_if_fail (ctxt->stylesheet);
|
|
|
|
charset = cr_string_dup (a_charset) ;
|
|
stmt = cr_statement_new_at_charset_rule (ctxt->stylesheet, charset);
|
|
g_return_if_fail (stmt);
|
|
stmt2 = cr_statement_append (ctxt->stylesheet->statements, stmt);
|
|
if (!stmt2) {
|
|
if (stmt) {
|
|
cr_statement_destroy (stmt);
|
|
stmt = NULL;
|
|
}
|
|
if (charset) {
|
|
cr_string_destroy (charset);
|
|
}
|
|
return;
|
|
}
|
|
ctxt->stylesheet->statements = stmt2;
|
|
stmt2 = NULL;
|
|
}
|
|
|
|
static void
|
|
start_page (CRDocHandler * a_this,
|
|
CRString * a_page,
|
|
CRString * a_pseudo,
|
|
CRParsingLocation *a_location)
|
|
{
|
|
enum CRStatus status = CR_OK;
|
|
ParsingContext *ctxt = NULL;
|
|
ParsingContext **ctxtptr = NULL;
|
|
|
|
g_return_if_fail (a_this);
|
|
ctxtptr = &ctxt;
|
|
status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr);
|
|
g_return_if_fail (status == CR_OK && ctxt);
|
|
g_return_if_fail (ctxt->cur_stmt == NULL);
|
|
|
|
ctxt->cur_stmt = cr_statement_new_at_page_rule
|
|
(ctxt->stylesheet, NULL, NULL, NULL);
|
|
if (a_page) {
|
|
ctxt->cur_stmt->kind.page_rule->name =
|
|
cr_string_dup (a_page) ;
|
|
|
|
if (!ctxt->cur_stmt->kind.page_rule->name) {
|
|
goto error;
|
|
}
|
|
}
|
|
if (a_pseudo) {
|
|
ctxt->cur_stmt->kind.page_rule->pseudo =
|
|
cr_string_dup (a_pseudo) ;
|
|
if (!ctxt->cur_stmt->kind.page_rule->pseudo) {
|
|
goto error;
|
|
}
|
|
}
|
|
return;
|
|
|
|
error:
|
|
if (ctxt->cur_stmt) {
|
|
cr_statement_destroy (ctxt->cur_stmt);
|
|
ctxt->cur_stmt = NULL;
|
|
}
|
|
}
|
|
|
|
static void
|
|
end_page (CRDocHandler * a_this,
|
|
CRString * a_page,
|
|
CRString * a_pseudo_page)
|
|
{
|
|
enum CRStatus status = CR_OK;
|
|
ParsingContext *ctxt = NULL;
|
|
ParsingContext **ctxtptr = NULL;
|
|
CRStatement *stmt = NULL;
|
|
|
|
(void) a_page;
|
|
(void) a_pseudo_page;
|
|
|
|
g_return_if_fail (a_this);
|
|
|
|
ctxtptr = &ctxt;
|
|
status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr);
|
|
|
|
g_return_if_fail (status == CR_OK && ctxt);
|
|
|
|
g_return_if_fail (ctxt->cur_stmt
|
|
&& ctxt->cur_stmt->type == AT_PAGE_RULE_STMT
|
|
&& ctxt->stylesheet);
|
|
|
|
stmt = cr_statement_append (ctxt->stylesheet->statements,
|
|
ctxt->cur_stmt);
|
|
|
|
if (stmt) {
|
|
ctxt->stylesheet->statements = stmt;
|
|
stmt = NULL;
|
|
ctxt->cur_stmt = NULL;
|
|
}
|
|
|
|
if (ctxt->cur_stmt) {
|
|
cr_statement_destroy (ctxt->cur_stmt);
|
|
ctxt->cur_stmt = NULL;
|
|
}
|
|
a_page = NULL; /*keep compiler happy */
|
|
a_pseudo_page = NULL; /*keep compiler happy */
|
|
}
|
|
|
|
static void
|
|
start_media (CRDocHandler * a_this,
|
|
GList * a_media_list,
|
|
CRParsingLocation *a_location)
|
|
{
|
|
enum CRStatus status = CR_OK;
|
|
ParsingContext *ctxt = NULL;
|
|
ParsingContext **ctxtptr = NULL;
|
|
GList *media_list = NULL;
|
|
|
|
g_return_if_fail (a_this);
|
|
ctxtptr = &ctxt;
|
|
status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr);
|
|
g_return_if_fail (status == CR_OK && ctxt);
|
|
|
|
g_return_if_fail (ctxt
|
|
&& ctxt->cur_stmt == NULL
|
|
&& ctxt->cur_media_stmt == NULL
|
|
&& ctxt->stylesheet);
|
|
if (a_media_list) {
|
|
/*duplicate the media_list */
|
|
media_list = cr_utils_dup_glist_of_cr_string
|
|
(a_media_list);
|
|
}
|
|
ctxt->cur_media_stmt =
|
|
cr_statement_new_at_media_rule
|
|
(ctxt->stylesheet, NULL, media_list);
|
|
|
|
}
|
|
|
|
static void
|
|
end_media (CRDocHandler * a_this, GList * a_media_list)
|
|
{
|
|
enum CRStatus status = CR_OK;
|
|
ParsingContext *ctxt = NULL;
|
|
ParsingContext **ctxtptr = NULL;
|
|
CRStatement *stmts = NULL;
|
|
|
|
(void) a_media_list;
|
|
|
|
g_return_if_fail (a_this);
|
|
|
|
ctxtptr = &ctxt;
|
|
status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr);
|
|
|
|
g_return_if_fail (status == CR_OK && ctxt);
|
|
|
|
g_return_if_fail (ctxt
|
|
&& ctxt->cur_media_stmt
|
|
&& ctxt->cur_media_stmt->type == AT_MEDIA_RULE_STMT
|
|
&& ctxt->stylesheet);
|
|
|
|
stmts = cr_statement_append (ctxt->stylesheet->statements,
|
|
ctxt->cur_media_stmt);
|
|
|
|
if (!stmts) {
|
|
cr_statement_destroy (ctxt->cur_media_stmt);
|
|
ctxt->cur_media_stmt = NULL;
|
|
}
|
|
|
|
ctxt->stylesheet->statements = stmts;
|
|
stmts = NULL;
|
|
|
|
ctxt->cur_stmt = NULL ;
|
|
ctxt->cur_media_stmt = NULL ;
|
|
a_media_list = NULL;
|
|
}
|
|
|
|
static void
|
|
import_style (CRDocHandler * a_this,
|
|
GList * a_media_list,
|
|
CRString * a_uri,
|
|
CRString * a_uri_default_ns,
|
|
CRParsingLocation *a_location)
|
|
{
|
|
enum CRStatus status = CR_OK;
|
|
CRString *uri = NULL;
|
|
CRStatement *stmt = NULL,
|
|
*stmt2 = NULL;
|
|
ParsingContext *ctxt = NULL;
|
|
ParsingContext **ctxtptr = NULL;
|
|
GList *media_list = NULL ;
|
|
|
|
(void) a_uri_default_ns;
|
|
|
|
g_return_if_fail (a_this);
|
|
|
|
ctxtptr = &ctxt;
|
|
status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr);
|
|
|
|
g_return_if_fail (status == CR_OK && ctxt);
|
|
|
|
g_return_if_fail (ctxt->stylesheet);
|
|
|
|
uri = cr_string_dup (a_uri) ;
|
|
|
|
if (a_media_list)
|
|
media_list = cr_utils_dup_glist_of_cr_string (a_media_list) ;
|
|
|
|
stmt = cr_statement_new_at_import_rule
|
|
(ctxt->stylesheet, uri, media_list, NULL);
|
|
|
|
if (!stmt)
|
|
goto error;
|
|
|
|
if (ctxt->cur_stmt) {
|
|
stmt2 = cr_statement_append (ctxt->cur_stmt, stmt);
|
|
if (!stmt2)
|
|
goto error;
|
|
ctxt->cur_stmt = stmt2;
|
|
stmt2 = NULL;
|
|
stmt = NULL;
|
|
} else {
|
|
stmt2 = cr_statement_append (ctxt->stylesheet->statements,
|
|
stmt);
|
|
if (!stmt2)
|
|
goto error;
|
|
ctxt->stylesheet->statements = stmt2;
|
|
stmt2 = NULL;
|
|
stmt = NULL;
|
|
}
|
|
|
|
return;
|
|
|
|
error:
|
|
if (uri) {
|
|
cr_string_destroy (uri);
|
|
}
|
|
|
|
if (stmt) {
|
|
cr_statement_destroy (stmt);
|
|
stmt = NULL;
|
|
}
|
|
a_uri_default_ns = NULL; /*keep compiler happy */
|
|
}
|
|
|
|
static void
|
|
start_selector (CRDocHandler * a_this, CRSelector * a_selector_list)
|
|
{
|
|
enum CRStatus status = CR_OK ;
|
|
ParsingContext *ctxt = NULL;
|
|
ParsingContext **ctxtptr = NULL;
|
|
|
|
g_return_if_fail (a_this);
|
|
ctxtptr = &ctxt;
|
|
status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr);
|
|
g_return_if_fail (status == CR_OK && ctxt);
|
|
if (ctxt->cur_stmt) {
|
|
/*hmm, this should be NULL so free it */
|
|
cr_statement_destroy (ctxt->cur_stmt);
|
|
ctxt->cur_stmt = NULL;
|
|
}
|
|
|
|
ctxt->cur_stmt = cr_statement_new_ruleset
|
|
(ctxt->stylesheet, a_selector_list, NULL, NULL);
|
|
}
|
|
|
|
static void
|
|
end_selector (CRDocHandler * a_this, CRSelector * a_selector_list)
|
|
{
|
|
enum CRStatus status = CR_OK;
|
|
ParsingContext *ctxt = NULL;
|
|
ParsingContext **ctxtptr = NULL;
|
|
|
|
(void) a_selector_list;
|
|
|
|
g_return_if_fail (a_this);
|
|
|
|
ctxtptr = &ctxt;
|
|
status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr);
|
|
|
|
g_return_if_fail (status == CR_OK && ctxt);
|
|
|
|
g_return_if_fail (ctxt->cur_stmt && ctxt->stylesheet);
|
|
|
|
if (ctxt->cur_stmt) {
|
|
CRStatement *stmts = NULL;
|
|
|
|
if (ctxt->cur_media_stmt) {
|
|
CRAtMediaRule *media_rule = NULL;
|
|
|
|
media_rule = ctxt->cur_media_stmt->kind.media_rule;
|
|
|
|
stmts = cr_statement_append
|
|
(media_rule->rulesets, ctxt->cur_stmt);
|
|
|
|
if (!stmts) {
|
|
cr_utils_trace_info
|
|
("Could not append a new statement");
|
|
cr_statement_destroy (media_rule->rulesets);
|
|
ctxt->cur_media_stmt->
|
|
kind.media_rule->rulesets = NULL;
|
|
return;
|
|
}
|
|
media_rule->rulesets = stmts;
|
|
ctxt->cur_stmt = NULL;
|
|
} else {
|
|
stmts = cr_statement_append
|
|
(ctxt->stylesheet->statements,
|
|
ctxt->cur_stmt);
|
|
if (!stmts) {
|
|
cr_utils_trace_info
|
|
("Could not append a new statement");
|
|
cr_statement_destroy (ctxt->cur_stmt);
|
|
ctxt->cur_stmt = NULL;
|
|
return;
|
|
}
|
|
ctxt->stylesheet->statements = stmts;
|
|
ctxt->cur_stmt = NULL;
|
|
}
|
|
|
|
}
|
|
|
|
a_selector_list = NULL; /*keep compiler happy */
|
|
}
|
|
|
|
static void
|
|
property (CRDocHandler * a_this,
|
|
CRString * a_name,
|
|
CRTerm * a_expression,
|
|
gboolean a_important)
|
|
{
|
|
enum CRStatus status = CR_OK;
|
|
ParsingContext *ctxt = NULL;
|
|
ParsingContext **ctxtptr = NULL;
|
|
CRDeclaration *decl = NULL,
|
|
*decl2 = NULL;
|
|
CRString *str = NULL;
|
|
|
|
g_return_if_fail (a_this);
|
|
ctxtptr = &ctxt;
|
|
status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr);
|
|
g_return_if_fail (status == CR_OK && ctxt);
|
|
|
|
/*
|
|
*make sure a current ruleset statement has been allocated
|
|
*already.
|
|
*/
|
|
g_return_if_fail
|
|
(ctxt->cur_stmt
|
|
&&
|
|
(ctxt->cur_stmt->type == RULESET_STMT
|
|
|| ctxt->cur_stmt->type == AT_FONT_FACE_RULE_STMT
|
|
|| ctxt->cur_stmt->type == AT_PAGE_RULE_STMT));
|
|
|
|
if (a_name) {
|
|
str = cr_string_dup (a_name);
|
|
g_return_if_fail (str);
|
|
}
|
|
|
|
/*instantiates a new declaration */
|
|
decl = cr_declaration_new (ctxt->cur_stmt, str, a_expression);
|
|
g_return_if_fail (decl);
|
|
str = NULL;
|
|
decl->important = a_important;
|
|
/*
|
|
*add the new declaration to the current statement
|
|
*being build.
|
|
*/
|
|
switch (ctxt->cur_stmt->type) {
|
|
case RULESET_STMT:
|
|
decl2 = cr_declaration_append
|
|
(ctxt->cur_stmt->kind.ruleset->decl_list, decl);
|
|
if (!decl2) {
|
|
cr_declaration_destroy (decl);
|
|
cr_utils_trace_info
|
|
("Could not append decl to ruleset");
|
|
goto error;
|
|
}
|
|
ctxt->cur_stmt->kind.ruleset->decl_list = decl2;
|
|
decl = NULL;
|
|
decl2 = NULL;
|
|
break;
|
|
|
|
case AT_FONT_FACE_RULE_STMT:
|
|
decl2 = cr_declaration_append
|
|
(ctxt->cur_stmt->kind.font_face_rule->decl_list,
|
|
decl);
|
|
if (!decl2) {
|
|
cr_declaration_destroy (decl);
|
|
cr_utils_trace_info
|
|
("Could not append decl to ruleset");
|
|
goto error;
|
|
}
|
|
ctxt->cur_stmt->kind.font_face_rule->decl_list = decl2;
|
|
decl = NULL;
|
|
decl2 = NULL;
|
|
break;
|
|
case AT_PAGE_RULE_STMT:
|
|
decl2 = cr_declaration_append
|
|
(ctxt->cur_stmt->kind.page_rule->decl_list, decl);
|
|
if (!decl2) {
|
|
cr_declaration_destroy (decl);
|
|
cr_utils_trace_info
|
|
("Could not append decl to ruleset");
|
|
goto error;
|
|
}
|
|
ctxt->cur_stmt->kind.page_rule->decl_list = decl2;
|
|
decl = NULL;
|
|
decl2 = NULL;
|
|
break;
|
|
|
|
default:
|
|
goto error;
|
|
break;
|
|
}
|
|
|
|
return;
|
|
|
|
error:
|
|
if (str) {
|
|
g_free (str);
|
|
str = NULL;
|
|
}
|
|
|
|
if (decl) {
|
|
cr_declaration_destroy (decl);
|
|
decl = NULL;
|
|
}
|
|
}
|
|
|
|
static void
|
|
error (CRDocHandler * a_this)
|
|
{
|
|
enum CRStatus status = CR_OK;
|
|
ParsingContext *ctxt = NULL;
|
|
ParsingContext **ctxtptr = NULL;
|
|
|
|
g_return_if_fail (a_this);
|
|
ctxtptr = &ctxt;
|
|
status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr);
|
|
g_return_if_fail (status == CR_OK && ctxt);
|
|
|
|
if (ctxt->cur_stmt) {
|
|
cr_statement_destroy (ctxt->cur_stmt);
|
|
ctxt->cur_stmt = NULL;
|
|
}
|
|
}
|
|
|
|
static void
|
|
unrecoverable_error (CRDocHandler * a_this)
|
|
{
|
|
enum CRStatus status = CR_OK;
|
|
ParsingContext *ctxt = NULL;
|
|
ParsingContext **ctxtptr = NULL;
|
|
|
|
ctxtptr = &ctxt;
|
|
status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr);
|
|
g_return_if_fail (status == CR_OK);
|
|
|
|
if (ctxt) {
|
|
if (ctxt->stylesheet) {
|
|
status = cr_doc_handler_set_result
|
|
(a_this, ctxt->stylesheet);
|
|
g_return_if_fail (status == CR_OK);
|
|
}
|
|
g_free (ctxt);
|
|
cr_doc_handler_set_ctxt (a_this, NULL);
|
|
}
|
|
}
|
|
|
|
/********************************************
|
|
*Public methods
|
|
********************************************/
|
|
|
|
/**
|
|
* cr_om_parser_new:
|
|
*@a_input: the input stream.
|
|
*
|
|
*Constructor of the CROMParser.
|
|
*Returns the newly built instance of #CROMParser.
|
|
*/
|
|
CROMParser *
|
|
cr_om_parser_new (CRInput * a_input)
|
|
{
|
|
CROMParser *result = NULL;
|
|
enum CRStatus status = CR_OK;
|
|
|
|
result = g_try_malloc (sizeof (CROMParser));
|
|
|
|
if (!result) {
|
|
cr_utils_trace_info ("Out of memory");
|
|
return NULL;
|
|
}
|
|
|
|
memset (result, 0, sizeof (CROMParser));
|
|
PRIVATE (result) = g_try_malloc (sizeof (CROMParserPriv));
|
|
|
|
if (!PRIVATE (result)) {
|
|
cr_utils_trace_info ("Out of memory");
|
|
goto error;
|
|
}
|
|
|
|
memset (PRIVATE (result), 0, sizeof (CROMParserPriv));
|
|
|
|
PRIVATE (result)->parser = cr_parser_new_from_input (a_input);
|
|
|
|
if (!PRIVATE (result)->parser) {
|
|
cr_utils_trace_info ("parsing instantiation failed");
|
|
goto error;
|
|
}
|
|
|
|
status = cr_om_parser_init_default_sac_handler (result);
|
|
|
|
if (status != CR_OK) {
|
|
goto error;
|
|
}
|
|
|
|
return result;
|
|
|
|
error:
|
|
|
|
if (result) {
|
|
cr_om_parser_destroy (result);
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/**
|
|
* cr_om_parser_parse_buf:
|
|
*@a_this: the current instance of #CROMParser.
|
|
*@a_buf: the in memory buffer to parse.
|
|
*@a_len: the length of the in memory buffer in number of bytes.
|
|
*@a_enc: the encoding of the in memory buffer.
|
|
*@a_result: out parameter the resulting style sheet
|
|
*
|
|
*Parses the content of an in memory buffer.
|
|
*
|
|
*Returns CR_OK upon successful completion, an error code otherwise.
|
|
*/
|
|
enum CRStatus
|
|
cr_om_parser_parse_buf (CROMParser * a_this,
|
|
const guchar * a_buf,
|
|
gulong a_len,
|
|
enum CREncoding a_enc, CRStyleSheet ** a_result)
|
|
{
|
|
|
|
enum CRStatus status = CR_OK;
|
|
|
|
g_return_val_if_fail (a_this && a_result, CR_BAD_PARAM_ERROR);
|
|
|
|
if (!PRIVATE (a_this)->parser) {
|
|
PRIVATE (a_this)->parser = cr_parser_new (NULL);
|
|
}
|
|
|
|
status = cr_parser_parse_buf (PRIVATE (a_this)->parser,
|
|
a_buf, a_len, a_enc);
|
|
|
|
if (status == CR_OK) {
|
|
CRStyleSheet *result = NULL;
|
|
CRStyleSheet **resultptr = NULL;
|
|
CRDocHandler *sac_handler = NULL;
|
|
|
|
cr_parser_get_sac_handler (PRIVATE (a_this)->parser,
|
|
&sac_handler);
|
|
g_return_val_if_fail (sac_handler, CR_ERROR);
|
|
resultptr = &result;
|
|
status = cr_doc_handler_get_result (sac_handler,
|
|
(gpointer *) resultptr);
|
|
g_return_val_if_fail (status == CR_OK, status);
|
|
|
|
if (result)
|
|
*a_result = result;
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
/**
|
|
* cr_om_parser_simply_parse_buf:
|
|
*@a_buf: the css2 in memory buffer.
|
|
*@a_len: the length of the in memory buffer.
|
|
*@a_enc: the encoding of the in memory buffer.
|
|
*@a_result: out parameter. The resulting css2 style sheet.
|
|
*
|
|
*The simpler way to parse an in memory css2 buffer.
|
|
*
|
|
*Returns CR_OK upon successful completion, an error code otherwise.
|
|
*/
|
|
enum CRStatus
|
|
cr_om_parser_simply_parse_buf (const guchar * a_buf,
|
|
gulong a_len,
|
|
enum CREncoding a_enc,
|
|
CRStyleSheet ** a_result)
|
|
{
|
|
CROMParser *parser = NULL;
|
|
enum CRStatus status = CR_OK;
|
|
|
|
parser = cr_om_parser_new (NULL);
|
|
if (!parser) {
|
|
cr_utils_trace_info ("Could not create om parser");
|
|
cr_utils_trace_info ("System possibly out of memory");
|
|
return CR_ERROR;
|
|
}
|
|
|
|
status = cr_om_parser_parse_buf (parser, a_buf, a_len,
|
|
a_enc, a_result);
|
|
|
|
if (parser) {
|
|
cr_om_parser_destroy (parser);
|
|
parser = NULL;
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
/**
|
|
* cr_om_parser_parse_file:
|
|
*@a_this: the current instance of the cssom parser.
|
|
*@a_file_uri: the uri of the file.
|
|
*(only local file paths are supported so far)
|
|
*@a_enc: the encoding of the file.
|
|
*@a_result: out parameter. A pointer
|
|
*the build css object model.
|
|
*
|
|
*Parses a css2 stylesheet contained
|
|
*in a file.
|
|
*
|
|
* Returns CR_OK upon successful completion, an error code otherwise.
|
|
*/
|
|
enum CRStatus
|
|
cr_om_parser_parse_file (CROMParser * a_this,
|
|
const guchar * a_file_uri,
|
|
enum CREncoding a_enc, CRStyleSheet ** a_result)
|
|
{
|
|
enum CRStatus status = CR_OK;
|
|
|
|
g_return_val_if_fail (a_this && a_file_uri && a_result,
|
|
CR_BAD_PARAM_ERROR);
|
|
|
|
if (!PRIVATE (a_this)->parser) {
|
|
PRIVATE (a_this)->parser = cr_parser_new_from_file
|
|
(a_file_uri, a_enc);
|
|
}
|
|
|
|
status = cr_parser_parse_file (PRIVATE (a_this)->parser,
|
|
a_file_uri, a_enc);
|
|
|
|
if (status == CR_OK) {
|
|
CRStyleSheet *result = NULL;
|
|
CRStyleSheet **resultptr = NULL;
|
|
CRDocHandler *sac_handler = NULL;
|
|
|
|
cr_parser_get_sac_handler (PRIVATE (a_this)->parser,
|
|
&sac_handler);
|
|
g_return_val_if_fail (sac_handler, CR_ERROR);
|
|
resultptr = &result;
|
|
status = cr_doc_handler_get_result
|
|
(sac_handler, (gpointer *) resultptr);
|
|
g_return_val_if_fail (status == CR_OK, status);
|
|
if (result)
|
|
*a_result = result;
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
/**
|
|
* cr_om_parser_simply_parse_file:
|
|
*@a_file_path: the css2 local file path.
|
|
*@a_enc: the file encoding.
|
|
*@a_result: out parameter. The returned css stylesheet.
|
|
*Must be freed by the caller using cr_stylesheet_destroy.
|
|
*
|
|
*The simpler method to parse a css2 file.
|
|
*
|
|
*Returns CR_OK upon successful completion, an error code otherwise.
|
|
*Note that this method uses cr_om_parser_parse_file() so both methods
|
|
*have the same return values.
|
|
*/
|
|
enum CRStatus
|
|
cr_om_parser_simply_parse_file (const guchar * a_file_path,
|
|
enum CREncoding a_enc,
|
|
CRStyleSheet ** a_result)
|
|
{
|
|
CROMParser *parser = NULL;
|
|
enum CRStatus status = CR_OK;
|
|
|
|
parser = cr_om_parser_new (NULL);
|
|
if (!parser) {
|
|
cr_utils_trace_info ("Could not allocate om parser");
|
|
cr_utils_trace_info ("System may be out of memory");
|
|
return CR_ERROR;
|
|
}
|
|
|
|
status = cr_om_parser_parse_file (parser, a_file_path,
|
|
a_enc, a_result);
|
|
if (parser) {
|
|
cr_om_parser_destroy (parser);
|
|
parser = NULL;
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
/**
|
|
* cr_om_parser_parse_paths_to_cascade:
|
|
*@a_this: the current instance of #CROMParser
|
|
*@a_author_path: the path to the author stylesheet
|
|
*@a_user_path: the path to the user stylesheet
|
|
*@a_ua_path: the path to the User Agent stylesheet
|
|
*@a_encoding: the encoding of the sheets.
|
|
*@a_result: out parameter. The resulting cascade if the parsing
|
|
*was okay
|
|
*
|
|
*Parses three sheets located by their paths and build a cascade
|
|
*
|
|
*Returns CR_OK upon successful completion, an error code otherwise
|
|
*/
|
|
enum CRStatus
|
|
cr_om_parser_parse_paths_to_cascade (CROMParser * a_this,
|
|
const guchar * a_author_path,
|
|
const guchar * a_user_path,
|
|
const guchar * a_ua_path,
|
|
enum CREncoding a_encoding,
|
|
CRCascade ** a_result)
|
|
{
|
|
enum CRStatus status = CR_OK;
|
|
|
|
/*0->author sheet, 1->user sheet, 2->UA sheet */
|
|
CRStyleSheet *sheets[3];
|
|
guchar *paths[3];
|
|
CRCascade *result = NULL;
|
|
gint i = 0;
|
|
|
|
g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
|
|
|
|
memset (sheets, 0, sizeof (CRStyleSheet*) * 3);
|
|
paths[0] = (guchar *) a_author_path;
|
|
paths[1] = (guchar *) a_user_path;
|
|
paths[2] = (guchar *) a_ua_path;
|
|
|
|
for (i = 0; i < 3; i++) {
|
|
status = cr_om_parser_parse_file (a_this, paths[i],
|
|
a_encoding, &sheets[i]);
|
|
if (status != CR_OK) {
|
|
if (sheets[i]) {
|
|
cr_stylesheet_unref (sheets[i]);
|
|
sheets[i] = NULL;
|
|
}
|
|
continue;
|
|
}
|
|
}
|
|
result = cr_cascade_new (sheets[0], sheets[1], sheets[2]);
|
|
if (!result) {
|
|
for (i = 0; i < 3; i++) {
|
|
cr_stylesheet_unref (sheets[i]);
|
|
sheets[i] = 0;
|
|
}
|
|
return CR_ERROR;
|
|
}
|
|
*a_result = result;
|
|
return CR_OK;
|
|
}
|
|
|
|
/**
|
|
* cr_om_parser_simply_parse_paths_to_cascade:
|
|
*@a_author_path: the path to the author stylesheet
|
|
*@a_user_path: the path to the user stylesheet
|
|
*@a_ua_path: the path to the User Agent stylesheet
|
|
*@a_encoding: the encoding of the sheets.
|
|
*@a_result: out parameter. The resulting cascade if the parsing
|
|
*was okay
|
|
*
|
|
*Parses three sheets located by their paths and build a cascade
|
|
*
|
|
*Returns CR_OK upon successful completion, an error code otherwise
|
|
*/
|
|
enum CRStatus
|
|
cr_om_parser_simply_parse_paths_to_cascade (const guchar * a_author_path,
|
|
const guchar * a_user_path,
|
|
const guchar * a_ua_path,
|
|
enum CREncoding a_encoding,
|
|
CRCascade ** a_result)
|
|
{
|
|
enum CRStatus status = CR_OK;
|
|
CROMParser *parser = NULL;
|
|
|
|
parser = cr_om_parser_new (NULL);
|
|
if (!parser) {
|
|
cr_utils_trace_info ("could not allocated om parser");
|
|
cr_utils_trace_info ("System may be out of memory");
|
|
return CR_ERROR;
|
|
}
|
|
status = cr_om_parser_parse_paths_to_cascade (parser,
|
|
a_author_path,
|
|
a_user_path,
|
|
a_ua_path,
|
|
a_encoding, a_result);
|
|
if (parser) {
|
|
cr_om_parser_destroy (parser);
|
|
parser = NULL;
|
|
}
|
|
return status;
|
|
}
|
|
|
|
/**
|
|
* cr_om_parser_destroy:
|
|
*@a_this: the current instance of #CROMParser.
|
|
*
|
|
*Destructor of the #CROMParser.
|
|
*/
|
|
void
|
|
cr_om_parser_destroy (CROMParser * a_this)
|
|
{
|
|
g_return_if_fail (a_this && PRIVATE (a_this));
|
|
|
|
if (PRIVATE (a_this)->parser) {
|
|
cr_parser_destroy (PRIVATE (a_this)->parser);
|
|
PRIVATE (a_this)->parser = NULL;
|
|
}
|
|
|
|
if (PRIVATE (a_this)) {
|
|
g_free (PRIVATE (a_this));
|
|
PRIVATE (a_this) = NULL;
|
|
}
|
|
|
|
if (a_this) {
|
|
g_free (a_this);
|
|
a_this = NULL;
|
|
}
|
|
}
|