2795 lines
85 KiB
C
2795 lines
85 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 files for copyrights information.
|
|
*/
|
|
|
|
#include <string.h>
|
|
#include "cr-statement.h"
|
|
#include "cr-parser.h"
|
|
|
|
/**
|
|
*@file
|
|
*Definition of the #CRStatement class.
|
|
*/
|
|
|
|
#define DECLARATION_INDENT_NB 2
|
|
|
|
static void cr_statement_clear (CRStatement * a_this);
|
|
|
|
static void
|
|
parse_font_face_start_font_face_cb (CRDocHandler * a_this,
|
|
CRParsingLocation *a_location)
|
|
{
|
|
CRStatement *stmt = NULL;
|
|
enum CRStatus status = CR_OK;
|
|
|
|
stmt = cr_statement_new_at_font_face_rule (NULL, NULL);
|
|
g_return_if_fail (stmt);
|
|
|
|
status = cr_doc_handler_set_ctxt (a_this, stmt);
|
|
g_return_if_fail (status == CR_OK);
|
|
}
|
|
|
|
static void
|
|
parse_font_face_unrecoverable_error_cb (CRDocHandler * a_this)
|
|
{
|
|
CRStatement *stmt = NULL;
|
|
CRStatement **stmtptr = NULL;
|
|
enum CRStatus status = CR_OK;
|
|
|
|
g_return_if_fail (a_this);
|
|
|
|
stmtptr = &stmt;
|
|
status = cr_doc_handler_get_ctxt (a_this, (gpointer *) stmtptr);
|
|
if (status != CR_OK) {
|
|
cr_utils_trace_info ("Couldn't get parsing context. "
|
|
"This may lead to some memory leaks.");
|
|
return;
|
|
}
|
|
if (stmt) {
|
|
cr_statement_destroy (stmt);
|
|
cr_doc_handler_set_ctxt (a_this, NULL);
|
|
return;
|
|
}
|
|
}
|
|
|
|
static void
|
|
parse_font_face_property_cb (CRDocHandler * a_this,
|
|
CRString * a_name,
|
|
CRTerm * a_value, gboolean a_important)
|
|
{
|
|
enum CRStatus status = CR_OK;
|
|
CRString *name = NULL;
|
|
CRDeclaration *decl = NULL;
|
|
CRStatement *stmt = NULL;
|
|
CRStatement **stmtptr = NULL;
|
|
|
|
g_return_if_fail (a_this && a_name);
|
|
|
|
stmtptr = &stmt;
|
|
status = cr_doc_handler_get_ctxt (a_this, (gpointer *) stmtptr);
|
|
g_return_if_fail (status == CR_OK && stmt);
|
|
g_return_if_fail (stmt->type == AT_FONT_FACE_RULE_STMT);
|
|
|
|
name = cr_string_dup (a_name) ;
|
|
g_return_if_fail (name);
|
|
decl = cr_declaration_new (stmt, name, a_value);
|
|
if (!decl) {
|
|
cr_utils_trace_info ("cr_declaration_new () failed.");
|
|
goto error;
|
|
}
|
|
name = NULL;
|
|
|
|
stmt->kind.font_face_rule->decl_list =
|
|
cr_declaration_append (stmt->kind.font_face_rule->decl_list,
|
|
decl);
|
|
if (!stmt->kind.font_face_rule->decl_list)
|
|
goto error;
|
|
decl = NULL;
|
|
|
|
error:
|
|
if (decl) {
|
|
cr_declaration_unref (decl);
|
|
decl = NULL;
|
|
}
|
|
if (name) {
|
|
cr_string_destroy (name);
|
|
name = NULL;
|
|
}
|
|
}
|
|
|
|
static void
|
|
parse_font_face_end_font_face_cb (CRDocHandler * a_this)
|
|
{
|
|
CRStatement *result = NULL;
|
|
CRStatement **resultptr = NULL;
|
|
enum CRStatus status = CR_OK;
|
|
|
|
g_return_if_fail (a_this);
|
|
|
|
resultptr = &result;
|
|
status = cr_doc_handler_get_ctxt (a_this, (gpointer *) resultptr);
|
|
g_return_if_fail (status == CR_OK && result);
|
|
g_return_if_fail (result->type == AT_FONT_FACE_RULE_STMT);
|
|
|
|
status = cr_doc_handler_set_result (a_this, result);
|
|
g_return_if_fail (status == CR_OK);
|
|
}
|
|
|
|
static void
|
|
parse_page_start_page_cb (CRDocHandler * a_this,
|
|
CRString * a_name,
|
|
CRString * a_pseudo_page,
|
|
CRParsingLocation *a_location)
|
|
{
|
|
CRStatement *stmt = NULL;
|
|
enum CRStatus status = CR_OK;
|
|
CRString *page_name = NULL, *pseudo_name = NULL ;
|
|
|
|
if (a_name)
|
|
page_name = cr_string_dup (a_name) ;
|
|
if (a_pseudo_page)
|
|
pseudo_name = cr_string_dup (a_pseudo_page) ;
|
|
|
|
stmt = cr_statement_new_at_page_rule (NULL, NULL,
|
|
page_name,
|
|
pseudo_name);
|
|
page_name = NULL ;
|
|
pseudo_name = NULL ;
|
|
g_return_if_fail (stmt);
|
|
status = cr_doc_handler_set_ctxt (a_this, stmt);
|
|
g_return_if_fail (status == CR_OK);
|
|
}
|
|
|
|
static void
|
|
parse_page_unrecoverable_error_cb (CRDocHandler * a_this)
|
|
{
|
|
CRStatement *stmt = NULL;
|
|
CRStatement **stmtptr = NULL;
|
|
enum CRStatus status = CR_OK;
|
|
|
|
g_return_if_fail (a_this);
|
|
|
|
stmtptr = &stmt;
|
|
status = cr_doc_handler_get_ctxt (a_this, (gpointer *) stmtptr);
|
|
if (status != CR_OK) {
|
|
cr_utils_trace_info ("Couldn't get parsing context. "
|
|
"This may lead to some memory leaks.");
|
|
return;
|
|
}
|
|
if (stmt) {
|
|
cr_statement_destroy (stmt);
|
|
stmt = NULL;
|
|
cr_doc_handler_set_ctxt (a_this, NULL);
|
|
}
|
|
}
|
|
|
|
static void
|
|
parse_page_property_cb (CRDocHandler * a_this,
|
|
CRString * a_name,
|
|
CRTerm * a_expression, gboolean a_important)
|
|
{
|
|
CRString *name = NULL;
|
|
CRStatement *stmt = NULL;
|
|
CRStatement **stmtptr = NULL;
|
|
CRDeclaration *decl = NULL;
|
|
enum CRStatus status = CR_OK;
|
|
|
|
stmtptr = &stmt;
|
|
status = cr_doc_handler_get_ctxt (a_this, (gpointer *) stmtptr);
|
|
g_return_if_fail (status == CR_OK && stmt->type == AT_PAGE_RULE_STMT);
|
|
|
|
name = cr_string_dup (a_name);
|
|
g_return_if_fail (name);
|
|
|
|
decl = cr_declaration_new (stmt, name, a_expression);
|
|
g_return_if_fail (decl);
|
|
decl->important = a_important;
|
|
stmt->kind.page_rule->decl_list =
|
|
cr_declaration_append (stmt->kind.page_rule->decl_list, decl);
|
|
g_return_if_fail (stmt->kind.page_rule->decl_list);
|
|
}
|
|
|
|
static void
|
|
parse_page_end_page_cb (CRDocHandler * a_this,
|
|
CRString * a_name,
|
|
CRString * a_pseudo_page)
|
|
{
|
|
enum CRStatus status = CR_OK;
|
|
CRStatement *stmt = NULL;
|
|
CRStatement **stmtptr = NULL;
|
|
|
|
stmtptr = &stmt;
|
|
status = cr_doc_handler_get_ctxt (a_this, (gpointer *) stmtptr);
|
|
g_return_if_fail (status == CR_OK && stmt);
|
|
g_return_if_fail (stmt->type == AT_PAGE_RULE_STMT);
|
|
|
|
status = cr_doc_handler_set_result (a_this, stmt);
|
|
g_return_if_fail (status == CR_OK);
|
|
}
|
|
|
|
static void
|
|
parse_at_media_start_media_cb (CRDocHandler * a_this,
|
|
GList * a_media_list,
|
|
CRParsingLocation *a_location)
|
|
{
|
|
enum CRStatus status = CR_OK;
|
|
CRStatement *at_media = NULL;
|
|
GList *media_list = NULL;
|
|
|
|
g_return_if_fail (a_this && a_this->priv);
|
|
|
|
if (a_media_list) {
|
|
/*duplicate media list */
|
|
media_list = cr_utils_dup_glist_of_cr_string
|
|
(a_media_list);
|
|
}
|
|
|
|
g_return_if_fail (media_list);
|
|
|
|
/*make sure cr_statement_new_at_media_rule works in this case. */
|
|
at_media = cr_statement_new_at_media_rule (NULL, NULL, media_list);
|
|
|
|
status = cr_doc_handler_set_ctxt (a_this, at_media);
|
|
g_return_if_fail (status == CR_OK);
|
|
status = cr_doc_handler_set_result (a_this, at_media);
|
|
g_return_if_fail (status == CR_OK);
|
|
}
|
|
|
|
static void
|
|
parse_at_media_unrecoverable_error_cb (CRDocHandler * a_this)
|
|
{
|
|
enum CRStatus status = CR_OK;
|
|
CRStatement *stmt = NULL;
|
|
CRStatement **stmtptr = NULL;
|
|
|
|
g_return_if_fail (a_this);
|
|
|
|
stmtptr = &stmt;
|
|
status = cr_doc_handler_get_result (a_this, (gpointer *) stmtptr);
|
|
if (status != CR_OK) {
|
|
cr_utils_trace_info ("Couldn't get parsing context. "
|
|
"This may lead to some memory leaks.");
|
|
return;
|
|
}
|
|
if (stmt) {
|
|
cr_statement_destroy (stmt);
|
|
stmt = NULL;
|
|
cr_doc_handler_set_ctxt (a_this, NULL);
|
|
cr_doc_handler_set_result (a_this, NULL);
|
|
}
|
|
}
|
|
|
|
static void
|
|
parse_at_media_start_selector_cb (CRDocHandler * a_this,
|
|
CRSelector * a_sellist)
|
|
{
|
|
enum CRStatus status = CR_OK;
|
|
CRStatement *at_media = NULL;
|
|
CRStatement **at_media_ptr = NULL;
|
|
CRStatement *ruleset = NULL;
|
|
|
|
g_return_if_fail (a_this && a_this->priv && a_sellist);
|
|
|
|
at_media_ptr = &at_media;
|
|
status = cr_doc_handler_get_ctxt (a_this, (gpointer *) at_media_ptr);
|
|
g_return_if_fail (status == CR_OK && at_media);
|
|
g_return_if_fail (at_media->type == AT_MEDIA_RULE_STMT);
|
|
ruleset = cr_statement_new_ruleset (NULL, a_sellist, NULL, at_media);
|
|
g_return_if_fail (ruleset);
|
|
status = cr_doc_handler_set_ctxt (a_this, ruleset);
|
|
g_return_if_fail (status == CR_OK);
|
|
}
|
|
|
|
static void
|
|
parse_at_media_property_cb (CRDocHandler * a_this,
|
|
CRString * a_name, CRTerm * a_value,
|
|
gboolean a_important)
|
|
{
|
|
enum CRStatus status = CR_OK;
|
|
|
|
/*
|
|
*the current ruleset stmt, child of the
|
|
*current at-media being parsed.
|
|
*/
|
|
CRStatement *stmt = NULL;
|
|
CRStatement **stmtptr = NULL;
|
|
CRDeclaration *decl = NULL;
|
|
CRString *name = NULL;
|
|
|
|
g_return_if_fail (a_this && a_name);
|
|
|
|
name = cr_string_dup (a_name) ;
|
|
g_return_if_fail (name);
|
|
|
|
stmtptr = &stmt;
|
|
status = cr_doc_handler_get_ctxt (a_this,
|
|
(gpointer *) stmtptr);
|
|
g_return_if_fail (status == CR_OK && stmt);
|
|
g_return_if_fail (stmt->type == RULESET_STMT);
|
|
|
|
decl = cr_declaration_new (stmt, name, a_value);
|
|
g_return_if_fail (decl);
|
|
decl->important = a_important;
|
|
status = cr_statement_ruleset_append_decl (stmt, decl);
|
|
g_return_if_fail (status == CR_OK);
|
|
}
|
|
|
|
static void
|
|
parse_at_media_end_selector_cb (CRDocHandler * a_this,
|
|
CRSelector * a_sellist)
|
|
{
|
|
enum CRStatus status = CR_OK;
|
|
|
|
/*
|
|
*the current ruleset stmt, child of the
|
|
*current at-media being parsed.
|
|
*/
|
|
CRStatement *stmt = NULL;
|
|
CRStatement **stmtptr = NULL;
|
|
|
|
g_return_if_fail (a_this && a_sellist);
|
|
|
|
stmtptr = &stmt;
|
|
status = cr_doc_handler_get_ctxt (a_this, (gpointer *) stmtptr);
|
|
g_return_if_fail (status == CR_OK && stmt
|
|
&& stmt->type == RULESET_STMT);
|
|
g_return_if_fail (stmt->kind.ruleset->parent_media_rule);
|
|
|
|
status = cr_doc_handler_set_ctxt
|
|
(a_this, stmt->kind.ruleset->parent_media_rule);
|
|
g_return_if_fail (status == CR_OK);
|
|
}
|
|
|
|
static void
|
|
parse_at_media_end_media_cb (CRDocHandler * a_this,
|
|
GList * a_media_list)
|
|
{
|
|
enum CRStatus status = CR_OK;
|
|
CRStatement *at_media = NULL;
|
|
CRStatement **at_media_ptr = NULL;
|
|
|
|
g_return_if_fail (a_this && a_this->priv);
|
|
|
|
at_media_ptr = &at_media;
|
|
status = cr_doc_handler_get_ctxt (a_this,
|
|
(gpointer *) at_media_ptr);
|
|
g_return_if_fail (status == CR_OK && at_media);
|
|
status = cr_doc_handler_set_result (a_this, at_media);
|
|
}
|
|
|
|
static void
|
|
parse_ruleset_start_selector_cb (CRDocHandler * a_this,
|
|
CRSelector * a_sellist)
|
|
{
|
|
CRStatement *ruleset = NULL;
|
|
|
|
g_return_if_fail (a_this && a_this->priv && a_sellist);
|
|
|
|
ruleset = cr_statement_new_ruleset (NULL, a_sellist, NULL, NULL);
|
|
g_return_if_fail (ruleset);
|
|
|
|
cr_doc_handler_set_result (a_this, ruleset);
|
|
}
|
|
|
|
static void
|
|
parse_ruleset_unrecoverable_error_cb (CRDocHandler * a_this)
|
|
{
|
|
CRStatement *stmt = NULL;
|
|
CRStatement **stmtptr = NULL;
|
|
enum CRStatus status = CR_OK;
|
|
|
|
stmtptr = &stmt;
|
|
status = cr_doc_handler_get_result (a_this, (gpointer *) stmtptr);
|
|
if (status != CR_OK) {
|
|
cr_utils_trace_info ("Couldn't get parsing context. "
|
|
"This may lead to some memory leaks.");
|
|
return;
|
|
}
|
|
if (stmt) {
|
|
cr_statement_destroy (stmt);
|
|
stmt = NULL;
|
|
cr_doc_handler_set_result (a_this, NULL);
|
|
}
|
|
}
|
|
|
|
static void
|
|
parse_ruleset_property_cb (CRDocHandler * a_this,
|
|
CRString * a_name,
|
|
CRTerm * a_value, gboolean a_important)
|
|
{
|
|
enum CRStatus status = CR_OK;
|
|
CRStatement *ruleset = NULL;
|
|
CRStatement **rulesetptr = NULL;
|
|
CRDeclaration *decl = NULL;
|
|
CRString *stringue = NULL;
|
|
|
|
g_return_if_fail (a_this && a_this->priv && a_name);
|
|
|
|
stringue = cr_string_dup (a_name);
|
|
g_return_if_fail (stringue);
|
|
|
|
rulesetptr = &ruleset;
|
|
status = cr_doc_handler_get_result (a_this, (gpointer *) rulesetptr);
|
|
g_return_if_fail (status == CR_OK
|
|
&& ruleset
|
|
&& ruleset->type == RULESET_STMT);
|
|
|
|
decl = cr_declaration_new (ruleset, stringue, a_value);
|
|
g_return_if_fail (decl);
|
|
decl->important = a_important;
|
|
status = cr_statement_ruleset_append_decl (ruleset, decl);
|
|
g_return_if_fail (status == CR_OK);
|
|
}
|
|
|
|
static void
|
|
parse_ruleset_end_selector_cb (CRDocHandler * a_this,
|
|
CRSelector * a_sellist)
|
|
{
|
|
CRStatement *result = NULL;
|
|
CRStatement **resultptr = NULL;
|
|
enum CRStatus status = CR_OK;
|
|
|
|
g_return_if_fail (a_this && a_sellist);
|
|
|
|
resultptr = &result;
|
|
status = cr_doc_handler_get_result (a_this, (gpointer *) resultptr);
|
|
|
|
g_return_if_fail (status == CR_OK
|
|
&& result
|
|
&& result->type == RULESET_STMT);
|
|
}
|
|
|
|
static void
|
|
cr_statement_clear (CRStatement * a_this)
|
|
{
|
|
g_return_if_fail (a_this);
|
|
|
|
switch (a_this->type) {
|
|
case AT_RULE_STMT:
|
|
break;
|
|
case RULESET_STMT:
|
|
if (!a_this->kind.ruleset)
|
|
return;
|
|
if (a_this->kind.ruleset->sel_list) {
|
|
cr_selector_unref (a_this->kind.ruleset->sel_list);
|
|
a_this->kind.ruleset->sel_list = NULL;
|
|
}
|
|
if (a_this->kind.ruleset->decl_list) {
|
|
cr_declaration_destroy
|
|
(a_this->kind.ruleset->decl_list);
|
|
a_this->kind.ruleset->decl_list = NULL;
|
|
}
|
|
g_free (a_this->kind.ruleset);
|
|
a_this->kind.ruleset = NULL;
|
|
break;
|
|
|
|
case AT_IMPORT_RULE_STMT:
|
|
if (!a_this->kind.import_rule)
|
|
return;
|
|
if (a_this->kind.import_rule->url) {
|
|
cr_string_destroy
|
|
(a_this->kind.import_rule->url) ;
|
|
a_this->kind.import_rule->url = NULL;
|
|
}
|
|
g_free (a_this->kind.import_rule);
|
|
a_this->kind.import_rule = NULL;
|
|
break;
|
|
|
|
case AT_MEDIA_RULE_STMT:
|
|
if (!a_this->kind.media_rule)
|
|
return;
|
|
if (a_this->kind.media_rule->rulesets) {
|
|
cr_statement_destroy
|
|
(a_this->kind.media_rule->rulesets);
|
|
a_this->kind.media_rule->rulesets = NULL;
|
|
}
|
|
if (a_this->kind.media_rule->media_list) {
|
|
GList *cur = NULL;
|
|
|
|
for (cur = a_this->kind.media_rule->media_list;
|
|
cur; cur = cur->next) {
|
|
if (cur->data) {
|
|
cr_string_destroy ((CRString *) cur->data);
|
|
cur->data = NULL;
|
|
}
|
|
|
|
}
|
|
g_list_free (a_this->kind.media_rule->media_list);
|
|
a_this->kind.media_rule->media_list = NULL;
|
|
}
|
|
g_free (a_this->kind.media_rule);
|
|
a_this->kind.media_rule = NULL;
|
|
break;
|
|
|
|
case AT_PAGE_RULE_STMT:
|
|
if (!a_this->kind.page_rule)
|
|
return;
|
|
|
|
if (a_this->kind.page_rule->decl_list) {
|
|
cr_declaration_destroy
|
|
(a_this->kind.page_rule->decl_list);
|
|
a_this->kind.page_rule->decl_list = NULL;
|
|
}
|
|
if (a_this->kind.page_rule->name) {
|
|
cr_string_destroy
|
|
(a_this->kind.page_rule->name);
|
|
a_this->kind.page_rule->name = NULL;
|
|
}
|
|
if (a_this->kind.page_rule->pseudo) {
|
|
cr_string_destroy
|
|
(a_this->kind.page_rule->pseudo);
|
|
a_this->kind.page_rule->pseudo = NULL;
|
|
}
|
|
g_free (a_this->kind.page_rule);
|
|
a_this->kind.page_rule = NULL;
|
|
break;
|
|
|
|
case AT_CHARSET_RULE_STMT:
|
|
if (!a_this->kind.charset_rule)
|
|
return;
|
|
|
|
if (a_this->kind.charset_rule->charset) {
|
|
cr_string_destroy
|
|
(a_this->kind.charset_rule->charset);
|
|
a_this->kind.charset_rule->charset = NULL;
|
|
}
|
|
g_free (a_this->kind.charset_rule);
|
|
a_this->kind.charset_rule = NULL;
|
|
break;
|
|
|
|
case AT_FONT_FACE_RULE_STMT:
|
|
if (!a_this->kind.font_face_rule)
|
|
return;
|
|
|
|
if (a_this->kind.font_face_rule->decl_list) {
|
|
cr_declaration_unref
|
|
(a_this->kind.font_face_rule->decl_list);
|
|
a_this->kind.font_face_rule->decl_list = NULL;
|
|
}
|
|
g_free (a_this->kind.font_face_rule);
|
|
a_this->kind.font_face_rule = NULL;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* cr_statement_ruleset_to_string:
|
|
*
|
|
*@a_this: the current instance of #CRStatement
|
|
*@a_indent: the number of whitespace to use for indentation
|
|
*
|
|
*Serializes the ruleset statement into a string
|
|
*
|
|
*Returns the newly allocated serialised string. Must be freed
|
|
*by the caller, using g_free().
|
|
*/
|
|
static gchar *
|
|
cr_statement_ruleset_to_string (CRStatement const * a_this, glong a_indent)
|
|
{
|
|
GString *stringue = NULL;
|
|
gchar *tmp_str = NULL,
|
|
*result = NULL;
|
|
|
|
g_return_val_if_fail (a_this && a_this->type == RULESET_STMT, NULL);
|
|
|
|
stringue = g_string_new (NULL);
|
|
|
|
if (a_this->kind.ruleset->sel_list) {
|
|
if (a_indent)
|
|
cr_utils_dump_n_chars2 (' ', stringue, a_indent);
|
|
|
|
tmp_str =
|
|
(gchar *) cr_selector_to_string (a_this->kind.ruleset->
|
|
sel_list);
|
|
if (tmp_str) {
|
|
g_string_append (stringue, tmp_str);
|
|
g_free (tmp_str);
|
|
tmp_str = NULL;
|
|
}
|
|
}
|
|
g_string_append (stringue, " {\n");
|
|
if (a_this->kind.ruleset->decl_list) {
|
|
tmp_str = (gchar *) cr_declaration_list_to_string2
|
|
(a_this->kind.ruleset->decl_list,
|
|
a_indent + DECLARATION_INDENT_NB, TRUE);
|
|
if (tmp_str) {
|
|
g_string_append (stringue, tmp_str);
|
|
g_free (tmp_str);
|
|
tmp_str = NULL;
|
|
}
|
|
g_string_append (stringue, "\n");
|
|
cr_utils_dump_n_chars2 (' ', stringue, a_indent);
|
|
}
|
|
g_string_append (stringue, "}");
|
|
result = stringue->str;
|
|
|
|
if (stringue) {
|
|
g_string_free (stringue, FALSE);
|
|
stringue = NULL;
|
|
}
|
|
if (tmp_str) {
|
|
g_free (tmp_str);
|
|
tmp_str = NULL;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
|
|
/**
|
|
* cr_statement_font_face_rule_to_string:
|
|
*
|
|
*@a_this: the current instance of #CRStatement to consider
|
|
*It must be a font face rule statement.
|
|
*@a_indent: the number of white spaces of indentation.
|
|
*
|
|
*Serializes a font face rule statement into a string.
|
|
*
|
|
*Returns the serialized string. Must be deallocated by the caller
|
|
*using g_free().
|
|
*/
|
|
static gchar *
|
|
cr_statement_font_face_rule_to_string (CRStatement const * a_this,
|
|
glong a_indent)
|
|
{
|
|
gchar *result = NULL, *tmp_str = NULL ;
|
|
GString *stringue = NULL ;
|
|
|
|
g_return_val_if_fail (a_this
|
|
&& a_this->type == AT_FONT_FACE_RULE_STMT,
|
|
NULL);
|
|
|
|
if (a_this->kind.font_face_rule->decl_list) {
|
|
stringue = g_string_new (NULL) ;
|
|
g_return_val_if_fail (stringue, NULL) ;
|
|
if (a_indent)
|
|
cr_utils_dump_n_chars2 (' ', stringue,
|
|
a_indent);
|
|
g_string_append (stringue, "@font-face {\n");
|
|
tmp_str = (gchar *) cr_declaration_list_to_string2
|
|
(a_this->kind.font_face_rule->decl_list,
|
|
a_indent + DECLARATION_INDENT_NB, TRUE) ;
|
|
if (tmp_str) {
|
|
g_string_append (stringue,
|
|
tmp_str) ;
|
|
g_free (tmp_str) ;
|
|
tmp_str = NULL ;
|
|
}
|
|
g_string_append (stringue, "\n}");
|
|
}
|
|
if (stringue) {
|
|
result = stringue->str ;
|
|
g_string_free (stringue, FALSE) ;
|
|
stringue = NULL ;
|
|
}
|
|
return result ;
|
|
}
|
|
|
|
|
|
/**
|
|
* cr_statement_charset_to_string:
|
|
*
|
|
*Serialises an \@charset statement into a string.
|
|
*@a_this: the statement to serialize.
|
|
*@a_indent: the number of indentation spaces
|
|
*
|
|
*Returns the serialized charset statement. Must be
|
|
*freed by the caller using g_free().
|
|
*/
|
|
static gchar *
|
|
cr_statement_charset_to_string (CRStatement const *a_this,
|
|
gulong a_indent)
|
|
{
|
|
gchar *str = NULL ;
|
|
GString *stringue = NULL ;
|
|
|
|
g_return_val_if_fail (a_this
|
|
&& a_this->type == AT_CHARSET_RULE_STMT,
|
|
NULL) ;
|
|
|
|
if (a_this->kind.charset_rule
|
|
&& a_this->kind.charset_rule->charset
|
|
&& a_this->kind.charset_rule->charset->stryng
|
|
&& a_this->kind.charset_rule->charset->stryng->str) {
|
|
str = g_strndup (a_this->kind.charset_rule->charset->stryng->str,
|
|
a_this->kind.charset_rule->charset->stryng->len);
|
|
g_return_val_if_fail (str, NULL);
|
|
stringue = g_string_new (NULL) ;
|
|
g_return_val_if_fail (stringue, NULL) ;
|
|
cr_utils_dump_n_chars2 (' ', stringue, a_indent);
|
|
g_string_append_printf (stringue,
|
|
"@charset \"%s\" ;", str);
|
|
if (str) {
|
|
g_free (str);
|
|
str = NULL;
|
|
}
|
|
}
|
|
if (stringue) {
|
|
str = stringue->str ;
|
|
g_string_free (stringue, FALSE) ;
|
|
}
|
|
return str ;
|
|
}
|
|
|
|
|
|
/**
|
|
* cr_statement_at_page_rule_to_string:
|
|
*
|
|
*Serialises the at page rule statement into a string
|
|
*@a_this: the current instance of #CRStatement. Must
|
|
*be an "\@page" rule statement.
|
|
*
|
|
*Returns the serialized string. Must be freed by the caller
|
|
*/
|
|
static gchar *
|
|
cr_statement_at_page_rule_to_string (CRStatement const *a_this,
|
|
gulong a_indent)
|
|
{
|
|
GString *stringue = NULL;
|
|
gchar *result = NULL ;
|
|
|
|
stringue = g_string_new (NULL) ;
|
|
|
|
cr_utils_dump_n_chars2 (' ', stringue, a_indent) ;
|
|
g_string_append (stringue, "@page");
|
|
if (a_this->kind.page_rule->name
|
|
&& a_this->kind.page_rule->name->stryng) {
|
|
g_string_append_printf
|
|
(stringue, " %s",
|
|
a_this->kind.page_rule->name->stryng->str) ;
|
|
} else {
|
|
g_string_append (stringue, " ");
|
|
}
|
|
if (a_this->kind.page_rule->pseudo
|
|
&& a_this->kind.page_rule->pseudo->stryng) {
|
|
g_string_append_printf
|
|
(stringue, " :%s",
|
|
a_this->kind.page_rule->pseudo->stryng->str) ;
|
|
}
|
|
if (a_this->kind.page_rule->decl_list) {
|
|
gchar *str = NULL ;
|
|
g_string_append (stringue, " {\n");
|
|
str = (gchar *) cr_declaration_list_to_string2
|
|
(a_this->kind.page_rule->decl_list,
|
|
a_indent + DECLARATION_INDENT_NB, TRUE) ;
|
|
if (str) {
|
|
g_string_append (stringue, str) ;
|
|
g_free (str) ;
|
|
str = NULL ;
|
|
}
|
|
g_string_append (stringue, "\n}\n");
|
|
}
|
|
result = stringue->str ;
|
|
g_string_free (stringue, FALSE) ;
|
|
stringue = NULL ;
|
|
return result ;
|
|
}
|
|
|
|
|
|
/**
|
|
*Serializes an \@media statement.
|
|
*@param a_this the current instance of #CRStatement
|
|
*@param a_indent the number of spaces of indentation.
|
|
*@return the serialized \@media statement. Must be freed
|
|
*by the caller using g_free().
|
|
*/
|
|
static gchar *
|
|
cr_statement_media_rule_to_string (CRStatement const *a_this,
|
|
gulong a_indent)
|
|
{
|
|
gchar *str = NULL ;
|
|
GString *stringue = NULL ;
|
|
GList const *cur = NULL;
|
|
|
|
g_return_val_if_fail (a_this->type == AT_MEDIA_RULE_STMT,
|
|
NULL);
|
|
|
|
if (a_this->kind.media_rule) {
|
|
stringue = g_string_new (NULL) ;
|
|
cr_utils_dump_n_chars2 (' ', stringue, a_indent);
|
|
g_string_append (stringue, "@media");
|
|
|
|
for (cur = a_this->kind.media_rule->media_list; cur;
|
|
cur = cur->next) {
|
|
if (cur->data) {
|
|
gchar *str2 = cr_string_dup2
|
|
((CRString const *) cur->data);
|
|
|
|
if (str2) {
|
|
if (cur->prev) {
|
|
g_string_append
|
|
(stringue,
|
|
",");
|
|
}
|
|
g_string_append_printf
|
|
(stringue,
|
|
" %s", str2);
|
|
g_free (str2);
|
|
str2 = NULL;
|
|
}
|
|
}
|
|
}
|
|
g_string_append (stringue, " {\n");
|
|
str = cr_statement_list_to_string
|
|
(a_this->kind.media_rule->rulesets,
|
|
a_indent + DECLARATION_INDENT_NB) ;
|
|
if (str) {
|
|
g_string_append (stringue, str) ;
|
|
g_free (str) ;
|
|
str = NULL ;
|
|
}
|
|
g_string_append (stringue, "\n}");
|
|
}
|
|
if (stringue) {
|
|
str = stringue->str ;
|
|
g_string_free (stringue, FALSE) ;
|
|
}
|
|
return str ;
|
|
}
|
|
|
|
|
|
static gchar *
|
|
cr_statement_import_rule_to_string (CRStatement const *a_this,
|
|
gulong a_indent)
|
|
{
|
|
GString *stringue = NULL ;
|
|
gchar *str = NULL;
|
|
|
|
g_return_val_if_fail (a_this
|
|
&& a_this->type == AT_IMPORT_RULE_STMT
|
|
&& a_this->kind.import_rule,
|
|
NULL) ;
|
|
|
|
if (a_this->kind.import_rule->url
|
|
&& a_this->kind.import_rule->url->stryng) {
|
|
stringue = g_string_new (NULL) ;
|
|
g_return_val_if_fail (stringue, NULL) ;
|
|
str = g_strndup (a_this->kind.import_rule->url->stryng->str,
|
|
a_this->kind.import_rule->url->stryng->len);
|
|
cr_utils_dump_n_chars2 (' ', stringue, a_indent);
|
|
if (str) {
|
|
g_string_append_printf (stringue,
|
|
"@import url(\"%s\")",
|
|
str);
|
|
g_free (str);
|
|
str = NULL ;
|
|
} else /*there is no url, so no import rule, get out! */
|
|
return NULL;
|
|
|
|
if (a_this->kind.import_rule->media_list) {
|
|
GList const *cur = NULL;
|
|
|
|
for (cur = a_this->kind.import_rule->media_list;
|
|
cur; cur = cur->next) {
|
|
if (cur->data) {
|
|
CRString const *crstr = cur->data;
|
|
|
|
if (cur->prev) {
|
|
g_string_append
|
|
(stringue, ", ");
|
|
}
|
|
if (crstr
|
|
&& crstr->stryng
|
|
&& crstr->stryng->str) {
|
|
g_string_append_len
|
|
(stringue,
|
|
crstr->stryng->str,
|
|
crstr->stryng->len) ;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
g_string_append (stringue, " ;");
|
|
}
|
|
if (stringue) {
|
|
str = stringue->str ;
|
|
g_string_free (stringue, FALSE) ;
|
|
stringue = NULL ;
|
|
}
|
|
return str ;
|
|
}
|
|
|
|
|
|
/*******************
|
|
*public functions
|
|
******************/
|
|
|
|
/**
|
|
* cr_statement_does_buf_parses_against_core:
|
|
*
|
|
*@a_buf: the buffer to parse.
|
|
*@a_encoding: the character encoding of a_buf.
|
|
*
|
|
*Tries to parse a buffer and says whether if the content of the buffer
|
|
*is a css statement as defined by the "Core CSS Grammar" (chapter 4 of the
|
|
*css spec) or not.
|
|
*
|
|
*Returns TRUE if the buffer parses against the core grammar, false otherwise.
|
|
*/
|
|
gboolean
|
|
cr_statement_does_buf_parses_against_core (const guchar * a_buf,
|
|
enum CREncoding a_encoding)
|
|
{
|
|
CRParser *parser = NULL;
|
|
enum CRStatus status = CR_OK;
|
|
gboolean result = FALSE;
|
|
|
|
parser = cr_parser_new_from_buf ((guchar*)a_buf, strlen ((const char *) a_buf),
|
|
a_encoding, FALSE);
|
|
g_return_val_if_fail (parser, FALSE);
|
|
|
|
status = cr_parser_set_use_core_grammar (parser, TRUE);
|
|
if (status != CR_OK) {
|
|
goto cleanup;
|
|
}
|
|
|
|
status = cr_parser_parse_statement_core (parser);
|
|
if (status == CR_OK) {
|
|
result = TRUE;
|
|
}
|
|
|
|
cleanup:
|
|
if (parser) {
|
|
cr_parser_destroy (parser);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* cr_statement_parse_from_buf:
|
|
*
|
|
*@a_buf: the buffer to parse.
|
|
*@a_encoding: the character encoding of a_buf.
|
|
*
|
|
*Parses a buffer that contains a css statement and returns
|
|
*an instance of #CRStatement in case of successful parsing.
|
|
*TODO: at support of "\@import" rules.
|
|
*
|
|
*Returns the newly built instance of #CRStatement in case
|
|
*of successful parsing, NULL otherwise.
|
|
*/
|
|
CRStatement *
|
|
cr_statement_parse_from_buf (const guchar * a_buf, enum CREncoding a_encoding)
|
|
{
|
|
CRStatement *result = NULL;
|
|
|
|
/*
|
|
*The strategy of this function is "brute force".
|
|
*It tries to parse all the types of CRStatement it knows about.
|
|
*I could do this a smarter way but I don't have the time now.
|
|
*I think I will revisit this when time of performances and
|
|
*pull based incremental parsing comes.
|
|
*/
|
|
|
|
result = cr_statement_ruleset_parse_from_buf (a_buf, a_encoding);
|
|
if (!result) {
|
|
result = cr_statement_at_charset_rule_parse_from_buf
|
|
(a_buf, a_encoding);
|
|
} else {
|
|
goto out;
|
|
}
|
|
|
|
if (!result) {
|
|
result = cr_statement_at_media_rule_parse_from_buf
|
|
(a_buf, a_encoding);
|
|
} else {
|
|
goto out;
|
|
}
|
|
|
|
if (!result) {
|
|
result = cr_statement_at_charset_rule_parse_from_buf
|
|
(a_buf, a_encoding);
|
|
} else {
|
|
goto out;
|
|
}
|
|
|
|
if (!result) {
|
|
result = cr_statement_font_face_rule_parse_from_buf
|
|
(a_buf, a_encoding);
|
|
|
|
} else {
|
|
goto out;
|
|
}
|
|
|
|
if (!result) {
|
|
result = cr_statement_at_page_rule_parse_from_buf
|
|
(a_buf, a_encoding);
|
|
} else {
|
|
goto out;
|
|
}
|
|
|
|
if (!result) {
|
|
result = cr_statement_at_import_rule_parse_from_buf
|
|
(a_buf, a_encoding);
|
|
} else {
|
|
goto out;
|
|
}
|
|
|
|
out:
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* cr_statement_ruleset_parse_from_buf:
|
|
*
|
|
*@a_buf: the buffer to parse.
|
|
*@a_enc: the character encoding of a_buf.
|
|
*
|
|
*Parses a buffer that contains a ruleset statement an instantiates
|
|
*a #CRStatement of type RULESET_STMT.
|
|
*
|
|
*Returns the newly built instance of #CRStatement in case of successful parsing,
|
|
*NULL otherwise.
|
|
*/
|
|
CRStatement *
|
|
cr_statement_ruleset_parse_from_buf (const guchar * a_buf,
|
|
enum CREncoding a_enc)
|
|
{
|
|
enum CRStatus status = CR_OK;
|
|
CRStatement *result = NULL;
|
|
CRStatement **resultptr = NULL;
|
|
CRParser *parser = NULL;
|
|
CRDocHandler *sac_handler = NULL;
|
|
|
|
g_return_val_if_fail (a_buf, NULL);
|
|
|
|
parser = cr_parser_new_from_buf ((guchar*)a_buf, strlen ((const char *) a_buf),
|
|
a_enc, FALSE);
|
|
|
|
g_return_val_if_fail (parser, NULL);
|
|
|
|
sac_handler = cr_doc_handler_new ();
|
|
g_return_val_if_fail (parser, NULL);
|
|
|
|
sac_handler->start_selector = parse_ruleset_start_selector_cb;
|
|
sac_handler->end_selector = parse_ruleset_end_selector_cb;
|
|
sac_handler->property = parse_ruleset_property_cb;
|
|
sac_handler->unrecoverable_error =
|
|
parse_ruleset_unrecoverable_error_cb;
|
|
|
|
cr_parser_set_sac_handler (parser, sac_handler);
|
|
cr_parser_try_to_skip_spaces_and_comments (parser);
|
|
status = cr_parser_parse_ruleset (parser);
|
|
if (status != CR_OK) {
|
|
goto cleanup;
|
|
}
|
|
|
|
resultptr = &result;
|
|
status = cr_doc_handler_get_result (sac_handler,
|
|
(gpointer *) resultptr);
|
|
if (!((status == CR_OK) && result)) {
|
|
if (result) {
|
|
cr_statement_destroy (result);
|
|
result = NULL;
|
|
}
|
|
}
|
|
|
|
cleanup:
|
|
if (parser) {
|
|
cr_parser_destroy (parser);
|
|
parser = NULL;
|
|
sac_handler = NULL ;
|
|
}
|
|
if (sac_handler) {
|
|
cr_doc_handler_unref (sac_handler);
|
|
sac_handler = NULL;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* cr_statement_new_ruleset:
|
|
*
|
|
*@a_sel_list: the list of #CRSimpleSel (selectors)
|
|
*the rule applies to.
|
|
*@a_decl_list: the list of instances of #CRDeclaration
|
|
*that composes the ruleset.
|
|
*@a_media_types: a list of instances of GString that
|
|
*describe the media list this ruleset applies to.
|
|
*
|
|
*Creates a new instance of #CRStatement of type
|
|
*#CRRulSet.
|
|
*
|
|
*Returns the new instance of #CRStatement or NULL if something
|
|
*went wrong.
|
|
*/
|
|
CRStatement *
|
|
cr_statement_new_ruleset (CRStyleSheet * a_sheet,
|
|
CRSelector * a_sel_list,
|
|
CRDeclaration * a_decl_list,
|
|
CRStatement * a_parent_media_rule)
|
|
{
|
|
CRStatement *result = NULL;
|
|
|
|
g_return_val_if_fail (a_sel_list, NULL);
|
|
|
|
if (a_parent_media_rule) {
|
|
g_return_val_if_fail
|
|
(a_parent_media_rule->type == AT_MEDIA_RULE_STMT,
|
|
NULL);
|
|
g_return_val_if_fail (a_parent_media_rule->kind.media_rule,
|
|
NULL);
|
|
}
|
|
|
|
result = g_try_malloc (sizeof (CRStatement));
|
|
|
|
if (!result) {
|
|
cr_utils_trace_info ("Out of memory");
|
|
return NULL;
|
|
}
|
|
|
|
memset (result, 0, sizeof (CRStatement));
|
|
result->type = RULESET_STMT;
|
|
result->kind.ruleset = g_try_malloc (sizeof (CRRuleSet));
|
|
|
|
if (!result->kind.ruleset) {
|
|
cr_utils_trace_info ("Out of memory");
|
|
if (result)
|
|
g_free (result);
|
|
return NULL;
|
|
}
|
|
|
|
memset (result->kind.ruleset, 0, sizeof (CRRuleSet));
|
|
result->kind.ruleset->sel_list = a_sel_list;
|
|
if (a_sel_list)
|
|
cr_selector_ref (a_sel_list);
|
|
result->kind.ruleset->decl_list = a_decl_list;
|
|
|
|
if (a_parent_media_rule) {
|
|
result->kind.ruleset->parent_media_rule = a_parent_media_rule;
|
|
a_parent_media_rule->kind.media_rule->rulesets =
|
|
cr_statement_append
|
|
(a_parent_media_rule->kind.media_rule->rulesets,
|
|
result);
|
|
}
|
|
|
|
cr_statement_set_parent_sheet (result, a_sheet);
|
|
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* cr_statement_at_media_rule_parse_from_buf:
|
|
*
|
|
*@a_buf: the input to parse.
|
|
*@a_enc: the encoding of the buffer.
|
|
*
|
|
*Parses a buffer that contains an "\@media" declaration
|
|
*and builds an \@media css statement.
|
|
*
|
|
*Returns the \@media statement, or NULL if the buffer could not
|
|
*be successfully parsed.
|
|
*/
|
|
CRStatement *
|
|
cr_statement_at_media_rule_parse_from_buf (const guchar * a_buf,
|
|
enum CREncoding a_enc)
|
|
{
|
|
CRParser *parser = NULL;
|
|
CRStatement *result = NULL;
|
|
CRStatement **resultptr = NULL;
|
|
CRDocHandler *sac_handler = NULL;
|
|
enum CRStatus status = CR_OK;
|
|
|
|
parser = cr_parser_new_from_buf ((guchar*)a_buf, strlen ((const char *) a_buf),
|
|
a_enc, FALSE);
|
|
if (!parser) {
|
|
cr_utils_trace_info ("Instantiation of the parser failed");
|
|
goto cleanup;
|
|
}
|
|
|
|
sac_handler = cr_doc_handler_new ();
|
|
if (!sac_handler) {
|
|
cr_utils_trace_info
|
|
("Instantiation of the sac handler failed");
|
|
goto cleanup;
|
|
}
|
|
|
|
sac_handler->start_media = parse_at_media_start_media_cb;
|
|
sac_handler->start_selector = parse_at_media_start_selector_cb;
|
|
sac_handler->property = parse_at_media_property_cb;
|
|
sac_handler->end_selector = parse_at_media_end_selector_cb;
|
|
sac_handler->end_media = parse_at_media_end_media_cb;
|
|
sac_handler->unrecoverable_error =
|
|
parse_at_media_unrecoverable_error_cb;
|
|
|
|
status = cr_parser_set_sac_handler (parser, sac_handler);
|
|
if (status != CR_OK)
|
|
goto cleanup;
|
|
|
|
status = cr_parser_try_to_skip_spaces_and_comments (parser);
|
|
if (status != CR_OK)
|
|
goto cleanup;
|
|
|
|
status = cr_parser_parse_media (parser);
|
|
if (status != CR_OK)
|
|
goto cleanup;
|
|
|
|
resultptr = &result;
|
|
status = cr_doc_handler_get_result (sac_handler,
|
|
(gpointer *) resultptr);
|
|
if (status != CR_OK)
|
|
goto cleanup;
|
|
|
|
cleanup:
|
|
|
|
if (parser) {
|
|
cr_parser_destroy (parser);
|
|
parser = NULL;
|
|
sac_handler = NULL ;
|
|
}
|
|
if (sac_handler) {
|
|
cr_doc_handler_unref (sac_handler);
|
|
sac_handler = NULL;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* cr_statement_new_at_media_rule:
|
|
*
|
|
*@a_ruleset: the ruleset statements contained
|
|
*in the \@media rule.
|
|
*@a_media: the media string list. A list of GString pointers.
|
|
*
|
|
*Instantiates an instance of #CRStatement of type
|
|
*AT_MEDIA_RULE_STMT (\@media ruleset).
|
|
*
|
|
*/
|
|
CRStatement *
|
|
cr_statement_new_at_media_rule (CRStyleSheet * a_sheet,
|
|
CRStatement * a_rulesets, GList * a_media)
|
|
{
|
|
CRStatement *result = NULL,
|
|
*cur = NULL;
|
|
|
|
if (a_rulesets)
|
|
g_return_val_if_fail (a_rulesets->type == RULESET_STMT, NULL);
|
|
|
|
result = g_try_malloc (sizeof (CRStatement));
|
|
|
|
if (!result) {
|
|
cr_utils_trace_info ("Out of memory");
|
|
return NULL;
|
|
}
|
|
|
|
memset (result, 0, sizeof (CRStatement));
|
|
result->type = AT_MEDIA_RULE_STMT;
|
|
|
|
result->kind.media_rule = g_try_malloc (sizeof (CRAtMediaRule));
|
|
if (!result->kind.media_rule) {
|
|
cr_utils_trace_info ("Out of memory");
|
|
g_free (result);
|
|
return NULL;
|
|
}
|
|
memset (result->kind.media_rule, 0, sizeof (CRAtMediaRule));
|
|
result->kind.media_rule->rulesets = a_rulesets;
|
|
for (cur = a_rulesets; cur; cur = cur->next) {
|
|
if (cur->type != RULESET_STMT || !cur->kind.ruleset) {
|
|
cr_utils_trace_info ("Bad parameter a_rulesets. "
|
|
"It should be a list of "
|
|
"correct ruleset statement only !");
|
|
goto error;
|
|
}
|
|
cur->kind.ruleset->parent_media_rule = result;
|
|
}
|
|
|
|
result->kind.media_rule->media_list = a_media;
|
|
if (a_sheet) {
|
|
cr_statement_set_parent_sheet (result, a_sheet);
|
|
}
|
|
|
|
return result;
|
|
|
|
error:
|
|
return NULL;
|
|
}
|
|
|
|
/**
|
|
* cr_statement_new_at_import_rule:
|
|
*
|
|
*@a_url: the url to connect to the get the file
|
|
*to be imported.
|
|
*@a_sheet: the imported parsed stylesheet.
|
|
*
|
|
*Creates a new instance of #CRStatment of type
|
|
*#CRAtImportRule.
|
|
*
|
|
*Returns the newly built instance of #CRStatement.
|
|
*/
|
|
CRStatement *
|
|
cr_statement_new_at_import_rule (CRStyleSheet * a_container_sheet,
|
|
CRString * a_url,
|
|
GList * a_media_list,
|
|
CRStyleSheet * a_imported_sheet)
|
|
{
|
|
CRStatement *result = NULL;
|
|
|
|
result = g_try_malloc (sizeof (CRStatement));
|
|
|
|
if (!result) {
|
|
cr_utils_trace_info ("Out of memory");
|
|
return NULL;
|
|
}
|
|
|
|
memset (result, 0, sizeof (CRStatement));
|
|
result->type = AT_IMPORT_RULE_STMT;
|
|
|
|
result->kind.import_rule = g_try_malloc (sizeof (CRAtImportRule));
|
|
|
|
if (!result->kind.import_rule) {
|
|
cr_utils_trace_info ("Out of memory");
|
|
g_free (result);
|
|
return NULL;
|
|
}
|
|
|
|
memset (result->kind.import_rule, 0, sizeof (CRAtImportRule));
|
|
result->kind.import_rule->url = a_url;
|
|
result->kind.import_rule->media_list = a_media_list;
|
|
result->kind.import_rule->sheet = a_imported_sheet;
|
|
if (a_container_sheet)
|
|
cr_statement_set_parent_sheet (result, a_container_sheet);
|
|
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* cr_statement_at_import_rule_parse_from_buf:
|
|
*
|
|
*@a_buf: the buffer to parse.
|
|
*@a_encoding: the encoding of a_buf.
|
|
*
|
|
*Parses a buffer that contains an "\@import" rule and
|
|
*instantiate a #CRStatement of type AT_IMPORT_RULE_STMT
|
|
*
|
|
*Returns the newly built instance of #CRStatement in case of
|
|
*a successful parsing, NULL otherwise.
|
|
*/
|
|
CRStatement *
|
|
cr_statement_at_import_rule_parse_from_buf (const guchar * a_buf,
|
|
enum CREncoding a_encoding)
|
|
{
|
|
enum CRStatus status = CR_OK;
|
|
CRParser *parser = NULL;
|
|
CRStatement *result = NULL;
|
|
GList *media_list = NULL;
|
|
CRString *import_string = NULL;
|
|
CRParsingLocation location = {0} ;
|
|
|
|
parser = cr_parser_new_from_buf ((guchar*)a_buf, strlen ((const char *) a_buf),
|
|
a_encoding, FALSE);
|
|
if (!parser) {
|
|
cr_utils_trace_info ("Instantiation of parser failed.");
|
|
goto cleanup;
|
|
}
|
|
|
|
status = cr_parser_try_to_skip_spaces_and_comments (parser);
|
|
if (status != CR_OK)
|
|
goto cleanup;
|
|
|
|
status = cr_parser_parse_import (parser,
|
|
&media_list,
|
|
&import_string,
|
|
&location);
|
|
if (status != CR_OK || !import_string)
|
|
goto cleanup;
|
|
|
|
result = cr_statement_new_at_import_rule (NULL, import_string,
|
|
media_list, NULL);
|
|
if (result) {
|
|
cr_parsing_location_copy (&result->location,
|
|
&location) ;
|
|
import_string = NULL;
|
|
media_list = NULL;
|
|
}
|
|
|
|
cleanup:
|
|
if (parser) {
|
|
cr_parser_destroy (parser);
|
|
parser = NULL;
|
|
}
|
|
if (media_list) {
|
|
for (; media_list;
|
|
media_list = g_list_next (media_list)) {
|
|
if (media_list->data) {
|
|
cr_string_destroy ((CRString*)media_list->data);
|
|
media_list->data = NULL;
|
|
}
|
|
}
|
|
g_list_free (media_list);
|
|
media_list = NULL;
|
|
}
|
|
if (import_string) {
|
|
cr_string_destroy (import_string);
|
|
import_string = NULL;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* cr_statement_new_at_page_rule:
|
|
*
|
|
*@a_decl_list: a list of instances of #CRDeclarations
|
|
*which is actually the list of declarations that applies to
|
|
*this page rule.
|
|
*@a_selector: the page rule selector.
|
|
*
|
|
*Creates a new instance of #CRStatement of type
|
|
*#CRAtPageRule.
|
|
*
|
|
*Returns the newly built instance of #CRStatement or NULL
|
|
*in case of error.
|
|
*/
|
|
CRStatement *
|
|
cr_statement_new_at_page_rule (CRStyleSheet * a_sheet,
|
|
CRDeclaration * a_decl_list,
|
|
CRString * a_name, CRString * a_pseudo)
|
|
{
|
|
CRStatement *result = NULL;
|
|
|
|
result = g_try_malloc (sizeof (CRStatement));
|
|
|
|
if (!result) {
|
|
cr_utils_trace_info ("Out of memory");
|
|
return NULL;
|
|
}
|
|
|
|
memset (result, 0, sizeof (CRStatement));
|
|
result->type = AT_PAGE_RULE_STMT;
|
|
|
|
result->kind.page_rule = g_try_malloc (sizeof (CRAtPageRule));
|
|
|
|
if (!result->kind.page_rule) {
|
|
cr_utils_trace_info ("Out of memory");
|
|
g_free (result);
|
|
return NULL;
|
|
}
|
|
|
|
memset (result->kind.page_rule, 0, sizeof (CRAtPageRule));
|
|
if (a_decl_list) {
|
|
result->kind.page_rule->decl_list = a_decl_list;
|
|
cr_declaration_ref (a_decl_list);
|
|
}
|
|
result->kind.page_rule->name = a_name;
|
|
result->kind.page_rule->pseudo = a_pseudo;
|
|
if (a_sheet)
|
|
cr_statement_set_parent_sheet (result, a_sheet);
|
|
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* cr_statement_at_page_rule_parse_from_buf:
|
|
*
|
|
*@a_buf: the character buffer to parse.
|
|
*@a_encoding: the character encoding of a_buf.
|
|
*
|
|
*Parses a buffer that contains an "\@page" production and,
|
|
*if the parsing succeeds, builds the page statement.
|
|
*
|
|
*Returns the newly built at page statement in case of successful parsing,
|
|
*NULL otherwise.
|
|
*/
|
|
CRStatement *
|
|
cr_statement_at_page_rule_parse_from_buf (const guchar * a_buf,
|
|
enum CREncoding a_encoding)
|
|
{
|
|
enum CRStatus status = CR_OK;
|
|
CRParser *parser = NULL;
|
|
CRDocHandler *sac_handler = NULL;
|
|
CRStatement *result = NULL;
|
|
CRStatement **resultptr = NULL;
|
|
|
|
g_return_val_if_fail (a_buf, NULL);
|
|
|
|
parser = cr_parser_new_from_buf ((guchar*)a_buf, strlen ((const char *) a_buf),
|
|
a_encoding, FALSE);
|
|
if (!parser) {
|
|
cr_utils_trace_info ("Instantiation of the parser failed.");
|
|
goto cleanup;
|
|
}
|
|
|
|
sac_handler = cr_doc_handler_new ();
|
|
if (!sac_handler) {
|
|
cr_utils_trace_info
|
|
("Instantiation of the sac handler failed.");
|
|
goto cleanup;
|
|
}
|
|
|
|
sac_handler->start_page = parse_page_start_page_cb;
|
|
sac_handler->property = parse_page_property_cb;
|
|
sac_handler->end_page = parse_page_end_page_cb;
|
|
sac_handler->unrecoverable_error = parse_page_unrecoverable_error_cb;
|
|
|
|
status = cr_parser_set_sac_handler (parser, sac_handler);
|
|
if (status != CR_OK)
|
|
goto cleanup;
|
|
|
|
/*Now, invoke the parser to parse the "@page production" */
|
|
cr_parser_try_to_skip_spaces_and_comments (parser);
|
|
if (status != CR_OK)
|
|
goto cleanup;
|
|
status = cr_parser_parse_page (parser);
|
|
if (status != CR_OK)
|
|
goto cleanup;
|
|
|
|
resultptr = &result;
|
|
status = cr_doc_handler_get_result (sac_handler,
|
|
(gpointer *) resultptr);
|
|
|
|
cleanup:
|
|
|
|
if (parser) {
|
|
cr_parser_destroy (parser);
|
|
parser = NULL;
|
|
sac_handler = NULL ;
|
|
}
|
|
if (sac_handler) {
|
|
cr_doc_handler_unref (sac_handler);
|
|
sac_handler = NULL;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* cr_statement_new_at_charset_rule:
|
|
*
|
|
*@a_charset: the string representing the charset.
|
|
*Note that the newly built instance of #CRStatement becomes
|
|
*the owner of a_charset. The caller must not free a_charset !!!.
|
|
*
|
|
*Creates a new instance of #CRStatement of type
|
|
*#CRAtCharsetRule.
|
|
*
|
|
*Returns the newly built instance of #CRStatement or NULL
|
|
*if an error arises.
|
|
*/
|
|
CRStatement *
|
|
cr_statement_new_at_charset_rule (CRStyleSheet * a_sheet,
|
|
CRString * a_charset)
|
|
{
|
|
CRStatement *result = NULL;
|
|
|
|
g_return_val_if_fail (a_charset, NULL);
|
|
|
|
result = g_try_malloc (sizeof (CRStatement));
|
|
|
|
if (!result) {
|
|
cr_utils_trace_info ("Out of memory");
|
|
return NULL;
|
|
}
|
|
|
|
memset (result, 0, sizeof (CRStatement));
|
|
result->type = AT_CHARSET_RULE_STMT;
|
|
|
|
result->kind.charset_rule = g_try_malloc (sizeof (CRAtCharsetRule));
|
|
|
|
if (!result->kind.charset_rule) {
|
|
cr_utils_trace_info ("Out of memory");
|
|
g_free (result);
|
|
return NULL;
|
|
}
|
|
memset (result->kind.charset_rule, 0, sizeof (CRAtCharsetRule));
|
|
result->kind.charset_rule->charset = a_charset;
|
|
cr_statement_set_parent_sheet (result, a_sheet);
|
|
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* cr_statement_at_charset_rule_parse_from_buf:
|
|
*
|
|
*@a_buf: the buffer to parse.
|
|
*@a_encoding: the character encoding of the buffer.
|
|
*
|
|
*Parses a buffer that contains an '\@charset' rule and
|
|
*creates an instance of #CRStatement of type AT_CHARSET_RULE_STMT.
|
|
*
|
|
*Returns the newly built instance of #CRStatement.
|
|
*/
|
|
CRStatement *
|
|
cr_statement_at_charset_rule_parse_from_buf (const guchar * a_buf,
|
|
enum CREncoding a_encoding)
|
|
{
|
|
enum CRStatus status = CR_OK;
|
|
CRParser *parser = NULL;
|
|
CRStatement *result = NULL;
|
|
CRString *charset = NULL;
|
|
|
|
g_return_val_if_fail (a_buf, NULL);
|
|
|
|
parser = cr_parser_new_from_buf ((guchar*)a_buf, strlen ((const char *) a_buf),
|
|
a_encoding, FALSE);
|
|
if (!parser) {
|
|
cr_utils_trace_info ("Instantiation of the parser failed.");
|
|
goto cleanup;
|
|
}
|
|
|
|
/*Now, invoke the parser to parse the "@charset production" */
|
|
cr_parser_try_to_skip_spaces_and_comments (parser);
|
|
if (status != CR_OK)
|
|
goto cleanup;
|
|
status = cr_parser_parse_charset (parser, &charset, NULL);
|
|
if (status != CR_OK || !charset)
|
|
goto cleanup;
|
|
|
|
result = cr_statement_new_at_charset_rule (NULL, charset);
|
|
if (result)
|
|
charset = NULL;
|
|
|
|
cleanup:
|
|
|
|
if (parser) {
|
|
cr_parser_destroy (parser);
|
|
parser = NULL;
|
|
}
|
|
if (charset) {
|
|
cr_string_destroy (charset);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* cr_statement_new_at_font_face_rule:
|
|
*
|
|
*@a_font_decls: a list of instances of #CRDeclaration. Each declaration
|
|
*is actually a font declaration.
|
|
*
|
|
*Creates an instance of #CRStatement of type #CRAtFontFaceRule.
|
|
*
|
|
*Returns the newly built instance of #CRStatement.
|
|
*/
|
|
CRStatement *
|
|
cr_statement_new_at_font_face_rule (CRStyleSheet * a_sheet,
|
|
CRDeclaration * a_font_decls)
|
|
{
|
|
CRStatement *result = NULL;
|
|
|
|
result = g_try_malloc (sizeof (CRStatement));
|
|
|
|
if (!result) {
|
|
cr_utils_trace_info ("Out of memory");
|
|
return NULL;
|
|
}
|
|
memset (result, 0, sizeof (CRStatement));
|
|
result->type = AT_FONT_FACE_RULE_STMT;
|
|
|
|
result->kind.font_face_rule = g_try_malloc
|
|
(sizeof (CRAtFontFaceRule));
|
|
|
|
if (!result->kind.font_face_rule) {
|
|
cr_utils_trace_info ("Out of memory");
|
|
g_free (result);
|
|
return NULL;
|
|
}
|
|
memset (result->kind.font_face_rule, 0, sizeof (CRAtFontFaceRule));
|
|
|
|
result->kind.font_face_rule->decl_list = a_font_decls;
|
|
if (a_sheet)
|
|
cr_statement_set_parent_sheet (result, a_sheet);
|
|
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* cr_statement_font_face_rule_parse_from_buf:
|
|
*
|
|
*
|
|
*@a_buf: the buffer to parse.
|
|
*@a_encoding: the character encoding of a_buf.
|
|
*
|
|
*Parses a buffer that contains an "\@font-face" rule and builds
|
|
*an instance of #CRStatement of type AT_FONT_FACE_RULE_STMT out of it.
|
|
*
|
|
*Returns the newly built instance of #CRStatement in case of successufull
|
|
*parsing, NULL otherwise.
|
|
*/
|
|
CRStatement *
|
|
cr_statement_font_face_rule_parse_from_buf (const guchar * a_buf,
|
|
enum CREncoding a_encoding)
|
|
{
|
|
CRStatement *result = NULL;
|
|
CRStatement **resultptr = NULL;
|
|
CRParser *parser = NULL;
|
|
CRDocHandler *sac_handler = NULL;
|
|
enum CRStatus status = CR_OK;
|
|
|
|
parser = cr_parser_new_from_buf ((guchar*)a_buf, strlen ((const char *) a_buf),
|
|
a_encoding, FALSE);
|
|
if (!parser)
|
|
goto cleanup;
|
|
|
|
sac_handler = cr_doc_handler_new ();
|
|
if (!sac_handler)
|
|
goto cleanup;
|
|
|
|
/*
|
|
*set sac callbacks here
|
|
*/
|
|
sac_handler->start_font_face = parse_font_face_start_font_face_cb;
|
|
sac_handler->property = parse_font_face_property_cb;
|
|
sac_handler->end_font_face = parse_font_face_end_font_face_cb;
|
|
sac_handler->unrecoverable_error =
|
|
parse_font_face_unrecoverable_error_cb;
|
|
|
|
status = cr_parser_set_sac_handler (parser, sac_handler);
|
|
if (status != CR_OK)
|
|
goto cleanup;
|
|
|
|
/*
|
|
*cleanup spaces of comment that may be there before the real
|
|
*"@font-face" thing.
|
|
*/
|
|
status = cr_parser_try_to_skip_spaces_and_comments (parser);
|
|
if (status != CR_OK)
|
|
goto cleanup;
|
|
|
|
status = cr_parser_parse_font_face (parser);
|
|
if (status != CR_OK)
|
|
goto cleanup;
|
|
|
|
resultptr = &result;
|
|
status = cr_doc_handler_get_result (sac_handler,
|
|
(gpointer *) resultptr);
|
|
if (status != CR_OK || !result)
|
|
goto cleanup;
|
|
|
|
cleanup:
|
|
if (parser) {
|
|
cr_parser_destroy (parser);
|
|
parser = NULL;
|
|
sac_handler = NULL ;
|
|
}
|
|
if (sac_handler) {
|
|
cr_doc_handler_unref (sac_handler);
|
|
sac_handler = NULL;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* cr_statement_set_parent_sheet:
|
|
*
|
|
*@a_this: the current instance of #CRStatement.
|
|
*@a_sheet: the sheet that contains the current statement.
|
|
*
|
|
*Sets the container stylesheet.
|
|
*
|
|
*Returns CR_OK upon successful completion, an error code otherwise.
|
|
*/
|
|
enum CRStatus
|
|
cr_statement_set_parent_sheet (CRStatement * a_this, CRStyleSheet * a_sheet)
|
|
{
|
|
g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
|
|
a_this->parent_sheet = a_sheet;
|
|
return CR_OK;
|
|
}
|
|
|
|
/**
|
|
* cr_statement_get_parent_sheet:
|
|
*
|
|
*@a_this: the current #CRStatement.
|
|
*@a_sheet: out parameter. A pointer to the sheets that
|
|
*
|
|
*Gets the sheets that contains the current statement.
|
|
*
|
|
*Returns CR_OK upon successful completion, an error code otherwise.
|
|
*/
|
|
enum CRStatus
|
|
cr_statement_get_parent_sheet (CRStatement * a_this, CRStyleSheet ** a_sheet)
|
|
{
|
|
g_return_val_if_fail (a_this && a_sheet, CR_BAD_PARAM_ERROR);
|
|
*a_sheet = a_this->parent_sheet;
|
|
return CR_OK;
|
|
}
|
|
|
|
/**
|
|
* cr_statement_append:
|
|
*
|
|
*@a_this: the current instance of the statement list.
|
|
*@a_new: a_new the new instance of #CRStatement to append.
|
|
*
|
|
*Appends a new statement to the statement list.
|
|
*
|
|
*Returns the new list statement list, or NULL in cas of failure.
|
|
*/
|
|
CRStatement *
|
|
cr_statement_append (CRStatement * a_this, CRStatement * a_new)
|
|
{
|
|
CRStatement *cur = NULL;
|
|
|
|
g_return_val_if_fail (a_new, NULL);
|
|
|
|
if (!a_this) {
|
|
return a_new;
|
|
}
|
|
|
|
/*walk forward in the current list to find the tail list element */
|
|
for (cur = a_this; cur && cur->next; cur = cur->next) ;
|
|
|
|
cur->next = a_new;
|
|
a_new->prev = cur;
|
|
|
|
return a_this;
|
|
}
|
|
|
|
/**
|
|
* cr_statement_prepend:
|
|
*
|
|
*@a_this: the current instance of #CRStatement.
|
|
*@a_new: the new statement to prepend.
|
|
*
|
|
*Prepends the an instance of #CRStatement to
|
|
*the current statement list.
|
|
*
|
|
*Returns the new list with the new statement prepended,
|
|
*or NULL in case of an error.
|
|
*/
|
|
CRStatement *
|
|
cr_statement_prepend (CRStatement * a_this, CRStatement * a_new)
|
|
{
|
|
CRStatement *cur = NULL;
|
|
|
|
g_return_val_if_fail (a_new, NULL);
|
|
|
|
if (!a_this)
|
|
return a_new;
|
|
|
|
a_new->next = a_this;
|
|
a_this->prev = a_new;
|
|
|
|
/*walk backward in the prepended list to find the head list element */
|
|
for (cur = a_new; cur && cur->prev; cur = cur->prev) ;
|
|
|
|
return cur;
|
|
}
|
|
|
|
/**
|
|
* cr_statement_unlink:
|
|
*
|
|
*@a_this: the current statements list.
|
|
*@a_to_unlink: the statement to unlink from the list.
|
|
*
|
|
*Unlinks a statement from the statements list.
|
|
*
|
|
*Returns the new list where a_to_unlink has been unlinked
|
|
*from, or NULL in case of error.
|
|
*/
|
|
CRStatement *
|
|
cr_statement_unlink (CRStatement * a_stmt)
|
|
{
|
|
CRStatement *result = a_stmt;
|
|
|
|
g_return_val_if_fail (result, NULL);
|
|
|
|
/**
|
|
*Some sanity checks first
|
|
*/
|
|
if (a_stmt->next) {
|
|
g_return_val_if_fail (a_stmt->next->prev == a_stmt, NULL);
|
|
}
|
|
if (a_stmt->prev) {
|
|
g_return_val_if_fail (a_stmt->prev->next == a_stmt, NULL);
|
|
}
|
|
|
|
/**
|
|
*Now, the real unlinking job.
|
|
*/
|
|
if (a_stmt->next) {
|
|
a_stmt->next->prev = a_stmt->prev;
|
|
}
|
|
if (a_stmt->prev) {
|
|
a_stmt->prev->next = a_stmt->next;
|
|
}
|
|
|
|
if (a_stmt->parent_sheet
|
|
&& a_stmt->parent_sheet->statements == a_stmt) {
|
|
a_stmt->parent_sheet->statements =
|
|
a_stmt->parent_sheet->statements->next;
|
|
}
|
|
|
|
a_stmt->next = NULL;
|
|
a_stmt->prev = NULL;
|
|
a_stmt->parent_sheet = NULL;
|
|
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* cr_statement_nr_rules:
|
|
*
|
|
*@a_this: the current instance of #CRStatement.
|
|
*
|
|
*Gets the number of rules in the statement list;
|
|
*
|
|
*Returns number of rules in the statement list.
|
|
*/
|
|
gint
|
|
cr_statement_nr_rules (CRStatement const * a_this)
|
|
{
|
|
CRStatement const *cur = NULL;
|
|
int nr = 0;
|
|
|
|
g_return_val_if_fail (a_this, -1);
|
|
|
|
for (cur = a_this; cur; cur = cur->next)
|
|
nr++;
|
|
return nr;
|
|
}
|
|
|
|
/**
|
|
* cr_statement_get_from_list:
|
|
*
|
|
*@a_this: the current instance of #CRStatement.
|
|
*@itemnr: the index into the statement list.
|
|
*
|
|
*Use an index to get a CRStatement from the statement list.
|
|
*
|
|
*Returns CRStatement at position itemnr, if itemnr > number of statements - 1,
|
|
*it will return NULL.
|
|
*/
|
|
CRStatement *
|
|
cr_statement_get_from_list (CRStatement * a_this, int itemnr)
|
|
{
|
|
CRStatement *cur = NULL;
|
|
int nr = 0;
|
|
|
|
g_return_val_if_fail (a_this, NULL);
|
|
|
|
for (cur = a_this; cur; cur = cur->next)
|
|
if (nr++ == itemnr)
|
|
return cur;
|
|
return NULL;
|
|
}
|
|
|
|
/**
|
|
* cr_statement_ruleset_set_sel_list:
|
|
*
|
|
*@a_this: the current ruleset statement.
|
|
*@a_sel_list: the selector list to set. Note
|
|
*that this function increments the ref count of a_sel_list.
|
|
*The sel list will be destroyed at the destruction of the
|
|
*current instance of #CRStatement.
|
|
*
|
|
*Sets a selector list to a ruleset statement.
|
|
*
|
|
*Returns CR_OK upon successful completion, an error code otherwise.
|
|
*/
|
|
enum CRStatus
|
|
cr_statement_ruleset_set_sel_list (CRStatement * a_this,
|
|
CRSelector * a_sel_list)
|
|
{
|
|
g_return_val_if_fail (a_this && a_this->type == RULESET_STMT,
|
|
CR_BAD_PARAM_ERROR);
|
|
|
|
if (a_this->kind.ruleset->sel_list)
|
|
cr_selector_unref (a_this->kind.ruleset->sel_list);
|
|
|
|
a_this->kind.ruleset->sel_list = a_sel_list;
|
|
|
|
if (a_sel_list)
|
|
cr_selector_ref (a_sel_list);
|
|
|
|
return CR_OK;
|
|
}
|
|
|
|
/**
|
|
* cr_statement_ruleset_get_declarations:
|
|
*
|
|
*@a_this: the current instance of #CRStatement.
|
|
*@a_decl_list: out parameter. A pointer to the the returned
|
|
*list of declaration. Must not be NULL.
|
|
*
|
|
*Gets a pointer to the list of declaration contained
|
|
*in the ruleset statement.
|
|
*
|
|
*Returns CR_OK upon successful completion, an error code if something
|
|
*bad happened.
|
|
*/
|
|
enum CRStatus
|
|
cr_statement_ruleset_get_declarations (CRStatement * a_this,
|
|
CRDeclaration ** a_decl_list)
|
|
{
|
|
g_return_val_if_fail (a_this
|
|
&& a_this->type == RULESET_STMT
|
|
&& a_this->kind.ruleset
|
|
&& a_decl_list, CR_BAD_PARAM_ERROR);
|
|
|
|
*a_decl_list = a_this->kind.ruleset->decl_list;
|
|
|
|
return CR_OK;
|
|
}
|
|
|
|
/**
|
|
* cr_statement_ruleset_get_sel_list:
|
|
*
|
|
*@a_this: the current ruleset statement.
|
|
*@a_list: out parameter. The returned selector list,
|
|
*if and only if the function returned CR_OK.
|
|
*
|
|
*Gets a pointer to the selector list contained in
|
|
*the current ruleset statement.
|
|
*
|
|
*Returns CR_OK upon successful completion, an error code otherwise.
|
|
*/
|
|
enum CRStatus
|
|
cr_statement_ruleset_get_sel_list (CRStatement const * a_this, CRSelector ** a_list)
|
|
{
|
|
g_return_val_if_fail (a_this && a_this->type == RULESET_STMT
|
|
&& a_this->kind.ruleset, CR_BAD_PARAM_ERROR);
|
|
|
|
*a_list = a_this->kind.ruleset->sel_list;
|
|
|
|
return CR_OK;
|
|
}
|
|
|
|
/**
|
|
* cr_statement_ruleset_set_decl_list:
|
|
*
|
|
*@a_this: the current ruleset statement.
|
|
*@a_list: the declaration list to be added to the current
|
|
*ruleset statement.
|
|
*
|
|
*Sets a declaration list to the current ruleset statement.
|
|
*
|
|
*Returns CR_OK upon successful completion, an error code otherwise.
|
|
*/
|
|
enum CRStatus
|
|
cr_statement_ruleset_set_decl_list (CRStatement * a_this,
|
|
CRDeclaration * a_list)
|
|
{
|
|
g_return_val_if_fail (a_this && a_this->type == RULESET_STMT
|
|
&& a_this->kind.ruleset, CR_BAD_PARAM_ERROR);
|
|
|
|
if (a_this->kind.ruleset->decl_list == a_list)
|
|
return CR_OK;
|
|
|
|
if (a_this->kind.ruleset->sel_list) {
|
|
cr_declaration_destroy (a_this->kind.ruleset->decl_list);
|
|
}
|
|
|
|
a_this->kind.ruleset->sel_list = NULL;
|
|
|
|
return CR_OK;
|
|
}
|
|
|
|
/**
|
|
* cr_statement_ruleset_append_decl2:
|
|
*
|
|
*@a_this: the current statement.
|
|
*@a_prop: the property of the declaration.
|
|
*@a_value: the value of the declaration.
|
|
*
|
|
*Appends a declaration to the current ruleset statement.
|
|
*
|
|
*Returns CR_OK upon successful completion, an error code
|
|
*otherwise.
|
|
*/
|
|
enum CRStatus
|
|
cr_statement_ruleset_append_decl2 (CRStatement * a_this,
|
|
CRString * a_prop,
|
|
CRTerm * a_value)
|
|
{
|
|
CRDeclaration *new_decls = NULL;
|
|
|
|
g_return_val_if_fail (a_this && a_this->type == RULESET_STMT
|
|
&& a_this->kind.ruleset, CR_BAD_PARAM_ERROR);
|
|
|
|
new_decls = cr_declaration_append2
|
|
(a_this->kind.ruleset->decl_list,
|
|
a_prop, a_value);
|
|
g_return_val_if_fail (new_decls, CR_ERROR);
|
|
a_this->kind.ruleset->decl_list = new_decls;
|
|
|
|
return CR_OK;
|
|
}
|
|
|
|
/**
|
|
* cr_statement_ruleset_append_decl:
|
|
*
|
|
*Appends a declaration to the current statement.
|
|
*
|
|
*@a_this: the current statement.
|
|
*@a_declaration: the declaration to append.
|
|
*
|
|
*Returns CR_OK upon successful completion, an error code
|
|
*otherwise.
|
|
*/
|
|
enum CRStatus
|
|
cr_statement_ruleset_append_decl (CRStatement * a_this,
|
|
CRDeclaration * a_decl)
|
|
{
|
|
CRDeclaration *new_decls = NULL;
|
|
|
|
g_return_val_if_fail (a_this && a_this->type == RULESET_STMT
|
|
&& a_this->kind.ruleset, CR_BAD_PARAM_ERROR);
|
|
|
|
new_decls = cr_declaration_append
|
|
(a_this->kind.ruleset->decl_list, a_decl);
|
|
g_return_val_if_fail (new_decls, CR_ERROR);
|
|
a_this->kind.ruleset->decl_list = new_decls;
|
|
|
|
return CR_OK;
|
|
}
|
|
|
|
/**
|
|
* cr_statement_at_import_rule_set_imported_sheet:
|
|
*
|
|
*Sets a stylesheet to the current \@import rule.
|
|
*@a_this: the current \@import rule.
|
|
*@a_sheet: the stylesheet. The stylesheet is owned
|
|
*by the current instance of #CRStatement, that is, the
|
|
*stylesheet will be destroyed when the current instance
|
|
*of #CRStatement is destroyed.
|
|
*
|
|
*Returns CR_OK upon successful completion, an error code otherwise.
|
|
*/
|
|
enum CRStatus
|
|
cr_statement_at_import_rule_set_imported_sheet (CRStatement * a_this,
|
|
CRStyleSheet * a_sheet)
|
|
{
|
|
g_return_val_if_fail (a_this
|
|
&& a_this->type == AT_IMPORT_RULE_STMT
|
|
&& a_this->kind.import_rule,
|
|
CR_BAD_PARAM_ERROR);
|
|
|
|
a_this->kind.import_rule->sheet = a_sheet;
|
|
|
|
return CR_OK;
|
|
}
|
|
|
|
/**
|
|
* cr_statement_at_import_rule_get_imported_sheet:
|
|
*
|
|
*@a_this: the current \@import rule statement.
|
|
*@a_sheet: out parameter. The returned stylesheet if and
|
|
*only if the function returns CR_OK.
|
|
*
|
|
*Gets the stylesheet contained by the \@import rule statement.
|
|
*Returns CR_OK upon successful completion, an error code otherwise.
|
|
*/
|
|
enum CRStatus
|
|
cr_statement_at_import_rule_get_imported_sheet (CRStatement * a_this,
|
|
CRStyleSheet ** a_sheet)
|
|
{
|
|
g_return_val_if_fail (a_this
|
|
&& a_this->type == AT_IMPORT_RULE_STMT
|
|
&& a_this->kind.import_rule,
|
|
CR_BAD_PARAM_ERROR);
|
|
*a_sheet = a_this->kind.import_rule->sheet;
|
|
return CR_OK;
|
|
|
|
}
|
|
|
|
/**
|
|
* cr_statement_at_import_rule_set_url:
|
|
*
|
|
*@a_this: the current \@import rule statement.
|
|
*@a_url: the url to set.
|
|
*
|
|
*Sets an url to the current \@import rule statement.
|
|
*
|
|
*Returns CR_OK upon successful completion, an error code otherwise.
|
|
*/
|
|
enum CRStatus
|
|
cr_statement_at_import_rule_set_url (CRStatement * a_this,
|
|
CRString * a_url)
|
|
{
|
|
g_return_val_if_fail (a_this
|
|
&& a_this->type == AT_IMPORT_RULE_STMT
|
|
&& a_this->kind.import_rule,
|
|
CR_BAD_PARAM_ERROR);
|
|
|
|
if (a_this->kind.import_rule->url) {
|
|
cr_string_destroy (a_this->kind.import_rule->url);
|
|
}
|
|
|
|
a_this->kind.import_rule->url = a_url;
|
|
|
|
return CR_OK;
|
|
}
|
|
|
|
/**
|
|
* cr_statement_at_import_rule_get_url:
|
|
*
|
|
*@a_this: the current \@import rule statement.
|
|
*@a_url: out parameter. The returned url if
|
|
*and only if the function returned CR_OK.
|
|
*
|
|
*Gets the url of the \@import rule statement.
|
|
*Returns CR_OK upon successful completion, an error code otherwise.
|
|
*/
|
|
enum CRStatus
|
|
cr_statement_at_import_rule_get_url (CRStatement const * a_this,
|
|
CRString ** a_url)
|
|
{
|
|
g_return_val_if_fail (a_this
|
|
&& a_this->type == AT_IMPORT_RULE_STMT
|
|
&& a_this->kind.import_rule,
|
|
CR_BAD_PARAM_ERROR);
|
|
|
|
*a_url = a_this->kind.import_rule->url;
|
|
|
|
return CR_OK;
|
|
}
|
|
|
|
/**
|
|
* cr_statement_at_media_nr_rules:
|
|
*
|
|
*@a_this: the current instance of #CRStatement.
|
|
*
|
|
*Returns the number of rules in the media rule;
|
|
*/
|
|
int
|
|
cr_statement_at_media_nr_rules (CRStatement const * a_this)
|
|
{
|
|
g_return_val_if_fail (a_this
|
|
&& a_this->type == AT_MEDIA_RULE_STMT
|
|
&& a_this->kind.media_rule, CR_BAD_PARAM_ERROR);
|
|
|
|
return cr_statement_nr_rules (a_this->kind.media_rule->rulesets);
|
|
}
|
|
|
|
/**
|
|
* cr_statement_at_media_get_from_list:
|
|
*
|
|
*@a_this: the current instance of #CRStatement.
|
|
*@itemnr: the index into the media rule list of rules.
|
|
*
|
|
*Use an index to get a CRStatement from the media rule list of rules.
|
|
*
|
|
*Returns CRStatement at position itemnr, if itemnr > number of rules - 1,
|
|
*it will return NULL.
|
|
*/
|
|
CRStatement *
|
|
cr_statement_at_media_get_from_list (CRStatement * a_this, int itemnr)
|
|
{
|
|
g_return_val_if_fail (a_this
|
|
&& a_this->type == AT_MEDIA_RULE_STMT
|
|
&& a_this->kind.media_rule, NULL);
|
|
|
|
return cr_statement_get_from_list (a_this->kind.media_rule->rulesets,
|
|
itemnr);
|
|
}
|
|
|
|
/**
|
|
* cr_statement_at_page_rule_set_declarations:
|
|
*
|
|
*@a_this: the current \@page rule statement.
|
|
*@a_decl_list: the declaration list to add. Will be freed
|
|
*by the current instance of #CRStatement when it is destroyed.
|
|
*
|
|
*Sets a declaration list to the current \@page rule statement.
|
|
*
|
|
*Returns CR_OK upon successful completion, an error code otherwise.
|
|
*/
|
|
enum CRStatus
|
|
cr_statement_at_page_rule_set_declarations (CRStatement * a_this,
|
|
CRDeclaration * a_decl_list)
|
|
{
|
|
g_return_val_if_fail (a_this
|
|
&& a_this->type == AT_PAGE_RULE_STMT
|
|
&& a_this->kind.page_rule, CR_BAD_PARAM_ERROR);
|
|
|
|
if (a_this->kind.page_rule->decl_list) {
|
|
cr_declaration_unref (a_this->kind.page_rule->decl_list);
|
|
}
|
|
|
|
a_this->kind.page_rule->decl_list = a_decl_list;
|
|
|
|
if (a_decl_list) {
|
|
cr_declaration_ref (a_decl_list);
|
|
}
|
|
|
|
return CR_OK;
|
|
}
|
|
|
|
/**
|
|
* cr_statement_at_page_rule_get_declarations:
|
|
*
|
|
*@a_this: the current \@page rule statement.
|
|
*@a_decl_list: out parameter. The returned declaration list.
|
|
*
|
|
*Gets the declaration list associated to the current \@page rule
|
|
*statement.
|
|
*
|
|
*Returns CR_OK upon successful completion, an error code otherwise.
|
|
*/
|
|
enum CRStatus
|
|
cr_statement_at_page_rule_get_declarations (CRStatement * a_this,
|
|
CRDeclaration ** a_decl_list)
|
|
{
|
|
g_return_val_if_fail (a_this
|
|
&& a_this->type == AT_PAGE_RULE_STMT
|
|
&& a_this->kind.page_rule, CR_BAD_PARAM_ERROR);
|
|
|
|
*a_decl_list = a_this->kind.page_rule->decl_list;
|
|
|
|
return CR_OK;
|
|
}
|
|
|
|
/**
|
|
* cr_statement_at_charset_rule_set_charset:
|
|
*
|
|
*
|
|
*@a_this: the current \@charset rule statement.
|
|
*@a_charset: the charset to set.
|
|
*
|
|
*Sets the charset of the current \@charset rule statement.
|
|
*
|
|
*Returns CR_OK upon successful completion, an error code otherwise.
|
|
*/
|
|
enum CRStatus
|
|
cr_statement_at_charset_rule_set_charset (CRStatement * a_this,
|
|
CRString * a_charset)
|
|
{
|
|
g_return_val_if_fail (a_this
|
|
&& a_this->type == AT_CHARSET_RULE_STMT
|
|
&& a_this->kind.charset_rule,
|
|
CR_BAD_PARAM_ERROR);
|
|
|
|
if (a_this->kind.charset_rule->charset) {
|
|
cr_string_destroy (a_this->kind.charset_rule->charset);
|
|
}
|
|
a_this->kind.charset_rule->charset = a_charset;
|
|
return CR_OK;
|
|
}
|
|
|
|
/**
|
|
* cr_statement_at_charset_rule_get_charset:
|
|
*@a_this: the current \@charset rule statement.
|
|
*@a_charset: out parameter. The returned charset string if
|
|
*and only if the function returned CR_OK.
|
|
*
|
|
*Gets the charset string associated to the current
|
|
*\@charset rule statement.
|
|
*
|
|
* Returns CR_OK upon successful completion, an error code otherwise.
|
|
*/
|
|
enum CRStatus
|
|
cr_statement_at_charset_rule_get_charset (CRStatement const * a_this,
|
|
CRString ** a_charset)
|
|
{
|
|
g_return_val_if_fail (a_this
|
|
&& a_this->type == AT_CHARSET_RULE_STMT
|
|
&& a_this->kind.charset_rule,
|
|
CR_BAD_PARAM_ERROR);
|
|
|
|
*a_charset = a_this->kind.charset_rule->charset;
|
|
|
|
return CR_OK;
|
|
}
|
|
|
|
/**
|
|
* cr_statement_at_font_face_rule_set_decls:
|
|
*
|
|
*@a_this: the current \@font-face rule statement.
|
|
*@a_decls: the declarations list to set.
|
|
*
|
|
*Sets a declaration list to the current \@font-face rule statement.
|
|
*
|
|
*Returns CR_OK upon successful completion, an error code otherwise.
|
|
*/
|
|
enum CRStatus
|
|
cr_statement_at_font_face_rule_set_decls (CRStatement * a_this,
|
|
CRDeclaration * a_decls)
|
|
{
|
|
g_return_val_if_fail (a_this
|
|
&& a_this->type == AT_FONT_FACE_RULE_STMT
|
|
&& a_this->kind.font_face_rule,
|
|
CR_BAD_PARAM_ERROR);
|
|
|
|
if (a_this->kind.font_face_rule->decl_list) {
|
|
cr_declaration_unref (a_this->kind.font_face_rule->decl_list);
|
|
}
|
|
|
|
a_this->kind.font_face_rule->decl_list = a_decls;
|
|
cr_declaration_ref (a_decls);
|
|
|
|
return CR_OK;
|
|
}
|
|
|
|
/**
|
|
* cr_statement_at_font_face_rule_get_decls:
|
|
*
|
|
*@a_this: the current \@font-face rule statement.
|
|
*@a_decls: out parameter. The returned declaration list if
|
|
*and only if this function returns CR_OK.
|
|
*
|
|
*Gets the declaration list associated to the current instance
|
|
*of \@font-face rule statement.
|
|
*
|
|
*Returns CR_OK upon successful completion, an error code otherwise.
|
|
*/
|
|
enum CRStatus
|
|
cr_statement_at_font_face_rule_get_decls (CRStatement * a_this,
|
|
CRDeclaration ** a_decls)
|
|
{
|
|
g_return_val_if_fail (a_this
|
|
&& a_this->type == AT_FONT_FACE_RULE_STMT
|
|
&& a_this->kind.font_face_rule,
|
|
CR_BAD_PARAM_ERROR);
|
|
|
|
*a_decls = a_this->kind.font_face_rule->decl_list;
|
|
|
|
return CR_OK;
|
|
}
|
|
|
|
/**
|
|
* cr_statement_at_font_face_rule_add_decl:
|
|
*
|
|
*@a_this: the current \@font-face rule statement.
|
|
*@a_prop: the property of the declaration.
|
|
*@a_value: the value of the declaration.
|
|
*
|
|
*Adds a declaration to the current \@font-face rule
|
|
*statement.
|
|
*
|
|
*Returns CR_OK upon successful completion, an error code otherwise.
|
|
*/
|
|
enum CRStatus
|
|
cr_statement_at_font_face_rule_add_decl (CRStatement * a_this,
|
|
CRString * a_prop, CRTerm * a_value)
|
|
{
|
|
CRDeclaration *decls = NULL;
|
|
|
|
g_return_val_if_fail (a_this
|
|
&& a_this->type == AT_FONT_FACE_RULE_STMT
|
|
&& a_this->kind.font_face_rule,
|
|
CR_BAD_PARAM_ERROR);
|
|
|
|
decls = cr_declaration_append2
|
|
(a_this->kind.font_face_rule->decl_list,
|
|
a_prop, a_value);
|
|
|
|
g_return_val_if_fail (decls, CR_ERROR);
|
|
|
|
if (a_this->kind.font_face_rule->decl_list == NULL)
|
|
cr_declaration_ref (decls);
|
|
|
|
a_this->kind.font_face_rule->decl_list = decls;
|
|
|
|
return CR_OK;
|
|
}
|
|
|
|
|
|
/**
|
|
* cr_statement_to_string:
|
|
*
|
|
*@a_this: the current statement to serialize
|
|
*@a_indent: the number of white space of indentation.
|
|
*
|
|
*Serializes a css statement into a string
|
|
*
|
|
*Returns the serialized statement. Must be freed by the caller
|
|
*using g_free().
|
|
*/
|
|
gchar *
|
|
cr_statement_to_string (CRStatement const * a_this, gulong a_indent)
|
|
{
|
|
gchar *str = NULL ;
|
|
|
|
if (!a_this)
|
|
return NULL;
|
|
|
|
switch (a_this->type) {
|
|
case RULESET_STMT:
|
|
str = cr_statement_ruleset_to_string
|
|
(a_this, a_indent);
|
|
break;
|
|
|
|
case AT_FONT_FACE_RULE_STMT:
|
|
str = cr_statement_font_face_rule_to_string
|
|
(a_this, a_indent) ;
|
|
break;
|
|
|
|
case AT_CHARSET_RULE_STMT:
|
|
str = cr_statement_charset_to_string
|
|
(a_this, a_indent);
|
|
break;
|
|
|
|
case AT_PAGE_RULE_STMT:
|
|
str = cr_statement_at_page_rule_to_string
|
|
(a_this, a_indent);
|
|
break;
|
|
|
|
case AT_MEDIA_RULE_STMT:
|
|
str = cr_statement_media_rule_to_string
|
|
(a_this, a_indent);
|
|
break;
|
|
|
|
case AT_IMPORT_RULE_STMT:
|
|
str = cr_statement_import_rule_to_string
|
|
(a_this, a_indent);
|
|
break;
|
|
|
|
default:
|
|
cr_utils_trace_info ("Statement unrecognized");
|
|
break;
|
|
}
|
|
return str ;
|
|
}
|
|
|
|
gchar*
|
|
cr_statement_list_to_string (CRStatement const *a_this, gulong a_indent)
|
|
{
|
|
CRStatement const *cur_stmt = NULL ;
|
|
GString *stringue = NULL ;
|
|
gchar *str = NULL ;
|
|
|
|
g_return_val_if_fail (a_this, NULL) ;
|
|
|
|
stringue = g_string_new (NULL) ;
|
|
if (!stringue) {
|
|
cr_utils_trace_info ("Out of memory") ;
|
|
return NULL ;
|
|
}
|
|
for (cur_stmt = a_this ; cur_stmt;
|
|
cur_stmt = cur_stmt->next) {
|
|
str = cr_statement_to_string (cur_stmt, a_indent) ;
|
|
if (str) {
|
|
if (!cur_stmt->prev) {
|
|
g_string_append (stringue, str) ;
|
|
} else {
|
|
g_string_append_printf
|
|
(stringue, "\n%s", str) ;
|
|
}
|
|
g_free (str) ;
|
|
str = NULL ;
|
|
}
|
|
}
|
|
str = stringue->str ;
|
|
g_string_free (stringue, FALSE) ;
|
|
return str ;
|
|
}
|
|
|
|
/**
|
|
* cr_statement_dump:
|
|
*
|
|
*@a_this: the current css2 statement.
|
|
*@a_fp: the destination file pointer.
|
|
*@a_indent: the number of white space indentation characters.
|
|
*
|
|
*Dumps the css2 statement to a file.
|
|
*/
|
|
void
|
|
cr_statement_dump (CRStatement const * a_this, FILE * a_fp, gulong a_indent)
|
|
{
|
|
gchar *str = NULL ;
|
|
|
|
if (!a_this)
|
|
return;
|
|
|
|
str = cr_statement_to_string (a_this, a_indent) ;
|
|
if (str) {
|
|
fprintf (a_fp, "%s",str) ;
|
|
g_free (str) ;
|
|
str = NULL ;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* cr_statement_dump_ruleset:
|
|
*
|
|
*@a_this: the current instance of #CRStatement.
|
|
*@a_fp: the destination file pointer.
|
|
*@a_indent: the number of indentation white spaces to add.
|
|
*
|
|
*Dumps a ruleset statement to a file.
|
|
*/
|
|
void
|
|
cr_statement_dump_ruleset (CRStatement const * a_this, FILE * a_fp, glong a_indent)
|
|
{
|
|
gchar *str = NULL;
|
|
|
|
g_return_if_fail (a_fp && a_this);
|
|
str = cr_statement_ruleset_to_string (a_this, a_indent);
|
|
if (str) {
|
|
fprintf (a_fp, "%s", str);
|
|
g_free (str);
|
|
str = NULL;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* cr_statement_dump_font_face_rule:
|
|
*
|
|
*@a_this: the current instance of font face rule statement.
|
|
*@a_fp: the destination file pointer.
|
|
*@a_indent: the number of white space indentation.
|
|
*
|
|
*Dumps a font face rule statement to a file.
|
|
*/
|
|
void
|
|
cr_statement_dump_font_face_rule (CRStatement const * a_this, FILE * a_fp,
|
|
glong a_indent)
|
|
{
|
|
gchar *str = NULL ;
|
|
g_return_if_fail (a_this
|
|
&& a_this->type == AT_FONT_FACE_RULE_STMT);
|
|
|
|
str = cr_statement_font_face_rule_to_string (a_this,
|
|
a_indent) ;
|
|
if (str) {
|
|
fprintf (a_fp, "%s", str) ;
|
|
g_free (str) ;
|
|
str = NULL ;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* cr_statement_dump_charset:
|
|
*
|
|
*@a_this: the current instance of the \@charset rule statement.
|
|
*@a_fp: the destination file pointer.
|
|
*@a_indent: the number of indentation white spaces.
|
|
*
|
|
*Dumps an \@charset rule statement to a file.
|
|
*/
|
|
void
|
|
cr_statement_dump_charset (CRStatement const * a_this, FILE * a_fp, gulong a_indent)
|
|
{
|
|
gchar *str = NULL;
|
|
|
|
g_return_if_fail (a_this && a_this->type == AT_CHARSET_RULE_STMT);
|
|
|
|
str = cr_statement_charset_to_string (a_this,
|
|
a_indent) ;
|
|
if (str) {
|
|
fprintf (a_fp, "%s", str) ;
|
|
g_free (str) ;
|
|
str = NULL ;
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* cr_statement_dump_page:
|
|
*
|
|
*@a_this: the statement to dump on stdout.
|
|
*@a_fp: the destination file pointer.
|
|
*@a_indent: the number of indentation white spaces.
|
|
*
|
|
*Dumps an \@page rule statement on stdout.
|
|
*/
|
|
void
|
|
cr_statement_dump_page (CRStatement const * a_this, FILE * a_fp, gulong a_indent)
|
|
{
|
|
gchar *str = NULL;
|
|
|
|
g_return_if_fail (a_this
|
|
&& a_this->type == AT_PAGE_RULE_STMT
|
|
&& a_this->kind.page_rule);
|
|
|
|
str = cr_statement_at_page_rule_to_string (a_this, a_indent) ;
|
|
if (str) {
|
|
fprintf (a_fp, "%s", str);
|
|
g_free (str) ;
|
|
str = NULL ;
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* cr_statement_dump_media_rule:
|
|
*
|
|
*@a_this: the statement to dump.
|
|
*@a_fp: the destination file pointer
|
|
*@a_indent: the number of white spaces indentation.
|
|
*
|
|
*Dumps an \@media rule statement to a file.
|
|
*/
|
|
void
|
|
cr_statement_dump_media_rule (CRStatement const * a_this,
|
|
FILE * a_fp,
|
|
gulong a_indent)
|
|
{
|
|
gchar *str = NULL ;
|
|
g_return_if_fail (a_this->type == AT_MEDIA_RULE_STMT);
|
|
|
|
str = cr_statement_media_rule_to_string (a_this, a_indent) ;
|
|
if (str) {
|
|
fprintf (a_fp, "%s", str) ;
|
|
g_free (str) ;
|
|
str = NULL ;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* cr_statement_dump_import_rule:
|
|
*
|
|
*@a_fp: the destination file pointer.
|
|
*@a_indent: the number of white space indentations.
|
|
*
|
|
*Dumps an \@import rule statement to a file.
|
|
*/
|
|
void
|
|
cr_statement_dump_import_rule (CRStatement const * a_this, FILE * a_fp,
|
|
gulong a_indent)
|
|
{
|
|
gchar *str = NULL ;
|
|
g_return_if_fail (a_this
|
|
&& a_this->type == AT_IMPORT_RULE_STMT
|
|
&& a_fp
|
|
&& a_this->kind.import_rule);
|
|
|
|
str = cr_statement_import_rule_to_string (a_this, a_indent) ;
|
|
if (str) {
|
|
fprintf (a_fp, "%s", str) ;
|
|
g_free (str) ;
|
|
str = NULL ;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* cr_statement_destroy:
|
|
*
|
|
* @a_this: the current instance of #CRStatement.
|
|
*
|
|
*Destructor of #CRStatement.
|
|
*/
|
|
void
|
|
cr_statement_destroy (CRStatement * a_this)
|
|
{
|
|
CRStatement *cur = NULL;
|
|
|
|
g_return_if_fail (a_this);
|
|
|
|
/*go get the tail of the list */
|
|
for (cur = a_this; cur && cur->next; cur = cur->next) {
|
|
cr_statement_clear (cur);
|
|
}
|
|
|
|
if (cur)
|
|
cr_statement_clear (cur);
|
|
|
|
if (cur->prev == NULL) {
|
|
g_free (a_this);
|
|
return;
|
|
}
|
|
|
|
/*walk backward and free next element */
|
|
for (cur = cur->prev; cur && cur->prev; cur = cur->prev) {
|
|
if (cur->next) {
|
|
g_free (cur->next);
|
|
cur->next = NULL;
|
|
}
|
|
}
|
|
|
|
if (!cur)
|
|
return;
|
|
|
|
/*free the one remaining list */
|
|
if (cur->next) {
|
|
g_free (cur->next);
|
|
cur->next = NULL;
|
|
}
|
|
|
|
g_free (cur);
|
|
cur = NULL;
|
|
}
|