25202 lines
784 KiB
Diff
25202 lines
784 KiB
Diff
From 47758d16ff0acd9edbd8ff6eb3922e59fb14f8bb Mon Sep 17 00:00:00 2001
|
|
From: Federico Mena Quintero <federico@gnome.org>
|
|
Date: Thu, 21 Nov 2019 14:24:02 -0600
|
|
Subject: [PATCH] Include the libcroco sources directly under src/st/croco
|
|
|
|
This is all of the original libcroco, minus these two which we don't use:
|
|
|
|
- cr-sel-eng - the CSS selection engine for xmlNode.
|
|
- cr-style.
|
|
|
|
Part of https://gitlab.gnome.org/GNOME/gnome-shell/issues/1934
|
|
---
|
|
meson.build | 2 -
|
|
src/st/croco/cr-additional-sel.c | 500 +++
|
|
src/st/croco/cr-additional-sel.h | 98 +
|
|
src/st/croco/cr-attr-sel.c | 235 ++
|
|
src/st/croco/cr-attr-sel.h | 74 +
|
|
src/st/croco/cr-cascade.c | 215 ++
|
|
src/st/croco/cr-cascade.h | 74 +
|
|
src/st/croco/cr-declaration.c | 801 +++++
|
|
src/st/croco/cr-declaration.h | 136 +
|
|
src/st/croco/cr-doc-handler.c | 276 ++
|
|
src/st/croco/cr-doc-handler.h | 298 ++
|
|
src/st/croco/cr-enc-handler.c | 184 ++
|
|
src/st/croco/cr-enc-handler.h | 94 +
|
|
src/st/croco/cr-fonts.c | 949 ++++++
|
|
src/st/croco/cr-fonts.h | 315 ++
|
|
src/st/croco/cr-input.c | 1191 ++++++++
|
|
src/st/croco/cr-input.h | 174 ++
|
|
src/st/croco/cr-num.c | 313 ++
|
|
src/st/croco/cr-num.h | 127 +
|
|
src/st/croco/cr-om-parser.c | 1142 +++++++
|
|
src/st/croco/cr-om-parser.h | 98 +
|
|
src/st/croco/cr-parser.c | 4525 ++++++++++++++++++++++++++++
|
|
src/st/croco/cr-parser.h | 128 +
|
|
src/st/croco/cr-parsing-location.c | 172 ++
|
|
src/st/croco/cr-parsing-location.h | 70 +
|
|
src/st/croco/cr-prop-list.c | 404 +++
|
|
src/st/croco/cr-prop-list.h | 80 +
|
|
src/st/croco/cr-pseudo.c | 167 +
|
|
src/st/croco/cr-pseudo.h | 64 +
|
|
src/st/croco/cr-rgb.c | 687 +++++
|
|
src/st/croco/cr-rgb.h | 94 +
|
|
src/st/croco/cr-selector.c | 306 ++
|
|
src/st/croco/cr-selector.h | 95 +
|
|
src/st/croco/cr-simple-sel.c | 325 ++
|
|
src/st/croco/cr-simple-sel.h | 130 +
|
|
src/st/croco/cr-statement.c | 2794 +++++++++++++++++
|
|
src/st/croco/cr-statement.h | 440 +++
|
|
src/st/croco/cr-string.c | 168 ++
|
|
src/st/croco/cr-string.h | 76 +
|
|
src/st/croco/cr-stylesheet.c | 178 ++
|
|
src/st/croco/cr-stylesheet.h | 102 +
|
|
src/st/croco/cr-term.c | 790 +++++
|
|
src/st/croco/cr-term.h | 190 ++
|
|
src/st/croco/cr-tknzr.c | 2762 +++++++++++++++++
|
|
src/st/croco/cr-tknzr.h | 115 +
|
|
src/st/croco/cr-token.c | 636 ++++
|
|
src/st/croco/cr-token.h | 212 ++
|
|
src/st/croco/cr-utils.c | 1330 ++++++++
|
|
src/st/croco/cr-utils.h | 246 ++
|
|
src/st/croco/libcroco-config.h | 13 +
|
|
src/st/croco/libcroco.h | 42 +
|
|
src/st/meson.build | 62 +-
|
|
src/st/st-theme-node-private.h | 2 +-
|
|
src/st/st-theme-private.h | 2 +-
|
|
54 files changed, 24696 insertions(+), 7 deletions(-)
|
|
create mode 100644 src/st/croco/cr-additional-sel.c
|
|
create mode 100644 src/st/croco/cr-additional-sel.h
|
|
create mode 100644 src/st/croco/cr-attr-sel.c
|
|
create mode 100644 src/st/croco/cr-attr-sel.h
|
|
create mode 100644 src/st/croco/cr-cascade.c
|
|
create mode 100644 src/st/croco/cr-cascade.h
|
|
create mode 100644 src/st/croco/cr-declaration.c
|
|
create mode 100644 src/st/croco/cr-declaration.h
|
|
create mode 100644 src/st/croco/cr-doc-handler.c
|
|
create mode 100644 src/st/croco/cr-doc-handler.h
|
|
create mode 100644 src/st/croco/cr-enc-handler.c
|
|
create mode 100644 src/st/croco/cr-enc-handler.h
|
|
create mode 100644 src/st/croco/cr-fonts.c
|
|
create mode 100644 src/st/croco/cr-fonts.h
|
|
create mode 100644 src/st/croco/cr-input.c
|
|
create mode 100644 src/st/croco/cr-input.h
|
|
create mode 100644 src/st/croco/cr-num.c
|
|
create mode 100644 src/st/croco/cr-num.h
|
|
create mode 100644 src/st/croco/cr-om-parser.c
|
|
create mode 100644 src/st/croco/cr-om-parser.h
|
|
create mode 100644 src/st/croco/cr-parser.c
|
|
create mode 100644 src/st/croco/cr-parser.h
|
|
create mode 100644 src/st/croco/cr-parsing-location.c
|
|
create mode 100644 src/st/croco/cr-parsing-location.h
|
|
create mode 100644 src/st/croco/cr-prop-list.c
|
|
create mode 100644 src/st/croco/cr-prop-list.h
|
|
create mode 100644 src/st/croco/cr-pseudo.c
|
|
create mode 100644 src/st/croco/cr-pseudo.h
|
|
create mode 100644 src/st/croco/cr-rgb.c
|
|
create mode 100644 src/st/croco/cr-rgb.h
|
|
create mode 100644 src/st/croco/cr-selector.c
|
|
create mode 100644 src/st/croco/cr-selector.h
|
|
create mode 100644 src/st/croco/cr-simple-sel.c
|
|
create mode 100644 src/st/croco/cr-simple-sel.h
|
|
create mode 100644 src/st/croco/cr-statement.c
|
|
create mode 100644 src/st/croco/cr-statement.h
|
|
create mode 100644 src/st/croco/cr-string.c
|
|
create mode 100644 src/st/croco/cr-string.h
|
|
create mode 100644 src/st/croco/cr-stylesheet.c
|
|
create mode 100644 src/st/croco/cr-stylesheet.h
|
|
create mode 100644 src/st/croco/cr-term.c
|
|
create mode 100644 src/st/croco/cr-term.h
|
|
create mode 100644 src/st/croco/cr-tknzr.c
|
|
create mode 100644 src/st/croco/cr-tknzr.h
|
|
create mode 100644 src/st/croco/cr-token.c
|
|
create mode 100644 src/st/croco/cr-token.h
|
|
create mode 100644 src/st/croco/cr-utils.c
|
|
create mode 100644 src/st/croco/cr-utils.h
|
|
create mode 100644 src/st/croco/libcroco-config.h
|
|
create mode 100644 src/st/croco/libcroco.h
|
|
|
|
diff --git a/meson.build b/meson.build
|
|
index bfe4ee8a6..9c6d5b946 100644
|
|
--- a/meson.build
|
|
+++ b/meson.build
|
|
@@ -13,7 +13,6 @@ cogl_pc = 'mutter-cogl-' + mutter_api_version
|
|
cogl_pango_pc = 'mutter-cogl-pango-' + mutter_api_version
|
|
libmutter_pc = 'libmutter-' + mutter_api_version
|
|
|
|
-croco_req = '>= 0.6.8'
|
|
ecal_req = '>= 3.5.3'
|
|
eds_req = '>= 3.17.2'
|
|
gcr_req = '>= 3.7.5'
|
|
@@ -89,7 +88,6 @@ gio_unix_dep = dependency('gio-unix-2.0', version: gio_req)
|
|
gjs_dep = dependency('gjs-1.0', version: gjs_req)
|
|
gtk_dep = dependency('gtk+-3.0', version: gtk_req)
|
|
libxml_dep = dependency('libxml-2.0')
|
|
-croco_dep = dependency('libcroco-0.6', version: croco_req)
|
|
clutter_dep = dependency(clutter_pc, version: mutter_req)
|
|
cogl_dep = dependency(cogl_pc, version: mutter_req)
|
|
cogl_pango_dep = dependency(cogl_pango_pc, version: mutter_req)
|
|
diff --git a/src/st/croco/cr-additional-sel.c b/src/st/croco/cr-additional-sel.c
|
|
new file mode 100644
|
|
index 000000000..c34b8d243
|
|
--- /dev/null
|
|
+++ b/src/st/croco/cr-additional-sel.c
|
|
@@ -0,0 +1,500 @@
|
|
+/* -*- 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 "cr-additional-sel.h"
|
|
+#include "string.h"
|
|
+
|
|
+/**
|
|
+ * CRAdditionalSel:
|
|
+ *
|
|
+ * #CRAdditionalSel abstracts an additionnal selector.
|
|
+ * An additional selector is the selector part
|
|
+ * that comes after the combination of type selectors.
|
|
+ * It can be either "a class selector (the .class part),
|
|
+ * a pseudo class selector, an attribute selector
|
|
+ * or an id selector.
|
|
+ */
|
|
+
|
|
+/**
|
|
+ * cr_additional_sel_new:
|
|
+ *
|
|
+ * Default constructor of #CRAdditionalSel.
|
|
+ * Returns the newly build instance of #CRAdditionalSel.
|
|
+ */
|
|
+CRAdditionalSel *
|
|
+cr_additional_sel_new (void)
|
|
+{
|
|
+ CRAdditionalSel *result = NULL;
|
|
+
|
|
+ result = g_try_malloc (sizeof (CRAdditionalSel));
|
|
+
|
|
+ if (result == NULL) {
|
|
+ cr_utils_trace_debug ("Out of memory");
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
+ memset (result, 0, sizeof (CRAdditionalSel));
|
|
+
|
|
+ return result;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_additional_sel_new_with_type:
|
|
+ * @a_sel_type: the type of the newly built instance
|
|
+ * of #CRAdditionalSel.
|
|
+ *
|
|
+ * Constructor of #CRAdditionalSel.
|
|
+ * Returns the newly built instance of #CRAdditionalSel.
|
|
+ */
|
|
+CRAdditionalSel *
|
|
+cr_additional_sel_new_with_type (enum AddSelectorType a_sel_type)
|
|
+{
|
|
+ CRAdditionalSel *result = NULL;
|
|
+
|
|
+ result = cr_additional_sel_new ();
|
|
+
|
|
+ g_return_val_if_fail (result, NULL);
|
|
+
|
|
+ result->type = a_sel_type;
|
|
+
|
|
+ return result;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_additional_sel_set_class_name:
|
|
+ * @a_this: the "this pointer" of the current instance
|
|
+ * of #CRAdditionalSel .
|
|
+ * @a_class_name: the new class name to set.
|
|
+ *
|
|
+ * Sets a new class name to a
|
|
+ * CLASS additional selector.
|
|
+ */
|
|
+void
|
|
+cr_additional_sel_set_class_name (CRAdditionalSel * a_this,
|
|
+ CRString * a_class_name)
|
|
+{
|
|
+ g_return_if_fail (a_this && a_this->type == CLASS_ADD_SELECTOR);
|
|
+
|
|
+ if (a_this->content.class_name) {
|
|
+ cr_string_destroy (a_this->content.class_name);
|
|
+ }
|
|
+
|
|
+ a_this->content.class_name = a_class_name;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_additional_sel_set_id_name:
|
|
+ * @a_this: the "this pointer" of the current instance
|
|
+ * of #CRAdditionalSel .
|
|
+ * @a_id: the new id to set.
|
|
+ *
|
|
+ * Sets a new id name to an
|
|
+ * ID additional selector.
|
|
+ */
|
|
+void
|
|
+cr_additional_sel_set_id_name (CRAdditionalSel * a_this, CRString * a_id)
|
|
+{
|
|
+ g_return_if_fail (a_this && a_this->type == ID_ADD_SELECTOR);
|
|
+
|
|
+ if (a_this->content.id_name) {
|
|
+ cr_string_destroy (a_this->content.id_name);
|
|
+ }
|
|
+
|
|
+ a_this->content.id_name = a_id;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_additional_sel_set_pseudo:
|
|
+ * @a_this: the "this pointer" of the current instance
|
|
+ * of #CRAdditionalSel .
|
|
+ * @a_pseudo: the new pseudo to set.
|
|
+ *
|
|
+ * Sets a new pseudo to a
|
|
+ * PSEUDO additional selector.
|
|
+ */
|
|
+void
|
|
+cr_additional_sel_set_pseudo (CRAdditionalSel * a_this, CRPseudo * a_pseudo)
|
|
+{
|
|
+ g_return_if_fail (a_this
|
|
+ && a_this->type == PSEUDO_CLASS_ADD_SELECTOR);
|
|
+
|
|
+ if (a_this->content.pseudo) {
|
|
+ cr_pseudo_destroy (a_this->content.pseudo);
|
|
+ }
|
|
+
|
|
+ a_this->content.pseudo = a_pseudo;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_additional_sel_set_attr_sel:
|
|
+ * @a_this: the "this pointer" of the current instance
|
|
+ * of #CRAdditionalSel .
|
|
+ * @a_sel: the new instance of #CRAttrSel to set.
|
|
+ *
|
|
+ * Sets a new instance of #CRAttrSel to
|
|
+ * a ATTRIBUTE additional selector.
|
|
+ */
|
|
+void
|
|
+cr_additional_sel_set_attr_sel (CRAdditionalSel * a_this, CRAttrSel * a_sel)
|
|
+{
|
|
+ g_return_if_fail (a_this && a_this->type == ATTRIBUTE_ADD_SELECTOR);
|
|
+
|
|
+ if (a_this->content.attr_sel) {
|
|
+ cr_attr_sel_destroy (a_this->content.attr_sel);
|
|
+ }
|
|
+
|
|
+ a_this->content.attr_sel = a_sel;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_additional_sel_append:
|
|
+ * @a_this: the "this pointer" of the current instance
|
|
+ * of #CRAdditionalSel .
|
|
+ * @a_sel: the new instance to #CRAdditional to append.
|
|
+ *
|
|
+ * Appends a new instance of #CRAdditional to the
|
|
+ * current list of #CRAdditional.
|
|
+ *
|
|
+ * Returns the new list of CRAdditionalSel or NULL if an error arises.
|
|
+ */
|
|
+CRAdditionalSel *
|
|
+cr_additional_sel_append (CRAdditionalSel * a_this, CRAdditionalSel * a_sel)
|
|
+{
|
|
+ CRAdditionalSel *cur_sel = NULL;
|
|
+
|
|
+ g_return_val_if_fail (a_sel, NULL);
|
|
+
|
|
+ if (a_this == NULL) {
|
|
+ return a_sel;
|
|
+ }
|
|
+
|
|
+ if (a_sel == NULL)
|
|
+ return NULL;
|
|
+
|
|
+ for (cur_sel = a_this;
|
|
+ cur_sel && cur_sel->next; cur_sel = cur_sel->next) ;
|
|
+
|
|
+ g_return_val_if_fail (cur_sel != NULL, NULL);
|
|
+
|
|
+ cur_sel->next = a_sel;
|
|
+ a_sel->prev = cur_sel;
|
|
+
|
|
+ return a_this;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_additional_sel_prepend:
|
|
+ * @a_this: the "this pointer" of the current instance
|
|
+ * of #CRAdditionalSel .
|
|
+ * @a_sel: the new instance to #CRAdditional to preappend.
|
|
+ *
|
|
+ * Preppends a new instance of #CRAdditional to the
|
|
+ * current list of #CRAdditional.
|
|
+ *
|
|
+ * Returns the new list of CRAdditionalSel or NULL if an error arises.
|
|
+ */
|
|
+CRAdditionalSel *
|
|
+cr_additional_sel_prepend (CRAdditionalSel * a_this, CRAdditionalSel * a_sel)
|
|
+{
|
|
+ g_return_val_if_fail (a_sel, NULL);
|
|
+
|
|
+ if (a_this == NULL) {
|
|
+ return a_sel;
|
|
+ }
|
|
+
|
|
+ a_sel->next = a_this;
|
|
+ a_this->prev = a_sel;
|
|
+
|
|
+ return a_sel;
|
|
+}
|
|
+
|
|
+guchar *
|
|
+cr_additional_sel_to_string (CRAdditionalSel const * a_this)
|
|
+{
|
|
+ guchar *result = NULL;
|
|
+ GString *str_buf = NULL;
|
|
+ CRAdditionalSel const *cur = NULL;
|
|
+
|
|
+ g_return_val_if_fail (a_this, NULL);
|
|
+
|
|
+ str_buf = g_string_new (NULL);
|
|
+
|
|
+ for (cur = a_this; cur; cur = cur->next) {
|
|
+ switch (cur->type) {
|
|
+ case CLASS_ADD_SELECTOR:
|
|
+ {
|
|
+ guchar *name = NULL;
|
|
+
|
|
+ if (cur->content.class_name) {
|
|
+ name = (guchar *) g_strndup
|
|
+ (cur->content.class_name->stryng->str,
|
|
+ cur->content.class_name->stryng->len);
|
|
+
|
|
+ if (name) {
|
|
+ g_string_append_printf
|
|
+ (str_buf, ".%s",
|
|
+ name);
|
|
+ g_free (name);
|
|
+ name = NULL;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case ID_ADD_SELECTOR:
|
|
+ {
|
|
+ guchar *name = NULL;
|
|
+
|
|
+ if (cur->content.id_name) {
|
|
+ name = (guchar *) g_strndup
|
|
+ (cur->content.id_name->stryng->str,
|
|
+ cur->content.id_name->stryng->len);
|
|
+
|
|
+ if (name) {
|
|
+ g_string_append_printf
|
|
+ (str_buf, "#%s",
|
|
+ name);
|
|
+ g_free (name);
|
|
+ name = NULL;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ break;
|
|
+
|
|
+ case PSEUDO_CLASS_ADD_SELECTOR:
|
|
+ {
|
|
+ if (cur->content.pseudo) {
|
|
+ guchar *tmp_str = NULL;
|
|
+
|
|
+ tmp_str = cr_pseudo_to_string
|
|
+ (cur->content.pseudo);
|
|
+ if (tmp_str) {
|
|
+ g_string_append_printf
|
|
+ (str_buf, ":%s",
|
|
+ tmp_str);
|
|
+ g_free (tmp_str);
|
|
+ tmp_str = NULL;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case ATTRIBUTE_ADD_SELECTOR:
|
|
+ if (cur->content.attr_sel) {
|
|
+ guchar *tmp_str = NULL;
|
|
+
|
|
+ g_string_append_c (str_buf, '[');
|
|
+ tmp_str = cr_attr_sel_to_string
|
|
+ (cur->content.attr_sel);
|
|
+ if (tmp_str) {
|
|
+ g_string_append_printf
|
|
+ (str_buf, "%s]", tmp_str);
|
|
+ g_free (tmp_str);
|
|
+ tmp_str = NULL;
|
|
+ }
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (str_buf) {
|
|
+ result = (guchar *) str_buf->str;
|
|
+ g_string_free (str_buf, FALSE);
|
|
+ str_buf = NULL;
|
|
+ }
|
|
+
|
|
+ return result;
|
|
+}
|
|
+
|
|
+guchar *
|
|
+cr_additional_sel_one_to_string (CRAdditionalSel const *a_this)
|
|
+{
|
|
+ guchar *result = NULL;
|
|
+ GString *str_buf = NULL;
|
|
+
|
|
+ g_return_val_if_fail (a_this, NULL) ;
|
|
+
|
|
+ str_buf = g_string_new (NULL) ;
|
|
+
|
|
+ switch (a_this->type) {
|
|
+ case CLASS_ADD_SELECTOR:
|
|
+ {
|
|
+ guchar *name = NULL;
|
|
+
|
|
+ if (a_this->content.class_name) {
|
|
+ name = (guchar *) g_strndup
|
|
+ (a_this->content.class_name->stryng->str,
|
|
+ a_this->content.class_name->stryng->len);
|
|
+
|
|
+ if (name) {
|
|
+ g_string_append_printf
|
|
+ (str_buf, ".%s",
|
|
+ name);
|
|
+ g_free (name);
|
|
+ name = NULL;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case ID_ADD_SELECTOR:
|
|
+ {
|
|
+ guchar *name = NULL;
|
|
+
|
|
+ if (a_this->content.id_name) {
|
|
+ name = (guchar *) g_strndup
|
|
+ (a_this->content.id_name->stryng->str,
|
|
+ a_this->content.id_name->stryng->len);
|
|
+
|
|
+ if (name) {
|
|
+ g_string_append_printf
|
|
+ (str_buf, "#%s",
|
|
+ name);
|
|
+ g_free (name);
|
|
+ name = NULL;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ break;
|
|
+
|
|
+ case PSEUDO_CLASS_ADD_SELECTOR:
|
|
+ {
|
|
+ if (a_this->content.pseudo) {
|
|
+ guchar *tmp_str = NULL;
|
|
+
|
|
+ tmp_str = cr_pseudo_to_string
|
|
+ (a_this->content.pseudo);
|
|
+ if (tmp_str) {
|
|
+ g_string_append_printf
|
|
+ (str_buf, ":%s",
|
|
+ tmp_str);
|
|
+ g_free (tmp_str);
|
|
+ tmp_str = NULL;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case ATTRIBUTE_ADD_SELECTOR:
|
|
+ if (a_this->content.attr_sel) {
|
|
+ guchar *tmp_str = NULL;
|
|
+
|
|
+ g_string_append_printf (str_buf, "[");
|
|
+ tmp_str = cr_attr_sel_to_string
|
|
+ (a_this->content.attr_sel);
|
|
+ if (tmp_str) {
|
|
+ g_string_append_printf
|
|
+ (str_buf, "%s]", tmp_str);
|
|
+ g_free (tmp_str);
|
|
+ tmp_str = NULL;
|
|
+ }
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ if (str_buf) {
|
|
+ result = (guchar *) str_buf->str;
|
|
+ g_string_free (str_buf, FALSE);
|
|
+ str_buf = NULL;
|
|
+ }
|
|
+
|
|
+ return result;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_additional_sel_dump:
|
|
+ * @a_this: the "this pointer" of the current instance of
|
|
+ * #CRAdditionalSel.
|
|
+ * @a_fp: the destination file.
|
|
+ *
|
|
+ * Dumps the current instance of #CRAdditionalSel to a file
|
|
+ */
|
|
+void
|
|
+cr_additional_sel_dump (CRAdditionalSel const * a_this, FILE * a_fp)
|
|
+{
|
|
+ guchar *tmp_str = NULL;
|
|
+
|
|
+ g_return_if_fail (a_fp);
|
|
+
|
|
+ if (a_this) {
|
|
+ tmp_str = cr_additional_sel_to_string (a_this);
|
|
+ if (tmp_str) {
|
|
+ fprintf (a_fp, "%s", tmp_str);
|
|
+ g_free (tmp_str);
|
|
+ tmp_str = NULL;
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_additional_sel_destroy:
|
|
+ * @a_this: the "this pointer" of the current instance
|
|
+ * of #CRAdditionalSel .
|
|
+ *
|
|
+ * Destroys an instance of #CRAdditional.
|
|
+ */
|
|
+void
|
|
+cr_additional_sel_destroy (CRAdditionalSel * a_this)
|
|
+{
|
|
+ g_return_if_fail (a_this);
|
|
+
|
|
+ switch (a_this->type) {
|
|
+ case CLASS_ADD_SELECTOR:
|
|
+ cr_string_destroy (a_this->content.class_name);
|
|
+ a_this->content.class_name = NULL;
|
|
+ break;
|
|
+
|
|
+ case PSEUDO_CLASS_ADD_SELECTOR:
|
|
+ cr_pseudo_destroy (a_this->content.pseudo);
|
|
+ a_this->content.pseudo = NULL;
|
|
+ break;
|
|
+
|
|
+ case ID_ADD_SELECTOR:
|
|
+ cr_string_destroy (a_this->content.id_name);
|
|
+ a_this->content.id_name = NULL;
|
|
+ break;
|
|
+
|
|
+ case ATTRIBUTE_ADD_SELECTOR:
|
|
+ cr_attr_sel_destroy (a_this->content.attr_sel);
|
|
+ a_this->content.attr_sel = NULL;
|
|
+ break;
|
|
+
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ if (a_this->next) {
|
|
+ cr_additional_sel_destroy (a_this->next);
|
|
+ }
|
|
+
|
|
+ g_free (a_this);
|
|
+}
|
|
diff --git a/src/st/croco/cr-additional-sel.h b/src/st/croco/cr-additional-sel.h
|
|
new file mode 100644
|
|
index 000000000..7ca3e07d5
|
|
--- /dev/null
|
|
+++ b/src/st/croco/cr-additional-sel.h
|
|
@@ -0,0 +1,98 @@
|
|
+/* -*- 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 the COPYRIGHTS file for copyright information.
|
|
+ */
|
|
+
|
|
+
|
|
+#ifndef __CR_ADD_SEL_H__
|
|
+#define __CR_ADD_SEL_H__
|
|
+
|
|
+#include <stdio.h>
|
|
+#include <glib.h>
|
|
+#include "cr-utils.h"
|
|
+#include "cr-attr-sel.h"
|
|
+#include "cr-pseudo.h"
|
|
+#include "cr-additional-sel.h"
|
|
+
|
|
+G_BEGIN_DECLS
|
|
+
|
|
+enum AddSelectorType
|
|
+{
|
|
+ NO_ADD_SELECTOR = 0 ,
|
|
+ CLASS_ADD_SELECTOR = 1 ,
|
|
+ PSEUDO_CLASS_ADD_SELECTOR = 1 << 1,
|
|
+ ID_ADD_SELECTOR = 1 << 3,
|
|
+ ATTRIBUTE_ADD_SELECTOR = 1 << 4
|
|
+} ;
|
|
+
|
|
+union CRAdditionalSelectorContent
|
|
+{
|
|
+ CRString *class_name ;
|
|
+ CRString *id_name ;
|
|
+ CRPseudo *pseudo ;
|
|
+ CRAttrSel *attr_sel ;
|
|
+} ;
|
|
+
|
|
+typedef struct _CRAdditionalSel CRAdditionalSel ;
|
|
+
|
|
+struct _CRAdditionalSel
|
|
+{
|
|
+ enum AddSelectorType type ;
|
|
+ union CRAdditionalSelectorContent content ;
|
|
+
|
|
+ CRAdditionalSel * next ;
|
|
+ CRAdditionalSel * prev ;
|
|
+ CRParsingLocation location ;
|
|
+} ;
|
|
+
|
|
+CRAdditionalSel * cr_additional_sel_new (void) ;
|
|
+
|
|
+CRAdditionalSel * cr_additional_sel_new_with_type (enum AddSelectorType a_sel_type) ;
|
|
+
|
|
+CRAdditionalSel * cr_additional_sel_append (CRAdditionalSel *a_this,
|
|
+ CRAdditionalSel *a_sel) ;
|
|
+
|
|
+void cr_additional_sel_set_class_name (CRAdditionalSel *a_this,
|
|
+ CRString *a_class_name) ;
|
|
+
|
|
+void cr_additional_sel_set_id_name (CRAdditionalSel *a_this,
|
|
+ CRString *a_id) ;
|
|
+
|
|
+void cr_additional_sel_set_pseudo (CRAdditionalSel *a_this,
|
|
+ CRPseudo *a_pseudo) ;
|
|
+
|
|
+void cr_additional_sel_set_attr_sel (CRAdditionalSel *a_this,
|
|
+ CRAttrSel *a_sel) ;
|
|
+
|
|
+CRAdditionalSel * cr_additional_sel_prepend (CRAdditionalSel *a_this,
|
|
+ CRAdditionalSel *a_sel) ;
|
|
+
|
|
+guchar * cr_additional_sel_to_string (CRAdditionalSel const *a_this) ;
|
|
+
|
|
+guchar * cr_additional_sel_one_to_string (CRAdditionalSel const *a_this) ;
|
|
+
|
|
+void cr_additional_sel_dump (CRAdditionalSel const *a_this, FILE *a_fp) ;
|
|
+
|
|
+void cr_additional_sel_destroy (CRAdditionalSel *a_this) ;
|
|
+
|
|
+G_END_DECLS
|
|
+
|
|
+#endif /*__CR_ADD_SEL_H*/
|
|
diff --git a/src/st/croco/cr-attr-sel.c b/src/st/croco/cr-attr-sel.c
|
|
new file mode 100644
|
|
index 000000000..c057bbbf6
|
|
--- /dev/null
|
|
+++ b/src/st/croco/cr-attr-sel.c
|
|
@@ -0,0 +1,235 @@
|
|
+/* -*- 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
|
|
+ *
|
|
+ * See COPYRIGHTS file for copyrights information.
|
|
+ */
|
|
+
|
|
+#include <stdio.h>
|
|
+#include "cr-attr-sel.h"
|
|
+
|
|
+/**
|
|
+ * CRAttrSel:
|
|
+ *
|
|
+ * #CRAdditionalSel abstracts an attribute selector.
|
|
+ * Attributes selectors are described in the css2 spec [5.8].
|
|
+ * There are more generally used in the css2 selectors described in
|
|
+ * css2 spec [5] .
|
|
+ */
|
|
+
|
|
+/**
|
|
+ * cr_attr_sel_new:
|
|
+ * The constructor of #CRAttrSel.
|
|
+ * Returns the newly allocated instance
|
|
+ * of #CRAttrSel.
|
|
+ */
|
|
+CRAttrSel *
|
|
+cr_attr_sel_new (void)
|
|
+{
|
|
+ CRAttrSel *result = NULL;
|
|
+
|
|
+ result = g_malloc0 (sizeof (CRAttrSel));
|
|
+
|
|
+ return result;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_attr_sel_append_attr_sel:
|
|
+ * @a_this: the this pointer of the current instance of #CRAttrSel.
|
|
+ * @a_attr_sel: selector to append.
|
|
+ *
|
|
+ * Appends an attribute selector to the current list of
|
|
+ * attribute selectors represented by a_this.
|
|
+ * Returns CR_OK upon successfull completion, an error code otherwise.
|
|
+ */
|
|
+enum CRStatus
|
|
+cr_attr_sel_append_attr_sel (CRAttrSel * a_this, CRAttrSel * a_attr_sel)
|
|
+{
|
|
+ CRAttrSel *cur_sel = NULL;
|
|
+
|
|
+ g_return_val_if_fail (a_this && a_attr_sel,
|
|
+ CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ for (cur_sel = a_this;
|
|
+ cur_sel->next;
|
|
+ cur_sel = cur_sel->next) ;
|
|
+
|
|
+ cur_sel->next = a_attr_sel;
|
|
+ a_attr_sel->prev = cur_sel;
|
|
+
|
|
+ return CR_OK;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_attr_sel_prepend_attr_sel:
|
|
+ *@a_this: the "this pointer" of the current instance *of #CRAttrSel.
|
|
+ *@a_attr_sel: the attribute selector to append.
|
|
+ *
|
|
+ *Prepends an attribute selector to the list of
|
|
+ *attributes selector represented by a_this.
|
|
+ *Returns CR_OK upon successfull completion, an error code otherwise.
|
|
+ */
|
|
+enum CRStatus
|
|
+cr_attr_sel_prepend_attr_sel (CRAttrSel * a_this,
|
|
+ CRAttrSel * a_attr_sel)
|
|
+{
|
|
+ g_return_val_if_fail (a_this && a_attr_sel,
|
|
+ CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ a_attr_sel->next = a_this;
|
|
+ a_this->prev = a_attr_sel;
|
|
+
|
|
+ return CR_OK;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_attr_sel_to_string:
|
|
+ * @a_this: the current instance of #CRAttrSel.
|
|
+ *
|
|
+ * Serializes an attribute selector into a string
|
|
+ * Returns the serialized attribute selector.
|
|
+ */
|
|
+guchar *
|
|
+cr_attr_sel_to_string (CRAttrSel const * a_this)
|
|
+{
|
|
+ CRAttrSel const *cur = NULL;
|
|
+ guchar *result = NULL;
|
|
+ GString *str_buf = NULL;
|
|
+
|
|
+ g_return_val_if_fail (a_this, NULL);
|
|
+
|
|
+ str_buf = g_string_new (NULL);
|
|
+
|
|
+ for (cur = a_this; cur; cur = cur->next) {
|
|
+ if (cur->prev) {
|
|
+ g_string_append_c (str_buf, ' ');
|
|
+ }
|
|
+
|
|
+ if (cur->name) {
|
|
+ guchar *name = NULL;
|
|
+
|
|
+ name = (guchar *) g_strndup (cur->name->stryng->str,
|
|
+ cur->name->stryng->len);
|
|
+ if (name) {
|
|
+ g_string_append (str_buf, (const gchar *) name);
|
|
+ g_free (name);
|
|
+ name = NULL;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (cur->value) {
|
|
+ guchar *value = NULL;
|
|
+
|
|
+ value = (guchar *) g_strndup (cur->value->stryng->str,
|
|
+ cur->value->stryng->len);
|
|
+ if (value) {
|
|
+ switch (cur->match_way) {
|
|
+ case SET:
|
|
+ break;
|
|
+
|
|
+ case EQUALS:
|
|
+ g_string_append_c (str_buf, '=');
|
|
+ break;
|
|
+
|
|
+ case INCLUDES:
|
|
+ g_string_append (str_buf, "~=");
|
|
+ break;
|
|
+
|
|
+ case DASHMATCH:
|
|
+ g_string_append (str_buf, "|=");
|
|
+ break;
|
|
+
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ g_string_append_printf
|
|
+ (str_buf, "\"%s\"", value);
|
|
+
|
|
+ g_free (value);
|
|
+ value = NULL;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (str_buf) {
|
|
+ result = (guchar *) str_buf->str;
|
|
+ g_string_free (str_buf, FALSE);
|
|
+ }
|
|
+
|
|
+ return result;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_attr_sel_dump:
|
|
+ * @a_this: the "this pointer" of the current instance of
|
|
+ * #CRAttrSel.
|
|
+ * @a_fp: the destination file.
|
|
+ *
|
|
+ * Dumps the current instance of #CRAttrSel to a file.
|
|
+ */
|
|
+void
|
|
+cr_attr_sel_dump (CRAttrSel const * a_this, FILE * a_fp)
|
|
+{
|
|
+ guchar *tmp_str = NULL;
|
|
+
|
|
+ g_return_if_fail (a_this);
|
|
+
|
|
+ tmp_str = cr_attr_sel_to_string (a_this);
|
|
+
|
|
+ if (tmp_str) {
|
|
+ fprintf (a_fp, "%s", tmp_str);
|
|
+ g_free (tmp_str);
|
|
+ tmp_str = NULL;
|
|
+ }
|
|
+}
|
|
+
|
|
+/**
|
|
+ *cr_attr_sel_destroy:
|
|
+ *@a_this: the "this pointer" of the current
|
|
+ *instance of #CRAttrSel.
|
|
+ *
|
|
+ *Destroys the current instance of #CRAttrSel.
|
|
+ *Frees all the fields if they are non null.
|
|
+ */
|
|
+void
|
|
+cr_attr_sel_destroy (CRAttrSel * a_this)
|
|
+{
|
|
+ g_return_if_fail (a_this);
|
|
+
|
|
+ if (a_this->name) {
|
|
+ cr_string_destroy (a_this->name);
|
|
+ a_this->name = NULL;
|
|
+ }
|
|
+
|
|
+ if (a_this->value) {
|
|
+ cr_string_destroy (a_this->value);
|
|
+ a_this->value = NULL;
|
|
+ }
|
|
+
|
|
+ if (a_this->next) {
|
|
+ cr_attr_sel_destroy (a_this->next);
|
|
+ a_this->next = NULL;
|
|
+ }
|
|
+
|
|
+ if (a_this) {
|
|
+ g_free (a_this);
|
|
+ a_this = NULL;
|
|
+ }
|
|
+}
|
|
+
|
|
diff --git a/src/st/croco/cr-attr-sel.h b/src/st/croco/cr-attr-sel.h
|
|
new file mode 100644
|
|
index 000000000..82d5a87d7
|
|
--- /dev/null
|
|
+++ b/src/st/croco/cr-attr-sel.h
|
|
@@ -0,0 +1,74 @@
|
|
+/* -*- 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.
|
|
+ */
|
|
+
|
|
+#ifndef __CR_ATTR_SEL_H__
|
|
+#define __CR_ATTR_SEL_H__
|
|
+
|
|
+#include <stdio.h>
|
|
+#include <glib.h>
|
|
+#include "cr-utils.h"
|
|
+#include "cr-parsing-location.h"
|
|
+#include "cr-string.h"
|
|
+
|
|
+G_BEGIN_DECLS
|
|
+
|
|
+
|
|
+struct _CRAttrSel ;
|
|
+typedef struct _CRAttrSel CRAttrSel ;
|
|
+
|
|
+enum AttrMatchWay
|
|
+{
|
|
+ NO_MATCH = 0,
|
|
+ SET,
|
|
+ EQUALS,
|
|
+ INCLUDES,
|
|
+ DASHMATCH
|
|
+} ;
|
|
+
|
|
+struct _CRAttrSel
|
|
+{
|
|
+ CRString *name ;
|
|
+ CRString *value ;
|
|
+ enum AttrMatchWay match_way ;
|
|
+ CRAttrSel *next ;
|
|
+ CRAttrSel *prev ;
|
|
+ CRParsingLocation location ;
|
|
+} ;
|
|
+
|
|
+CRAttrSel * cr_attr_sel_new (void) ;
|
|
+
|
|
+enum CRStatus cr_attr_sel_append_attr_sel (CRAttrSel * a_this,
|
|
+ CRAttrSel *a_attr_sel) ;
|
|
+
|
|
+enum CRStatus cr_attr_sel_prepend_attr_sel (CRAttrSel *a_this,
|
|
+ CRAttrSel *a_attr_sel) ;
|
|
+
|
|
+guchar * cr_attr_sel_to_string (CRAttrSel const *a_this) ;
|
|
+
|
|
+void cr_attr_sel_dump (CRAttrSel const *a_this, FILE *a_fp) ;
|
|
+
|
|
+void cr_attr_sel_destroy (CRAttrSel *a_this) ;
|
|
+
|
|
+G_END_DECLS
|
|
+
|
|
+#endif /*__CR_ATTR_SEL_H__*/
|
|
diff --git a/src/st/croco/cr-cascade.c b/src/st/croco/cr-cascade.c
|
|
new file mode 100644
|
|
index 000000000..b8f827716
|
|
--- /dev/null
|
|
+++ b/src/st/croco/cr-cascade.c
|
|
@@ -0,0 +1,215 @@
|
|
+/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */
|
|
+
|
|
+/*
|
|
+ * This file is part of The Croco Library
|
|
+ *
|
|
+ * Copyright (C) 2002-2003 Dodji Seketeli <dodji@seketeli.org>
|
|
+ *
|
|
+ * 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
|
|
+ */
|
|
+
|
|
+/*
|
|
+ *$Id$
|
|
+ */
|
|
+
|
|
+#include <string.h>
|
|
+#include "cr-cascade.h"
|
|
+
|
|
+#define PRIVATE(a_this) ((a_this)->priv)
|
|
+
|
|
+struct _CRCascadePriv {
|
|
+ /**
|
|
+ *the 3 style sheets of the cascade:
|
|
+ *author, user, and useragent sheet.
|
|
+ *Intended to be addressed by
|
|
+ *sheets[ORIGIN_AUTHOR] or sheets[ORIGIN_USER]
|
|
+ *of sheets[ORIGIN_UA] ;
|
|
+ */
|
|
+ CRStyleSheet *sheets[3];
|
|
+ guint ref_count;
|
|
+};
|
|
+
|
|
+/**
|
|
+ * cr_cascade_new:
|
|
+ *@a_author_sheet: the author origin style sheet. May be NULL.
|
|
+ *@a_user_sheet: the user origin style sheet. May be NULL.
|
|
+ *@a_ua_sheet: the user agent origin style sheet. May be NULL.
|
|
+ *
|
|
+ *Constructor of the #CRCascade class.
|
|
+ *Note that all three parameters of this
|
|
+ *method are ref counted and their refcount is increased.
|
|
+ *Their refcount will be decreased at the destruction of
|
|
+ *the instance of #CRCascade.
|
|
+ *So the caller should not call their destructor. The caller
|
|
+ *should call their ref/unref method instead if it wants
|
|
+ *
|
|
+ *Returns the newly built instance of CRCascade or NULL if
|
|
+ *an error arose during constrution.
|
|
+ */
|
|
+CRCascade *
|
|
+cr_cascade_new (CRStyleSheet * a_author_sheet,
|
|
+ CRStyleSheet * a_user_sheet, CRStyleSheet * a_ua_sheet)
|
|
+{
|
|
+ CRCascade *result = NULL;
|
|
+
|
|
+ result = g_try_malloc (sizeof (CRCascade));
|
|
+ if (!result) {
|
|
+ cr_utils_trace_info ("Out of memory");
|
|
+ return NULL;
|
|
+ }
|
|
+ memset (result, 0, sizeof (CRCascade));
|
|
+
|
|
+ PRIVATE (result) = g_try_malloc (sizeof (CRCascadePriv));
|
|
+ if (!PRIVATE (result)) {
|
|
+ cr_utils_trace_info ("Out of memory");
|
|
+ g_free (result);
|
|
+ return NULL;
|
|
+ }
|
|
+ memset (PRIVATE (result), 0, sizeof (CRCascadePriv));
|
|
+
|
|
+ if (a_author_sheet) {
|
|
+ cr_cascade_set_sheet (result, a_author_sheet, ORIGIN_AUTHOR);
|
|
+ }
|
|
+ if (a_user_sheet) {
|
|
+ cr_cascade_set_sheet (result, a_user_sheet, ORIGIN_USER);
|
|
+ }
|
|
+ if (a_ua_sheet) {
|
|
+ cr_cascade_set_sheet (result, a_ua_sheet, ORIGIN_UA);
|
|
+ }
|
|
+
|
|
+ return result;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_cascade_get_sheet:
|
|
+ *@a_this: the current instance of #CRCascade.
|
|
+ *@a_origin: the origin of the style sheet as
|
|
+ *defined in the css2 spec in chapter 6.4.
|
|
+ *Gets a given origin sheet.
|
|
+ *
|
|
+ *Gets a sheet, part of the cascade.
|
|
+ *Note that the returned stylesheet
|
|
+ *is refcounted so if the caller wants
|
|
+ *to manage it's lifecycle, it must use
|
|
+ *cr_stylesheet_ref()/cr_stylesheet_unref() instead
|
|
+ *of the cr_stylesheet_destroy() method.
|
|
+ *Returns the style sheet, or NULL if it does not
|
|
+ *exist.
|
|
+ */
|
|
+CRStyleSheet *
|
|
+cr_cascade_get_sheet (CRCascade * a_this, enum CRStyleOrigin a_origin)
|
|
+{
|
|
+ g_return_val_if_fail (a_this
|
|
+ && a_origin >= ORIGIN_UA
|
|
+ && a_origin < NB_ORIGINS, NULL);
|
|
+
|
|
+ return PRIVATE (a_this)->sheets[a_origin];
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_cascade_set_sheet:
|
|
+ *@a_this: the current instance of #CRCascade.
|
|
+ *@a_sheet: the stylesheet to set.
|
|
+ *@a_origin: the origin of the stylesheet.
|
|
+ *
|
|
+ *Sets a stylesheet in the cascade
|
|
+ *
|
|
+ *Returns CR_OK upon successfull completion, an error
|
|
+ *code otherwise.
|
|
+ */
|
|
+enum CRStatus
|
|
+cr_cascade_set_sheet (CRCascade * a_this,
|
|
+ CRStyleSheet * a_sheet, enum CRStyleOrigin a_origin)
|
|
+{
|
|
+ g_return_val_if_fail (a_this
|
|
+ && a_sheet
|
|
+ && a_origin >= ORIGIN_UA
|
|
+ && a_origin < NB_ORIGINS, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ if (PRIVATE (a_this)->sheets[a_origin])
|
|
+ cr_stylesheet_unref (PRIVATE (a_this)->sheets[a_origin]);
|
|
+ PRIVATE (a_this)->sheets[a_origin] = a_sheet;
|
|
+ cr_stylesheet_ref (a_sheet);
|
|
+ a_sheet->origin = a_origin;
|
|
+ return CR_OK;
|
|
+}
|
|
+
|
|
+/**
|
|
+ *cr_cascade_ref:
|
|
+ *@a_this: the current instance of #CRCascade
|
|
+ *
|
|
+ *Increases the reference counter of the current instance
|
|
+ *of #CRCascade.
|
|
+ */
|
|
+void
|
|
+cr_cascade_ref (CRCascade * a_this)
|
|
+{
|
|
+ g_return_if_fail (a_this && PRIVATE (a_this));
|
|
+
|
|
+ PRIVATE (a_this)->ref_count++;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_cascade_unref:
|
|
+ *@a_this: the current instance of
|
|
+ *#CRCascade.
|
|
+ *
|
|
+ *Decrements the reference counter associated
|
|
+ *to this instance of #CRCascade. If the reference
|
|
+ *counter reaches zero, the instance is destroyed
|
|
+ *using cr_cascade_destroy()
|
|
+ */
|
|
+void
|
|
+cr_cascade_unref (CRCascade * a_this)
|
|
+{
|
|
+ g_return_if_fail (a_this && PRIVATE (a_this));
|
|
+
|
|
+ if (PRIVATE (a_this)->ref_count)
|
|
+ PRIVATE (a_this)->ref_count--;
|
|
+ if (!PRIVATE (a_this)->ref_count) {
|
|
+ cr_cascade_destroy (a_this);
|
|
+ }
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_cascade_destroy:
|
|
+ * @a_this: the current instance of #CRCascade
|
|
+ *
|
|
+ * Destructor of #CRCascade.
|
|
+ */
|
|
+void
|
|
+cr_cascade_destroy (CRCascade * a_this)
|
|
+{
|
|
+ g_return_if_fail (a_this);
|
|
+
|
|
+ if (PRIVATE (a_this)) {
|
|
+ gulong i = 0;
|
|
+
|
|
+ for (i = 0; PRIVATE (a_this)->sheets && i < NB_ORIGINS; i++) {
|
|
+ if (PRIVATE (a_this)->sheets[i]) {
|
|
+ if (cr_stylesheet_unref
|
|
+ (PRIVATE (a_this)->sheets[i])
|
|
+ == TRUE) {
|
|
+ PRIVATE (a_this)->sheets[i] = NULL;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ g_free (PRIVATE (a_this));
|
|
+ PRIVATE (a_this) = NULL;
|
|
+ }
|
|
+ g_free (a_this);
|
|
+}
|
|
diff --git a/src/st/croco/cr-cascade.h b/src/st/croco/cr-cascade.h
|
|
new file mode 100644
|
|
index 000000000..3119ae85f
|
|
--- /dev/null
|
|
+++ b/src/st/croco/cr-cascade.h
|
|
@@ -0,0 +1,74 @@
|
|
+/* -*- 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
|
|
+ *
|
|
+ */
|
|
+
|
|
+/*
|
|
+ *$Id$
|
|
+ */
|
|
+
|
|
+#ifndef __CR_CASCADE_H__
|
|
+#define __CR_CASCADE_H__
|
|
+
|
|
+#include "cr-stylesheet.h"
|
|
+
|
|
+/**
|
|
+ *@file
|
|
+ *the declaration of the #CRCascade class.
|
|
+ */
|
|
+
|
|
+G_BEGIN_DECLS
|
|
+
|
|
+
|
|
+typedef struct _CRCascadePriv CRCascadePriv ;
|
|
+
|
|
+/**
|
|
+ *An abstraction of the "Cascade" defined
|
|
+ *in the css2 spec, chapter 6.4.
|
|
+ */
|
|
+typedef struct _CRCascade CRCascade ;
|
|
+
|
|
+struct _CRCascade
|
|
+{
|
|
+ CRCascadePriv *priv ;
|
|
+};
|
|
+
|
|
+
|
|
+CRCascade * cr_cascade_new (CRStyleSheet *a_author_sheet,
|
|
+ CRStyleSheet *a_user_sheet,
|
|
+ CRStyleSheet *a_ua_sheet) ;
|
|
+
|
|
+CRStyleSheet * cr_cascade_get_sheet (CRCascade *a_this,
|
|
+ enum CRStyleOrigin a_origin) ;
|
|
+
|
|
+enum CRStatus cr_cascade_set_sheet (CRCascade *a_this,
|
|
+ CRStyleSheet *a_sheet,
|
|
+ enum CRStyleOrigin a_origin) ;
|
|
+
|
|
+void cr_cascade_ref (CRCascade *a_this) ;
|
|
+
|
|
+void cr_cascade_unref (CRCascade *a_this) ;
|
|
+
|
|
+void cr_cascade_destroy (CRCascade *a_this) ;
|
|
+
|
|
+G_END_DECLS
|
|
+
|
|
+#endif /*__CR_CASCADE_H__*/
|
|
diff --git a/src/st/croco/cr-declaration.c b/src/st/croco/cr-declaration.c
|
|
new file mode 100644
|
|
index 000000000..2a13c8266
|
|
--- /dev/null
|
|
+++ b/src/st/croco/cr-declaration.c
|
|
@@ -0,0 +1,801 @@
|
|
+/* -*- 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-declaration.h"
|
|
+#include "cr-statement.h"
|
|
+#include "cr-parser.h"
|
|
+
|
|
+/**
|
|
+ *@CRDeclaration:
|
|
+ *
|
|
+ *The definition of the #CRDeclaration class.
|
|
+ */
|
|
+
|
|
+/**
|
|
+ * dump:
|
|
+ *@a_this: the current instance of #CRDeclaration.
|
|
+ *@a_fp: the destination file pointer.
|
|
+ *@a_indent: the number of indentation white char.
|
|
+ *
|
|
+ *Dumps (serializes) one css declaration to a file.
|
|
+ */
|
|
+static void
|
|
+dump (CRDeclaration const * a_this, FILE * a_fp, glong a_indent)
|
|
+{
|
|
+ guchar *str = NULL;
|
|
+
|
|
+ g_return_if_fail (a_this);
|
|
+
|
|
+ str = (guchar *) cr_declaration_to_string (a_this, a_indent);
|
|
+ if (str) {
|
|
+ fprintf (a_fp, "%s", str);
|
|
+ g_free (str);
|
|
+ str = NULL;
|
|
+ }
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_declaration_new:
|
|
+ * @a_statement: the statement this declaration belongs to. can be NULL.
|
|
+ *@a_property: the property string of the declaration
|
|
+ *@a_value: the value expression of the declaration.
|
|
+ *Constructor of #CRDeclaration.
|
|
+ *
|
|
+ *Returns the newly built instance of #CRDeclaration, or NULL in
|
|
+ *case of error.
|
|
+ *
|
|
+ *The returned CRDeclaration takes ownership of @a_property and @a_value.
|
|
+ *(E.g. cr_declaration_destroy on this CRDeclaration will also free
|
|
+ *@a_property and @a_value.)
|
|
+ */
|
|
+CRDeclaration *
|
|
+cr_declaration_new (CRStatement * a_statement,
|
|
+ CRString * a_property, CRTerm * a_value)
|
|
+{
|
|
+ CRDeclaration *result = NULL;
|
|
+
|
|
+ g_return_val_if_fail (a_property, NULL);
|
|
+
|
|
+ if (a_statement)
|
|
+ g_return_val_if_fail (a_statement
|
|
+ && ((a_statement->type == RULESET_STMT)
|
|
+ || (a_statement->type
|
|
+ == AT_FONT_FACE_RULE_STMT)
|
|
+ || (a_statement->type
|
|
+ == AT_PAGE_RULE_STMT)), NULL);
|
|
+
|
|
+ result = g_try_malloc (sizeof (CRDeclaration));
|
|
+ if (!result) {
|
|
+ cr_utils_trace_info ("Out of memory");
|
|
+ return NULL;
|
|
+ }
|
|
+ memset (result, 0, sizeof (CRDeclaration));
|
|
+ result->property = a_property;
|
|
+ result->value = a_value;
|
|
+
|
|
+ if (a_value) {
|
|
+ cr_term_ref (a_value);
|
|
+ }
|
|
+ result->parent_statement = a_statement;
|
|
+ return result;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_declaration_parse_from_buf:
|
|
+ *@a_statement: the parent css2 statement of this
|
|
+ *this declaration. Must be non NULL and of type
|
|
+ *RULESET_STMT (must be a ruleset).
|
|
+ *@a_str: the string that contains the statement.
|
|
+ *@a_enc: the encoding of a_str.
|
|
+ *
|
|
+ *Parses a text buffer that contains
|
|
+ *a css declaration.
|
|
+ *Returns the parsed declaration, or NULL in case of error.
|
|
+ */
|
|
+CRDeclaration *
|
|
+cr_declaration_parse_from_buf (CRStatement * a_statement,
|
|
+ const guchar * a_str, enum CREncoding a_enc)
|
|
+{
|
|
+ enum CRStatus status = CR_OK;
|
|
+ CRTerm *value = NULL;
|
|
+ CRString *property = NULL;
|
|
+ CRDeclaration *result = NULL;
|
|
+ CRParser *parser = NULL;
|
|
+ gboolean important = FALSE;
|
|
+
|
|
+ g_return_val_if_fail (a_str, NULL);
|
|
+ if (a_statement)
|
|
+ g_return_val_if_fail (a_statement->type == RULESET_STMT,
|
|
+ NULL);
|
|
+
|
|
+ parser = cr_parser_new_from_buf ((guchar*)a_str, strlen ((const char *) a_str), a_enc, FALSE);
|
|
+ g_return_val_if_fail (parser, NULL);
|
|
+
|
|
+ status = cr_parser_try_to_skip_spaces_and_comments (parser);
|
|
+ if (status != CR_OK)
|
|
+ goto cleanup;
|
|
+
|
|
+ status = cr_parser_parse_declaration (parser, &property,
|
|
+ &value, &important);
|
|
+ if (status != CR_OK || !property)
|
|
+ goto cleanup;
|
|
+
|
|
+ result = cr_declaration_new (a_statement, property, value);
|
|
+ if (result) {
|
|
+ property = NULL;
|
|
+ value = NULL;
|
|
+ result->important = important;
|
|
+ }
|
|
+
|
|
+ cleanup:
|
|
+
|
|
+ if (parser) {
|
|
+ cr_parser_destroy (parser);
|
|
+ parser = NULL;
|
|
+ }
|
|
+
|
|
+ if (property) {
|
|
+ cr_string_destroy (property);
|
|
+ property = NULL;
|
|
+ }
|
|
+
|
|
+ if (value) {
|
|
+ cr_term_destroy (value);
|
|
+ value = NULL;
|
|
+ }
|
|
+
|
|
+ return result;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_declaration_parse_list_from_buf:
|
|
+ *@a_str: the input buffer that contains the list of declaration to
|
|
+ *parse.
|
|
+ *@a_enc: the encoding of a_str
|
|
+ *
|
|
+ *Parses a ';' separated list of properties declaration.
|
|
+ *Returns the parsed list of declaration, NULL if parsing failed.
|
|
+ */
|
|
+CRDeclaration *
|
|
+cr_declaration_parse_list_from_buf (const guchar * a_str,
|
|
+ enum CREncoding a_enc)
|
|
+{
|
|
+
|
|
+ enum CRStatus status = CR_OK;
|
|
+ CRTerm *value = NULL;
|
|
+ CRString *property = NULL;
|
|
+ CRDeclaration *result = NULL,
|
|
+ *cur_decl = NULL;
|
|
+ CRParser *parser = NULL;
|
|
+ CRTknzr *tokenizer = NULL;
|
|
+ gboolean important = FALSE;
|
|
+
|
|
+ g_return_val_if_fail (a_str, NULL);
|
|
+
|
|
+ parser = cr_parser_new_from_buf ((guchar*)a_str, strlen ((const char *) a_str), a_enc, FALSE);
|
|
+ g_return_val_if_fail (parser, NULL);
|
|
+ status = cr_parser_get_tknzr (parser, &tokenizer);
|
|
+ if (status != CR_OK || !tokenizer) {
|
|
+ if (status == CR_OK)
|
|
+ status = CR_ERROR;
|
|
+ goto cleanup;
|
|
+ }
|
|
+ status = cr_parser_try_to_skip_spaces_and_comments (parser);
|
|
+ if (status != CR_OK)
|
|
+ goto cleanup;
|
|
+
|
|
+ status = cr_parser_parse_declaration (parser, &property,
|
|
+ &value, &important);
|
|
+ if (status != CR_OK || !property) {
|
|
+ if (status != CR_OK)
|
|
+ status = CR_ERROR;
|
|
+ goto cleanup;
|
|
+ }
|
|
+ result = cr_declaration_new (NULL, property, value);
|
|
+ if (result) {
|
|
+ property = NULL;
|
|
+ value = NULL;
|
|
+ result->important = important;
|
|
+ }
|
|
+ /*now, go parse the other declarations */
|
|
+ for (;;) {
|
|
+ guint32 c = 0;
|
|
+
|
|
+ cr_parser_try_to_skip_spaces_and_comments (parser);
|
|
+ status = cr_tknzr_peek_char (tokenizer, &c);
|
|
+ if (status != CR_OK) {
|
|
+ if (status == CR_END_OF_INPUT_ERROR)
|
|
+ status = CR_OK;
|
|
+ goto cleanup;
|
|
+ }
|
|
+ if (c == ';') {
|
|
+ status = cr_tknzr_read_char (tokenizer, &c);
|
|
+ } else {
|
|
+ break;
|
|
+ }
|
|
+ important = FALSE;
|
|
+ cr_parser_try_to_skip_spaces_and_comments (parser);
|
|
+ status = cr_parser_parse_declaration (parser, &property,
|
|
+ &value, &important);
|
|
+ if (status != CR_OK || !property) {
|
|
+ if (status == CR_END_OF_INPUT_ERROR) {
|
|
+ status = CR_OK;
|
|
+ }
|
|
+ break;
|
|
+ }
|
|
+ cur_decl = cr_declaration_new (NULL, property, value);
|
|
+ if (cur_decl) {
|
|
+ cur_decl->important = important;
|
|
+ result = cr_declaration_append (result, cur_decl);
|
|
+ property = NULL;
|
|
+ value = NULL;
|
|
+ cur_decl = NULL;
|
|
+ } else {
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ cleanup:
|
|
+
|
|
+ if (parser) {
|
|
+ cr_parser_destroy (parser);
|
|
+ parser = NULL;
|
|
+ }
|
|
+
|
|
+ if (property) {
|
|
+ cr_string_destroy (property);
|
|
+ property = NULL;
|
|
+ }
|
|
+
|
|
+ if (value) {
|
|
+ cr_term_destroy (value);
|
|
+ value = NULL;
|
|
+ }
|
|
+
|
|
+ if (status != CR_OK && result) {
|
|
+ cr_declaration_destroy (result);
|
|
+ result = NULL;
|
|
+ }
|
|
+ return result;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_declaration_append:
|
|
+ *@a_this: the current declaration list.
|
|
+ *@a_new: the declaration to append.
|
|
+ *
|
|
+ *Appends a new declaration to the current declarations list.
|
|
+ *Returns the declaration list with a_new appended to it, or NULL
|
|
+ *in case of error.
|
|
+ */
|
|
+CRDeclaration *
|
|
+cr_declaration_append (CRDeclaration * a_this, CRDeclaration * a_new)
|
|
+{
|
|
+ CRDeclaration *cur = NULL;
|
|
+
|
|
+ g_return_val_if_fail (a_new, NULL);
|
|
+
|
|
+ if (!a_this)
|
|
+ return a_new;
|
|
+
|
|
+ for (cur = a_this; cur && cur->next; cur = cur->next) ;
|
|
+
|
|
+ cur->next = a_new;
|
|
+ a_new->prev = cur;
|
|
+
|
|
+ return a_this;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_declaration_unlink:
|
|
+ *@a_decls: the declaration to unlink.
|
|
+ *
|
|
+ *Unlinks the declaration from the declaration list.
|
|
+ *case of a successfull completion, NULL otherwise.
|
|
+ *
|
|
+ *Returns a pointer to the unlinked declaration in
|
|
+ */
|
|
+CRDeclaration *
|
|
+cr_declaration_unlink (CRDeclaration * a_decl)
|
|
+{
|
|
+ CRDeclaration *result = a_decl;
|
|
+
|
|
+ g_return_val_if_fail (result, NULL);
|
|
+
|
|
+ /*
|
|
+ *some sanity checks first
|
|
+ */
|
|
+ if (a_decl->prev) {
|
|
+ g_return_val_if_fail (a_decl->prev->next == a_decl, NULL);
|
|
+
|
|
+ }
|
|
+ if (a_decl->next) {
|
|
+ g_return_val_if_fail (a_decl->next->prev == a_decl, NULL);
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ *now, the real unlinking job.
|
|
+ */
|
|
+ if (a_decl->prev) {
|
|
+ a_decl->prev->next = a_decl->next;
|
|
+ }
|
|
+ if (a_decl->next) {
|
|
+ a_decl->next->prev = a_decl->prev;
|
|
+ }
|
|
+ if (a_decl->parent_statement) {
|
|
+ CRDeclaration **children_decl_ptr = NULL;
|
|
+
|
|
+ switch (a_decl->parent_statement->type) {
|
|
+ case RULESET_STMT:
|
|
+ if (a_decl->parent_statement->kind.ruleset) {
|
|
+ children_decl_ptr =
|
|
+ &a_decl->parent_statement->
|
|
+ kind.ruleset->decl_list;
|
|
+ }
|
|
+
|
|
+ break;
|
|
+
|
|
+ case AT_FONT_FACE_RULE_STMT:
|
|
+ if (a_decl->parent_statement->kind.font_face_rule) {
|
|
+ children_decl_ptr =
|
|
+ &a_decl->parent_statement->
|
|
+ kind.font_face_rule->decl_list;
|
|
+ }
|
|
+ break;
|
|
+ case AT_PAGE_RULE_STMT:
|
|
+ if (a_decl->parent_statement->kind.page_rule) {
|
|
+ children_decl_ptr =
|
|
+ &a_decl->parent_statement->
|
|
+ kind.page_rule->decl_list;
|
|
+ }
|
|
+
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+ if (children_decl_ptr
|
|
+ && *children_decl_ptr && *children_decl_ptr == a_decl)
|
|
+ *children_decl_ptr = (*children_decl_ptr)->next;
|
|
+ }
|
|
+
|
|
+ a_decl->next = NULL;
|
|
+ a_decl->prev = NULL;
|
|
+ a_decl->parent_statement = NULL;
|
|
+
|
|
+ return result;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_declaration_prepend:
|
|
+ * @a_this: the current declaration list.
|
|
+ * @a_new: the declaration to prepend.
|
|
+ *
|
|
+ * prepends a declaration to the current declaration list.
|
|
+ *
|
|
+ * Returns the list with a_new prepended or NULL in case of error.
|
|
+ */
|
|
+CRDeclaration *
|
|
+cr_declaration_prepend (CRDeclaration * a_this, CRDeclaration * a_new)
|
|
+{
|
|
+ CRDeclaration *cur = NULL;
|
|
+
|
|
+ g_return_val_if_fail (a_new, NULL);
|
|
+
|
|
+ if (!a_this)
|
|
+ return a_new;
|
|
+
|
|
+ a_this->prev = a_new;
|
|
+ a_new->next = a_this;
|
|
+
|
|
+ for (cur = a_new; cur && cur->prev; cur = cur->prev) ;
|
|
+
|
|
+ return cur;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_declaration_append2:
|
|
+ *@a_this: the current declaration list.
|
|
+ *@a_prop: the property string of the declaration to append.
|
|
+ *@a_value: the value of the declaration to append.
|
|
+ *
|
|
+ *Appends a declaration to the current declaration list.
|
|
+ *Returns the list with the new property appended to it, or NULL in
|
|
+ *case of an error.
|
|
+ */
|
|
+CRDeclaration *
|
|
+cr_declaration_append2 (CRDeclaration * a_this,
|
|
+ CRString * a_prop, CRTerm * a_value)
|
|
+{
|
|
+ CRDeclaration *new_elem = NULL;
|
|
+
|
|
+ if (a_this) {
|
|
+ new_elem = cr_declaration_new (a_this->parent_statement,
|
|
+ a_prop, a_value);
|
|
+ } else {
|
|
+ new_elem = cr_declaration_new (NULL, a_prop, a_value);
|
|
+ }
|
|
+
|
|
+ g_return_val_if_fail (new_elem, NULL);
|
|
+
|
|
+ return cr_declaration_append (a_this, new_elem);
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_declaration_dump:
|
|
+ *@a_this: the current instance of #CRDeclaration.
|
|
+ *@a_fp: the destination file.
|
|
+ *@a_indent: the number of indentation white char.
|
|
+ *@a_one_per_line: whether to put one declaration per line of not .
|
|
+ *
|
|
+ *
|
|
+ *Dumps a declaration list to a file.
|
|
+ */
|
|
+void
|
|
+cr_declaration_dump (CRDeclaration const * a_this, FILE * a_fp, glong a_indent,
|
|
+ gboolean a_one_per_line)
|
|
+{
|
|
+ CRDeclaration const *cur = NULL;
|
|
+
|
|
+ g_return_if_fail (a_this);
|
|
+
|
|
+ for (cur = a_this; cur; cur = cur->next) {
|
|
+ if (cur->prev) {
|
|
+ if (a_one_per_line == TRUE)
|
|
+ fprintf (a_fp, ";\n");
|
|
+ else
|
|
+ fprintf (a_fp, "; ");
|
|
+ }
|
|
+ dump (cur, a_fp, a_indent);
|
|
+ }
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_declaration_dump_one:
|
|
+ *@a_this: the current instance of #CRDeclaration.
|
|
+ *@a_fp: the destination file.
|
|
+ *@a_indent: the number of indentation white char.
|
|
+ *
|
|
+ *Dumps the first declaration of the declaration list to a file.
|
|
+ */
|
|
+void
|
|
+cr_declaration_dump_one (CRDeclaration const * a_this, FILE * a_fp, glong a_indent)
|
|
+{
|
|
+ g_return_if_fail (a_this);
|
|
+
|
|
+ dump (a_this, a_fp, a_indent);
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_declaration_to_string:
|
|
+ *@a_this: the current instance of #CRDeclaration.
|
|
+ *@a_indent: the number of indentation white char
|
|
+ *to put before the actual serialisation.
|
|
+ *
|
|
+ *Serializes the declaration into a string
|
|
+ *Returns the serialized form the declaration. The caller must
|
|
+ *free the string using g_free().
|
|
+ */
|
|
+gchar *
|
|
+cr_declaration_to_string (CRDeclaration const * a_this, gulong a_indent)
|
|
+{
|
|
+ GString *stringue = NULL;
|
|
+
|
|
+ gchar *str = NULL,
|
|
+ *result = NULL;
|
|
+
|
|
+ g_return_val_if_fail (a_this, NULL);
|
|
+
|
|
+ stringue = g_string_new (NULL);
|
|
+
|
|
+ if (a_this->property
|
|
+ && a_this->property->stryng
|
|
+ && a_this->property->stryng->str) {
|
|
+ str = g_strndup (a_this->property->stryng->str,
|
|
+ a_this->property->stryng->len);
|
|
+ if (str) {
|
|
+ cr_utils_dump_n_chars2 (' ', stringue,
|
|
+ a_indent);
|
|
+ g_string_append (stringue, str);
|
|
+ g_free (str);
|
|
+ str = NULL;
|
|
+ } else
|
|
+ goto error;
|
|
+
|
|
+ if (a_this->value) {
|
|
+ guchar *value_str = NULL;
|
|
+
|
|
+ value_str = cr_term_to_string (a_this->value);
|
|
+ if (value_str) {
|
|
+ g_string_append_printf (stringue, " : %s",
|
|
+ value_str);
|
|
+ g_free (value_str);
|
|
+ } else
|
|
+ goto error;
|
|
+ }
|
|
+ if (a_this->important == TRUE) {
|
|
+ g_string_append_printf (stringue, " %s",
|
|
+ "!important");
|
|
+ }
|
|
+ }
|
|
+ if (stringue && stringue->str) {
|
|
+ result = stringue->str;
|
|
+ g_string_free (stringue, FALSE);
|
|
+ }
|
|
+ return result;
|
|
+
|
|
+ error:
|
|
+ if (stringue) {
|
|
+ g_string_free (stringue, TRUE);
|
|
+ stringue = NULL;
|
|
+ }
|
|
+ if (str) {
|
|
+ g_free (str);
|
|
+ str = NULL;
|
|
+ }
|
|
+
|
|
+ return result;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_declaration_list_to_string:
|
|
+ *@a_this: the current instance of #CRDeclaration.
|
|
+ *@a_indent: the number of indentation white char
|
|
+ *to put before the actual serialisation.
|
|
+ *
|
|
+ *Serializes the declaration list into a string
|
|
+ */
|
|
+guchar *
|
|
+cr_declaration_list_to_string (CRDeclaration const * a_this, gulong a_indent)
|
|
+{
|
|
+ CRDeclaration const *cur = NULL;
|
|
+ GString *stringue = NULL;
|
|
+ guchar *str = NULL,
|
|
+ *result = NULL;
|
|
+
|
|
+ g_return_val_if_fail (a_this, NULL);
|
|
+
|
|
+ stringue = g_string_new (NULL);
|
|
+
|
|
+ for (cur = a_this; cur; cur = cur->next) {
|
|
+ str = (guchar *) cr_declaration_to_string (cur, a_indent);
|
|
+ if (str) {
|
|
+ g_string_append_printf (stringue, "%s;", str);
|
|
+ g_free (str);
|
|
+ } else
|
|
+ break;
|
|
+ }
|
|
+ if (stringue && stringue->str) {
|
|
+ result = (guchar *) stringue->str;
|
|
+ g_string_free (stringue, FALSE);
|
|
+ }
|
|
+
|
|
+ return result;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_declaration_list_to_string2:
|
|
+ *@a_this: the current instance of #CRDeclaration.
|
|
+ *@a_indent: the number of indentation white char
|
|
+ *@a_one_decl_per_line: whether to output one doc per line or not.
|
|
+ *to put before the actual serialisation.
|
|
+ *
|
|
+ *Serializes the declaration list into a string
|
|
+ *Returns the serialized form the declararation.
|
|
+ */
|
|
+guchar *
|
|
+cr_declaration_list_to_string2 (CRDeclaration const * a_this,
|
|
+ gulong a_indent, gboolean a_one_decl_per_line)
|
|
+{
|
|
+ CRDeclaration const *cur = NULL;
|
|
+ GString *stringue = NULL;
|
|
+ guchar *str = NULL,
|
|
+ *result = NULL;
|
|
+
|
|
+ g_return_val_if_fail (a_this, NULL);
|
|
+
|
|
+ stringue = g_string_new (NULL);
|
|
+
|
|
+ for (cur = a_this; cur; cur = cur->next) {
|
|
+ str = (guchar *) cr_declaration_to_string (cur, a_indent);
|
|
+ if (str) {
|
|
+ if (a_one_decl_per_line == TRUE) {
|
|
+ if (cur->next)
|
|
+ g_string_append_printf (stringue,
|
|
+ "%s;\n", str);
|
|
+ else
|
|
+ g_string_append (stringue,
|
|
+ (const gchar *) str);
|
|
+ } else {
|
|
+ if (cur->next)
|
|
+ g_string_append_printf (stringue,
|
|
+ "%s;", str);
|
|
+ else
|
|
+ g_string_append (stringue,
|
|
+ (const gchar *) str);
|
|
+ }
|
|
+ g_free (str);
|
|
+ } else
|
|
+ break;
|
|
+ }
|
|
+ if (stringue && stringue->str) {
|
|
+ result = (guchar *) stringue->str;
|
|
+ g_string_free (stringue, FALSE);
|
|
+ }
|
|
+
|
|
+ return result;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_declaration_nr_props:
|
|
+ *@a_this: the current instance of #CRDeclaration.
|
|
+ *Return the number of properties in the declaration
|
|
+ */
|
|
+gint
|
|
+cr_declaration_nr_props (CRDeclaration const * a_this)
|
|
+{
|
|
+ CRDeclaration 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_declaration_get_from_list:
|
|
+ *@a_this: the current instance of #CRDeclaration.
|
|
+ *@itemnr: the index into the declaration list.
|
|
+ *
|
|
+ *Use an index to get a CRDeclaration from the declaration list.
|
|
+ *
|
|
+ *Returns #CRDeclaration at position itemnr,
|
|
+ *if itemnr > number of declarations - 1,
|
|
+ *it will return NULL.
|
|
+ */
|
|
+CRDeclaration *
|
|
+cr_declaration_get_from_list (CRDeclaration * a_this, int itemnr)
|
|
+{
|
|
+ CRDeclaration *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_declaration_get_by_prop_name:
|
|
+ *@a_this: the current instance of #CRDeclaration.
|
|
+ *@a_prop: the property name to search for.
|
|
+ *
|
|
+ *Use property name to get a CRDeclaration from the declaration list.
|
|
+ *Returns #CRDeclaration with property name a_prop, or NULL if not found.
|
|
+ */
|
|
+CRDeclaration *
|
|
+cr_declaration_get_by_prop_name (CRDeclaration * a_this,
|
|
+ const guchar * a_prop)
|
|
+{
|
|
+ CRDeclaration *cur = NULL;
|
|
+
|
|
+ g_return_val_if_fail (a_this, NULL);
|
|
+ g_return_val_if_fail (a_prop, NULL);
|
|
+
|
|
+ for (cur = a_this; cur; cur = cur->next) {
|
|
+ if (cur->property
|
|
+ && cur->property->stryng
|
|
+ && cur->property->stryng->str) {
|
|
+ if (!strcmp (cur->property->stryng->str,
|
|
+ (const char *) a_prop)) {
|
|
+ return cur;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ return NULL;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_declaration_ref:
|
|
+ *@a_this: the current instance of #CRDeclaration.
|
|
+ *
|
|
+ *Increases the ref count of the current instance of #CRDeclaration.
|
|
+ */
|
|
+void
|
|
+cr_declaration_ref (CRDeclaration * a_this)
|
|
+{
|
|
+ g_return_if_fail (a_this);
|
|
+
|
|
+ a_this->ref_count++;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_declaration_unref:
|
|
+ *@a_this: the current instance of #CRDeclaration.
|
|
+ *
|
|
+ *Decrements the ref count of the current instance of #CRDeclaration.
|
|
+ *If the ref count reaches zero, the current instance of #CRDeclaration
|
|
+ *if destroyed.
|
|
+ *Returns TRUE if @a_this was destroyed (ref count reached zero),
|
|
+ *FALSE otherwise.
|
|
+ */
|
|
+gboolean
|
|
+cr_declaration_unref (CRDeclaration * a_this)
|
|
+{
|
|
+ g_return_val_if_fail (a_this, FALSE);
|
|
+
|
|
+ if (a_this->ref_count) {
|
|
+ a_this->ref_count--;
|
|
+ }
|
|
+
|
|
+ if (a_this->ref_count == 0) {
|
|
+ cr_declaration_destroy (a_this);
|
|
+ return TRUE;
|
|
+ }
|
|
+ return FALSE;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_declaration_destroy:
|
|
+ *@a_this: the current instance of #CRDeclaration.
|
|
+ *
|
|
+ *Destructor of the declaration list.
|
|
+ */
|
|
+void
|
|
+cr_declaration_destroy (CRDeclaration * a_this)
|
|
+{
|
|
+ CRDeclaration *cur = NULL;
|
|
+
|
|
+ g_return_if_fail (a_this);
|
|
+
|
|
+ /*
|
|
+ * Go to the last element of the list.
|
|
+ */
|
|
+ for (cur = a_this; cur->next; cur = cur->next)
|
|
+ g_assert (cur->next->prev == cur);
|
|
+
|
|
+ /*
|
|
+ * Walk backward the list and free each "next" element.
|
|
+ * Meanwhile, free each property/value pair contained in the list.
|
|
+ */
|
|
+ for (; cur; cur = cur->prev) {
|
|
+ g_free (cur->next);
|
|
+ cur->next = NULL;
|
|
+
|
|
+ if (cur->property) {
|
|
+ cr_string_destroy (cur->property);
|
|
+ cur->property = NULL;
|
|
+ }
|
|
+
|
|
+ if (cur->value) {
|
|
+ cr_term_destroy (cur->value);
|
|
+ cur->value = NULL;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ g_free (a_this);
|
|
+}
|
|
diff --git a/src/st/croco/cr-declaration.h b/src/st/croco/cr-declaration.h
|
|
new file mode 100644
|
|
index 000000000..eee8be321
|
|
--- /dev/null
|
|
+++ b/src/st/croco/cr-declaration.h
|
|
@@ -0,0 +1,136 @@
|
|
+/* -*- 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
|
|
+ *
|
|
+ * See the COPYRIGHTS file for copyright information.
|
|
+ */
|
|
+
|
|
+#ifndef __CR_DECLARATION_H__
|
|
+#define __CR_DECLARATION_H__
|
|
+
|
|
+#include <stdio.h>
|
|
+#include "cr-utils.h"
|
|
+#include "cr-term.h"
|
|
+#include "cr-parsing-location.h"
|
|
+
|
|
+G_BEGIN_DECLS
|
|
+
|
|
+/**
|
|
+ *@file
|
|
+ *The declaration of the #CRDeclaration class.
|
|
+ */
|
|
+
|
|
+/*forward declaration of what is defined in cr-statement.h*/
|
|
+typedef struct _CRStatement CRStatement ;
|
|
+
|
|
+/**
|
|
+ *The abstraction of a css declaration defined by the
|
|
+ *css2 spec in chapter 4.
|
|
+ *It is actually a chained list of property/value pairs.
|
|
+ */
|
|
+typedef struct _CRDeclaration CRDeclaration ;
|
|
+struct _CRDeclaration
|
|
+{
|
|
+ /**The property.*/
|
|
+ CRString *property ;
|
|
+
|
|
+ /**The value of the property.*/
|
|
+ CRTerm *value ;
|
|
+
|
|
+ /*the ruleset that contains this declaration*/
|
|
+ CRStatement *parent_statement ;
|
|
+
|
|
+ /*the next declaration*/
|
|
+ CRDeclaration *next ;
|
|
+
|
|
+ /*the previous one declaration*/
|
|
+ CRDeclaration *prev ;
|
|
+
|
|
+ /*does the declaration have the important keyword ?*/
|
|
+ gboolean important ;
|
|
+
|
|
+ glong ref_count ;
|
|
+
|
|
+ CRParsingLocation location ;
|
|
+ /*reserved for future usage*/
|
|
+ gpointer rfu0 ;
|
|
+ gpointer rfu1 ;
|
|
+ gpointer rfu2 ;
|
|
+ gpointer rfu3 ;
|
|
+} ;
|
|
+
|
|
+
|
|
+CRDeclaration * cr_declaration_new (CRStatement *a_statement,
|
|
+ CRString *a_property,
|
|
+ CRTerm *a_value) ;
|
|
+
|
|
+
|
|
+CRDeclaration * cr_declaration_parse_from_buf (CRStatement *a_statement,
|
|
+ const guchar *a_str,
|
|
+ enum CREncoding a_enc) ;
|
|
+
|
|
+CRDeclaration * cr_declaration_parse_list_from_buf (const guchar *a_str,
|
|
+ enum CREncoding a_enc) ;
|
|
+
|
|
+CRDeclaration * cr_declaration_append (CRDeclaration *a_this,
|
|
+ CRDeclaration *a_new) ;
|
|
+
|
|
+CRDeclaration * cr_declaration_append2 (CRDeclaration *a_this,
|
|
+ CRString *a_prop,
|
|
+ CRTerm *a_value) ;
|
|
+
|
|
+CRDeclaration * cr_declaration_prepend (CRDeclaration *a_this,
|
|
+ CRDeclaration *a_new) ;
|
|
+
|
|
+CRDeclaration * cr_declaration_unlink (CRDeclaration * a_decl) ;
|
|
+
|
|
+void
|
|
+cr_declaration_dump (CRDeclaration const *a_this,
|
|
+ FILE *a_fp, glong a_indent,
|
|
+ gboolean a_one_per_line) ;
|
|
+
|
|
+void cr_declaration_dump_one (CRDeclaration const *a_this,
|
|
+ FILE *a_fp, glong a_indent) ;
|
|
+
|
|
+gint cr_declaration_nr_props (CRDeclaration const *a_this) ;
|
|
+
|
|
+CRDeclaration * cr_declaration_get_from_list (CRDeclaration *a_this,
|
|
+ int itemnr) ;
|
|
+
|
|
+CRDeclaration * cr_declaration_get_by_prop_name (CRDeclaration *a_this,
|
|
+ const guchar *a_str) ;
|
|
+
|
|
+gchar * cr_declaration_to_string (CRDeclaration const *a_this,
|
|
+ gulong a_indent) ;
|
|
+
|
|
+guchar * cr_declaration_list_to_string (CRDeclaration const *a_this,
|
|
+ gulong a_indent) ;
|
|
+
|
|
+guchar * cr_declaration_list_to_string2 (CRDeclaration const *a_this,
|
|
+ gulong a_indent,
|
|
+ gboolean a_one_decl_per_line) ;
|
|
+
|
|
+void cr_declaration_ref (CRDeclaration *a_this) ;
|
|
+
|
|
+gboolean cr_declaration_unref (CRDeclaration *a_this) ;
|
|
+
|
|
+void cr_declaration_destroy (CRDeclaration *a_this) ;
|
|
+
|
|
+G_END_DECLS
|
|
+
|
|
+#endif /*__CR_DECLARATION_H__*/
|
|
diff --git a/src/st/croco/cr-doc-handler.c b/src/st/croco/cr-doc-handler.c
|
|
new file mode 100644
|
|
index 000000000..bbb158298
|
|
--- /dev/null
|
|
+++ b/src/st/croco/cr-doc-handler.c
|
|
@@ -0,0 +1,276 @@
|
|
+/* -*- 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
|
|
+ *
|
|
+ * See COPRYRIGHTS file for copyright information.
|
|
+ */
|
|
+
|
|
+#include <string.h>
|
|
+#include "cr-doc-handler.h"
|
|
+#include "cr-parser.h"
|
|
+
|
|
+/**
|
|
+ *@CRDocHandler:
|
|
+ *
|
|
+ *The definition of the CRDocHandler class.
|
|
+ *Contains methods to instantiate, destroy,
|
|
+ *and initialyze instances of #CRDocHandler
|
|
+ *to custom values.
|
|
+ */
|
|
+
|
|
+#define PRIVATE(obj) (obj)->priv
|
|
+
|
|
+struct _CRDocHandlerPriv {
|
|
+ /**
|
|
+ *This pointer is to hold an application parsing context.
|
|
+ *For example, it used by the Object Model parser to
|
|
+ *store it parsing context. #CRParser does not touch it, but
|
|
+ *#CROMParser does. #CROMParser allocates this pointer at
|
|
+ *the beginning of the css document, and frees it at the end
|
|
+ *of the document.
|
|
+ */
|
|
+ gpointer context;
|
|
+
|
|
+ /**
|
|
+ *The place where #CROMParser puts the result of its parsing, if
|
|
+ *any.
|
|
+ */
|
|
+ gpointer result;
|
|
+ /**
|
|
+ *a pointer to the parser used to parse
|
|
+ *the current document.
|
|
+ */
|
|
+ CRParser *parser ;
|
|
+};
|
|
+
|
|
+/**
|
|
+ * cr_doc_handler_new:
|
|
+ *Constructor of #CRDocHandler.
|
|
+ *
|
|
+ *Returns the newly built instance of
|
|
+ *#CRDocHandler
|
|
+ *
|
|
+ */
|
|
+CRDocHandler *
|
|
+cr_doc_handler_new (void)
|
|
+{
|
|
+ CRDocHandler *result = NULL;
|
|
+
|
|
+ result = g_try_malloc (sizeof (CRDocHandler));
|
|
+
|
|
+ g_return_val_if_fail (result, NULL);
|
|
+
|
|
+ memset (result, 0, sizeof (CRDocHandler));
|
|
+ result->ref_count++;
|
|
+
|
|
+ result->priv = g_try_malloc (sizeof (CRDocHandlerPriv));
|
|
+ if (!result->priv) {
|
|
+ cr_utils_trace_info ("Out of memory exception");
|
|
+ g_free (result);
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
+ cr_doc_handler_set_default_sac_handler (result);
|
|
+
|
|
+ return result;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_doc_handler_get_ctxt:
|
|
+ *@a_this: the current instance of #CRDocHandler.
|
|
+ *@a_ctxt: out parameter. The new parsing context.
|
|
+ *
|
|
+ *Gets the private parsing context associated to the document handler
|
|
+ *The private parsing context is used by libcroco only.
|
|
+ *
|
|
+ *Returns CR_OK upon successfull completion, an error code otherwise.
|
|
+ */
|
|
+enum CRStatus
|
|
+cr_doc_handler_get_ctxt (CRDocHandler const * a_this, gpointer * a_ctxt)
|
|
+{
|
|
+ g_return_val_if_fail (a_this && a_this->priv, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ *a_ctxt = a_this->priv->context;
|
|
+
|
|
+ return CR_OK;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_doc_handler_set_ctxt:
|
|
+ *@a_this: the current instance of #CRDocHandler
|
|
+ *@a_ctxt: a pointer to the parsing context.
|
|
+ *
|
|
+ *Sets the private parsing context.
|
|
+ *This is used by libcroco only.
|
|
+ *Returns CR_OK upon successfull completion, an error code otherwise.
|
|
+ */
|
|
+enum CRStatus
|
|
+cr_doc_handler_set_ctxt (CRDocHandler * a_this, gpointer a_ctxt)
|
|
+{
|
|
+ g_return_val_if_fail (a_this && a_this->priv, CR_BAD_PARAM_ERROR);
|
|
+ a_this->priv->context = a_ctxt;
|
|
+ return CR_OK;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_doc_handler_get_result:
|
|
+ *@a_this: the current instance of #CRDocHandler
|
|
+ *@a_result: out parameter. The returned result.
|
|
+ *
|
|
+ *Gets the private parsing result.
|
|
+ *The private parsing result is used by libcroco only.
|
|
+ *
|
|
+ *Returns CR_OK upon successfull completion, an error code otherwise.
|
|
+ */
|
|
+enum CRStatus
|
|
+cr_doc_handler_get_result (CRDocHandler const * a_this, gpointer * a_result)
|
|
+{
|
|
+ g_return_val_if_fail (a_this && a_this->priv, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ *a_result = a_this->priv->result;
|
|
+
|
|
+ return CR_OK;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_doc_handler_set_result:
|
|
+ *@a_this: the current instance of #CRDocHandler
|
|
+ *@a_result: the new result.
|
|
+ *
|
|
+ *Sets the private parsing context.
|
|
+ *This is used by libcroco only.
|
|
+ *
|
|
+ *Returns CR_OK upon successfull completion, an error code otherwise.
|
|
+ */
|
|
+enum CRStatus
|
|
+cr_doc_handler_set_result (CRDocHandler * a_this, gpointer a_result)
|
|
+{
|
|
+ g_return_val_if_fail (a_this && a_this->priv, CR_BAD_PARAM_ERROR);
|
|
+ a_this->priv->result = a_result;
|
|
+ return CR_OK;
|
|
+}
|
|
+
|
|
+/**
|
|
+ *cr_doc_handler_set_default_sac_handler:
|
|
+ *@a_this: a pointer to the current instance of #CRDocHandler.
|
|
+ *
|
|
+ *Sets the sac handlers contained in the current
|
|
+ *instance of DocHandler to the default handlers.
|
|
+ *For the time being the default handlers are
|
|
+ *test handlers. This is expected to change in a
|
|
+ *near future, when the libcroco gets a bit debugged.
|
|
+ *
|
|
+ *Returns CR_OK upon successfull completion, an error code otherwise.
|
|
+ */
|
|
+enum CRStatus
|
|
+cr_doc_handler_set_default_sac_handler (CRDocHandler * a_this)
|
|
+{
|
|
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ a_this->start_document = NULL;
|
|
+ a_this->end_document = NULL;
|
|
+ a_this->import_style = NULL;
|
|
+ a_this->namespace_declaration = NULL;
|
|
+ a_this->comment = NULL;
|
|
+ a_this->start_selector = NULL;
|
|
+ a_this->end_selector = NULL;
|
|
+ a_this->property = NULL;
|
|
+ a_this->start_font_face = NULL;
|
|
+ a_this->end_font_face = NULL;
|
|
+ a_this->start_media = NULL;
|
|
+ a_this->end_media = NULL;
|
|
+ a_this->start_page = NULL;
|
|
+ a_this->end_page = NULL;
|
|
+ a_this->ignorable_at_rule = NULL;
|
|
+ a_this->error = NULL;
|
|
+ a_this->unrecoverable_error = NULL;
|
|
+ return CR_OK;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_doc_handler_ref:
|
|
+ *@a_this: the current instance of #CRDocHandler.
|
|
+ */
|
|
+void
|
|
+cr_doc_handler_ref (CRDocHandler * a_this)
|
|
+{
|
|
+ g_return_if_fail (a_this);
|
|
+
|
|
+ a_this->ref_count++;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_doc_handler_unref:
|
|
+ *@a_this: the currrent instance of #CRDocHandler.
|
|
+ *
|
|
+ *Decreases the ref count of the current instance of #CRDocHandler.
|
|
+ *If the ref count reaches '0' then, destroys the instance.
|
|
+ *
|
|
+ *Returns TRUE if the instance as been destroyed, FALSE otherwise.
|
|
+ */
|
|
+gboolean
|
|
+cr_doc_handler_unref (CRDocHandler * a_this)
|
|
+{
|
|
+ g_return_val_if_fail (a_this, FALSE);
|
|
+
|
|
+ if (a_this->ref_count > 0) {
|
|
+ a_this->ref_count--;
|
|
+ }
|
|
+
|
|
+ if (a_this->ref_count == 0) {
|
|
+ cr_doc_handler_destroy (a_this);
|
|
+ return TRUE;
|
|
+ }
|
|
+ return FALSE ;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_doc_handler_destroy:
|
|
+ *@a_this: the instance of #CRDocHandler to
|
|
+ *destroy.
|
|
+ *
|
|
+ *The destructor of the #CRDocHandler class.
|
|
+ */
|
|
+void
|
|
+cr_doc_handler_destroy (CRDocHandler * a_this)
|
|
+{
|
|
+ g_return_if_fail (a_this);
|
|
+
|
|
+ if (a_this->priv) {
|
|
+ g_free (a_this->priv);
|
|
+ a_this->priv = NULL;
|
|
+ }
|
|
+ g_free (a_this);
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_doc_handler_associate_a_parser:
|
|
+ *Associates a parser to the current document handler
|
|
+ *
|
|
+ *@a_this: the current instance of document handler.
|
|
+ *@a_parser: the parser to associate.
|
|
+ */
|
|
+void
|
|
+cr_doc_handler_associate_a_parser (CRDocHandler *a_this,
|
|
+ gpointer a_parser)
|
|
+{
|
|
+ g_return_if_fail (a_this && PRIVATE (a_this)
|
|
+ && a_parser) ;
|
|
+
|
|
+ PRIVATE (a_this)->parser = a_parser ;
|
|
+}
|
|
diff --git a/src/st/croco/cr-doc-handler.h b/src/st/croco/cr-doc-handler.h
|
|
new file mode 100644
|
|
index 000000000..d12673f31
|
|
--- /dev/null
|
|
+++ b/src/st/croco/cr-doc-handler.h
|
|
@@ -0,0 +1,298 @@
|
|
+/* -*- 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
|
|
+ *
|
|
+ * See the COPYRIGHTS file for copyright information.
|
|
+ */
|
|
+
|
|
+#ifndef __CR_DOC_HANDLER_H__
|
|
+#define __CR_DOC_HANDLER_H__
|
|
+
|
|
+/**
|
|
+ *@file
|
|
+ *The declaration of the #CRDocumentHandler class.
|
|
+ *This class is actually the parsing events handler.
|
|
+ */
|
|
+
|
|
+#include <glib.h>
|
|
+#include "cr-utils.h"
|
|
+#include "cr-input.h"
|
|
+#include "cr-stylesheet.h"
|
|
+
|
|
+G_BEGIN_DECLS
|
|
+
|
|
+
|
|
+typedef struct _CRDocHandler CRDocHandler ;
|
|
+
|
|
+struct _CRDocHandlerPriv ;
|
|
+typedef struct _CRDocHandlerPriv CRDocHandlerPriv ;
|
|
+
|
|
+
|
|
+/**
|
|
+ *The SAC document handler.
|
|
+ *An instance of this class is to
|
|
+ *be passed to a parser. Then, during the parsing
|
|
+ *the parser calls the convenient function pointer
|
|
+ *whenever a particular event (a css construction) occurs.
|
|
+ */
|
|
+struct _CRDocHandler
|
|
+{
|
|
+ CRDocHandlerPriv *priv ;
|
|
+
|
|
+ /**
|
|
+ *This pointer is to be used by the application for
|
|
+ *it custom needs. It is there to extend the doc handler.
|
|
+ */
|
|
+ gpointer app_data ;
|
|
+
|
|
+ /**
|
|
+ *Is called at the beginning of the parsing of the document.
|
|
+ *@param a_this a pointer to the current instance of
|
|
+ *#CRDocHandler.
|
|
+ */
|
|
+ void (*start_document) (CRDocHandler *a_this) ;
|
|
+
|
|
+ /**
|
|
+ *Is called to notify the end of the parsing of the document.
|
|
+ *@param a_this a pointer to the current instance of
|
|
+ *#CRDocHandler.
|
|
+ */
|
|
+ void (*end_document) (CRDocHandler *a_this) ;
|
|
+
|
|
+ /**
|
|
+ *Is called to notify an at charset rule.
|
|
+ *@param a_this the document handler.
|
|
+ *@param a_charset the declared charset.
|
|
+ */
|
|
+ void (*charset) (CRDocHandler *a_this,
|
|
+ CRString *a_charset,
|
|
+ CRParsingLocation *a_charset_sym_location) ;
|
|
+
|
|
+ /**
|
|
+ *Is called to notify an import statement in
|
|
+ *the stylesheet.
|
|
+ *@param a_this the current instance of #CRDocHandler.
|
|
+ *@param a_media_list a doubly linked list of GString objects.
|
|
+ *Each GString object contains a string which is the
|
|
+ *destination media for style information.
|
|
+ *@param a_uri the uri of the imported style sheet.
|
|
+ *@param a_uri_default_ns the default namespace of URI
|
|
+ *@param a_location the parsing location of the '\@import'
|
|
+ *keyword.
|
|
+ *of the imported style sheet.
|
|
+ */
|
|
+ void (*import_style) (CRDocHandler *a_this,
|
|
+ GList *a_media_list,
|
|
+ CRString *a_uri,
|
|
+ CRString *a_uri_default_ns,
|
|
+ CRParsingLocation *a_location) ;
|
|
+
|
|
+ void (*import_style_result) (CRDocHandler *a_this,
|
|
+ GList *a_media_list,
|
|
+ CRString *a_uri,
|
|
+ CRString *a_uri_default_ns,
|
|
+ CRStyleSheet *a_sheet) ;
|
|
+
|
|
+ /**
|
|
+ *Is called to notify a namespace declaration.
|
|
+ *Not used yet.
|
|
+ *@param a_this the current instance of #CRDocHandler.
|
|
+ *@param a_prefix the prefix of the namespace.
|
|
+ *@param a_uri the uri of the namespace.
|
|
+ *@param a_location the location of the "@namespace" keyword.
|
|
+ */
|
|
+ void (*namespace_declaration) (CRDocHandler *a_this,
|
|
+ CRString *a_prefix,
|
|
+ CRString *a_uri,
|
|
+ CRParsingLocation *a_location) ;
|
|
+
|
|
+ /**
|
|
+ *Is called to notify a comment.
|
|
+ *@param a_this a pointer to the current instance
|
|
+ *of #CRDocHandler.
|
|
+ *@param a_comment the comment.
|
|
+ */
|
|
+ void (*comment) (CRDocHandler *a_this,
|
|
+ CRString *a_comment) ;
|
|
+
|
|
+ /**
|
|
+ *Is called to notify the beginning of a rule
|
|
+ *statement.
|
|
+ *@param a_this the current instance of #CRDocHandler.
|
|
+ *@param a_selector_list the list of selectors that precedes
|
|
+ *the rule declarations.
|
|
+ */
|
|
+ void (*start_selector) (CRDocHandler * a_this,
|
|
+ CRSelector *a_selector_list) ;
|
|
+
|
|
+ /**
|
|
+ *Is called to notify the end of a rule statement.
|
|
+ *@param a_this the current instance of #CRDocHandler.
|
|
+ *@param a_selector_list the list of selectors that precedes
|
|
+ *the rule declarations. This pointer is the same as
|
|
+ *the one passed to start_selector() ;
|
|
+ */
|
|
+ void (*end_selector) (CRDocHandler *a_this,
|
|
+ CRSelector *a_selector_list) ;
|
|
+
|
|
+
|
|
+ /**
|
|
+ *Is called to notify a declaration.
|
|
+ *@param a_this a pointer to the current instance
|
|
+ *of #CRDocHandler.
|
|
+ *@param a_name the name of the parsed property.
|
|
+ *@param a_expression a css expression that represents
|
|
+ *the value of the property. A css expression is
|
|
+ *actually a linked list of 'terms'. Each term can
|
|
+ *be linked to other using operators.
|
|
+ *
|
|
+ */
|
|
+ void (*property) (CRDocHandler *a_this,
|
|
+ CRString *a_name,
|
|
+ CRTerm *a_expression,
|
|
+ gboolean a_is_important) ;
|
|
+ /**
|
|
+ *Is called to notify the start of a font face statement.
|
|
+ *The parser invokes this method at the beginning of every
|
|
+ *font face statement in the style sheet. There will
|
|
+ *be a corresponding end_font_face () event for every
|
|
+ *start_font_face () event.
|
|
+ *
|
|
+ *@param a_this a pointer to the current instance of
|
|
+ *#CRDocHandler.
|
|
+ *@param a_location the parsing location of the "\@font-face"
|
|
+ *keyword.
|
|
+ */
|
|
+ void (*start_font_face) (CRDocHandler *a_this,
|
|
+ CRParsingLocation *a_location) ;
|
|
+
|
|
+ /**
|
|
+ *Is called to notify the end of a font face statement.
|
|
+ *@param a_this a pointer to the current instance of
|
|
+ *#CRDocHandler.
|
|
+ */
|
|
+ void (*end_font_face) (CRDocHandler *a_this) ;
|
|
+
|
|
+
|
|
+ /**
|
|
+ *Is called to notify the beginning of a media statement.
|
|
+ *The parser will invoke this method at the beginning of
|
|
+ *every media statement in the style sheet. There will be
|
|
+ *a corresponding end_media() event for every start_media()
|
|
+ *event.
|
|
+ *@param a_this a pointer to the current instance of
|
|
+ *#CRDocHandler.
|
|
+ *@param a_media_list a double linked list of
|
|
+ #CRString * objects.
|
|
+ *Each CRString objects is actually a destination media for
|
|
+ *the style information.
|
|
+ */
|
|
+ void (*start_media) (CRDocHandler *a_this,
|
|
+ GList *a_media_list,
|
|
+ CRParsingLocation *a_location) ;
|
|
+
|
|
+ /**
|
|
+ *Is called to notify the end of a media statement.
|
|
+ *@param a_this a pointer to the current instance
|
|
+ *of #CRDocHandler.
|
|
+ *@param a_media_list a double linked list of GString * objects.
|
|
+ *Each GString objects is actually a destination media for
|
|
+ *the style information.
|
|
+ */
|
|
+ void (*end_media) (CRDocHandler *a_this,
|
|
+ GList *a_media_list) ;
|
|
+
|
|
+ /**
|
|
+ *Is called to notify the beginning of a page statement.
|
|
+ *The parser invokes this function at the beginning of
|
|
+ *every page statement in the style sheet. There will be
|
|
+ *a corresponding end_page() event for every single
|
|
+ *start_page() event.
|
|
+ *@param a_this a pointer to the current instance of
|
|
+ *#CRDocHandler.
|
|
+ *@param a_name the name of the page (if any, null otherwise).
|
|
+ *@param a_pseudo_page the pseudo page (if any, null otherwise).
|
|
+ *@param a_location the parsing location of the "\@page" keyword.
|
|
+ */
|
|
+ void (*start_page) (CRDocHandler *a_this,
|
|
+ CRString *a_name,
|
|
+ CRString *a_pseudo_page,
|
|
+ CRParsingLocation *a_location) ;
|
|
+
|
|
+ /**
|
|
+ *Is called to notify the end of a page statement.
|
|
+ *@param a_this a pointer to the current instance of
|
|
+ *#CRDocHandler.
|
|
+ *@param a_name the name of the page (if any, null otherwise).
|
|
+ *@param a_pseudo_page the pseudo page (if any, null otherwise).
|
|
+ */
|
|
+ void (*end_page) (CRDocHandler *a_this,
|
|
+ CRString *a_name,
|
|
+ CRString *pseudo_page) ;
|
|
+
|
|
+ /**
|
|
+ *Is Called to notify an unknown at-rule not supported
|
|
+ *by this parser.
|
|
+ */
|
|
+ void (*ignorable_at_rule) (CRDocHandler *a_this,
|
|
+ CRString *a_name) ;
|
|
+
|
|
+ /**
|
|
+ *Is called to notify a parsing error. After this error
|
|
+ *the application must ignore the rule being parsed, if
|
|
+ *any. After completion of this callback,
|
|
+ *the parser will then try to resume the parsing,
|
|
+ *ignoring the current error.
|
|
+ */
|
|
+ void (*error) (CRDocHandler *a_this) ;
|
|
+
|
|
+ /**
|
|
+ *Is called to notify an unrecoverable parsing error.
|
|
+ *This is the place to put emergency routines that free allocated
|
|
+ *resources.
|
|
+ */
|
|
+ void (*unrecoverable_error) (CRDocHandler *a_this) ;
|
|
+
|
|
+ gboolean resolve_import ;
|
|
+ gulong ref_count ;
|
|
+} ;
|
|
+
|
|
+CRDocHandler * cr_doc_handler_new (void) ;
|
|
+
|
|
+enum CRStatus cr_doc_handler_set_result (CRDocHandler *a_this, gpointer a_result) ;
|
|
+
|
|
+enum CRStatus cr_doc_handler_get_result (CRDocHandler const *a_this, gpointer * a_result) ;
|
|
+
|
|
+enum CRStatus cr_doc_handler_set_ctxt (CRDocHandler *a_this, gpointer a_ctxt) ;
|
|
+
|
|
+enum CRStatus cr_doc_handler_get_ctxt (CRDocHandler const *a_this, gpointer * a_ctxt) ;
|
|
+
|
|
+enum CRStatus cr_doc_handler_set_default_sac_handler (CRDocHandler *a_this) ;
|
|
+
|
|
+void cr_doc_handler_associate_a_parser (CRDocHandler *a_this,
|
|
+ gpointer a_parser) ;
|
|
+
|
|
+void cr_doc_handler_ref (CRDocHandler *a_this) ;
|
|
+
|
|
+gboolean cr_doc_handler_unref (CRDocHandler *a_this) ;
|
|
+
|
|
+void cr_doc_handler_destroy (CRDocHandler *a_this) ;
|
|
+
|
|
+G_END_DECLS
|
|
+
|
|
+#endif /*__CR_DOC_HANDLER_H__*/
|
|
diff --git a/src/st/croco/cr-enc-handler.c b/src/st/croco/cr-enc-handler.c
|
|
new file mode 100644
|
|
index 000000000..a7c4269ad
|
|
--- /dev/null
|
|
+++ b/src/st/croco/cr-enc-handler.c
|
|
@@ -0,0 +1,184 @@
|
|
+/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
|
|
+
|
|
+/*
|
|
+ * This file is part of The Croco Library
|
|
+ *
|
|
+ * Copyright (C) 2002-2003 Dodji Seketeli <dodji@seketeli.org>
|
|
+ *
|
|
+ * 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
|
|
+ */
|
|
+
|
|
+/*
|
|
+ *$Id$
|
|
+ */
|
|
+
|
|
+/**
|
|
+ *@file
|
|
+ *The definition of the #CREncHandler class.
|
|
+ */
|
|
+
|
|
+#include "cr-enc-handler.h"
|
|
+#include "cr-utils.h"
|
|
+
|
|
+#include <string.h>
|
|
+
|
|
+struct CREncAlias {
|
|
+ const gchar *name;
|
|
+ enum CREncoding encoding;
|
|
+};
|
|
+
|
|
+static struct CREncAlias gv_default_aliases[] = {
|
|
+ {"UTF-8", CR_UTF_8},
|
|
+ {"UTF_8", CR_UTF_8},
|
|
+ {"UTF8", CR_UTF_8},
|
|
+ {"UTF-16", CR_UTF_16},
|
|
+ {"UTF_16", CR_UTF_16},
|
|
+ {"UTF16", CR_UTF_16},
|
|
+ {"UCS1", CR_UCS_1},
|
|
+ {"UCS-1", CR_UCS_1},
|
|
+ {"UCS_1", CR_UCS_1},
|
|
+ {"ISO-8859-1", CR_UCS_1},
|
|
+ {"ISO_8859-1", CR_UCS_1},
|
|
+ {"UCS-1", CR_UCS_1},
|
|
+ {"UCS_1", CR_UCS_1},
|
|
+ {"UCS4", CR_UCS_4},
|
|
+ {"UCS-4", CR_UCS_4},
|
|
+ {"UCS_4", CR_UCS_4},
|
|
+ {"ASCII", CR_ASCII},
|
|
+ {0, 0}
|
|
+};
|
|
+
|
|
+static CREncHandler gv_default_enc_handlers[] = {
|
|
+ {CR_UCS_1, cr_utils_ucs1_to_utf8, cr_utils_utf8_to_ucs1,
|
|
+ cr_utils_ucs1_str_len_as_utf8, cr_utils_utf8_str_len_as_ucs1},
|
|
+
|
|
+ {CR_ISO_8859_1, cr_utils_ucs1_to_utf8, cr_utils_utf8_to_ucs1,
|
|
+ cr_utils_ucs1_str_len_as_utf8, cr_utils_utf8_str_len_as_ucs1},
|
|
+
|
|
+ {CR_ASCII, cr_utils_ucs1_to_utf8, cr_utils_utf8_to_ucs1,
|
|
+ cr_utils_ucs1_str_len_as_utf8, cr_utils_utf8_str_len_as_ucs1},
|
|
+
|
|
+ {0, NULL, NULL, NULL, NULL}
|
|
+};
|
|
+
|
|
+/**
|
|
+ * cr_enc_handler_get_instance:
|
|
+ *@a_enc: the encoding of the Handler.
|
|
+ *
|
|
+ *Gets the instance of encoding handler.
|
|
+ *This function implements a singleton pattern.
|
|
+ *
|
|
+ *Returns the instance of #CREncHandler.
|
|
+ */
|
|
+CREncHandler *
|
|
+cr_enc_handler_get_instance (enum CREncoding a_enc)
|
|
+{
|
|
+ gulong i = 0;
|
|
+
|
|
+ for (i = 0; gv_default_enc_handlers[i].encoding; i++) {
|
|
+ if (gv_default_enc_handlers[i].encoding == a_enc) {
|
|
+ return (CREncHandler *) & gv_default_enc_handlers[i];
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return NULL;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_enc_handler_resolve_enc_alias:
|
|
+ *@a_alias_name: the encoding name.
|
|
+ *@a_enc: output param. The returned encoding type
|
|
+ *or 0 if the alias is not supported.
|
|
+ *
|
|
+ *Given an encoding name (called an alias name)
|
|
+ *the function returns the matching encoding type.
|
|
+ *
|
|
+ *Returns CR_OK upon successfull completion, an error code otherwise.
|
|
+ */
|
|
+enum CRStatus
|
|
+cr_enc_handler_resolve_enc_alias (const guchar * a_alias_name,
|
|
+ enum CREncoding *a_enc)
|
|
+{
|
|
+ gulong i = 0;
|
|
+ guchar *alias_name_up = NULL;
|
|
+ enum CRStatus status = CR_ENCODING_NOT_FOUND_ERROR;
|
|
+
|
|
+ g_return_val_if_fail (a_alias_name != NULL, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ alias_name_up = (guchar *) g_ascii_strup ((const gchar *) a_alias_name, -1);
|
|
+
|
|
+ for (i = 0; gv_default_aliases[i].name; i++) {
|
|
+ if (!strcmp (gv_default_aliases[i].name, (const gchar *) alias_name_up)) {
|
|
+ *a_enc = gv_default_aliases[i].encoding;
|
|
+ status = CR_OK;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return status;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_enc_handler_convert_input:
|
|
+ *@a_this: the current instance of #CREncHandler.
|
|
+ *@a_in: the input buffer to convert.
|
|
+ *@a_in_len: in/out parameter. The len of the input
|
|
+ *buffer to convert. After return, contains the number of
|
|
+ *bytes actually consumed.
|
|
+ *@a_out: output parameter. The converted output buffer.
|
|
+ *Must be freed by the buffer.
|
|
+ *@a_out_len: output parameter. The length of the output buffer.
|
|
+ *
|
|
+ *Converts a raw input buffer into an utf8 buffer.
|
|
+ *
|
|
+ *Returns CR_OK upon successfull completion, an error code otherwise.
|
|
+ */
|
|
+enum CRStatus
|
|
+cr_enc_handler_convert_input (CREncHandler * a_this,
|
|
+ const guchar * a_in,
|
|
+ gulong * a_in_len,
|
|
+ guchar ** a_out, gulong * a_out_len)
|
|
+{
|
|
+ enum CRStatus status = CR_OK;
|
|
+
|
|
+ g_return_val_if_fail (a_this && a_in && a_in_len && a_out,
|
|
+ CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ if (a_this->decode_input == NULL)
|
|
+ return CR_OK;
|
|
+
|
|
+ if (a_this->enc_str_len_as_utf8) {
|
|
+ status = a_this->enc_str_len_as_utf8 (a_in,
|
|
+ &a_in[*a_in_len - 1],
|
|
+ a_out_len);
|
|
+
|
|
+ g_return_val_if_fail (status == CR_OK, status);
|
|
+ } else {
|
|
+ *a_out_len = *a_in_len;
|
|
+ }
|
|
+
|
|
+ *a_out = g_malloc0 (*a_out_len);
|
|
+
|
|
+ status = a_this->decode_input (a_in, a_in_len, *a_out, a_out_len);
|
|
+
|
|
+ if (status != CR_OK) {
|
|
+ g_free (*a_out);
|
|
+ *a_out = NULL;
|
|
+ }
|
|
+
|
|
+ g_return_val_if_fail (status == CR_OK, status);
|
|
+
|
|
+ return CR_OK;
|
|
+}
|
|
diff --git a/src/st/croco/cr-enc-handler.h b/src/st/croco/cr-enc-handler.h
|
|
new file mode 100644
|
|
index 000000000..0727764c0
|
|
--- /dev/null
|
|
+++ b/src/st/croco/cr-enc-handler.h
|
|
@@ -0,0 +1,94 @@
|
|
+/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
|
|
+
|
|
+/*
|
|
+ * This file is part of The Croco Library
|
|
+ *
|
|
+ * Copyright (C) 2002-2003 Dodji Seketeli <dodji@seketeli.org>
|
|
+ *
|
|
+ * 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
|
|
+ */
|
|
+
|
|
+/*
|
|
+ *$Id$
|
|
+ */
|
|
+
|
|
+/**
|
|
+ *@file:
|
|
+ *The declaration of the #CREncHandler class.
|
|
+ *
|
|
+ */
|
|
+
|
|
+#ifndef __CR_ENC_HANDLER_H__
|
|
+#define __CR_ENC_HANDLER_H__
|
|
+
|
|
+#include "cr-utils.h"
|
|
+
|
|
+G_BEGIN_DECLS
|
|
+
|
|
+
|
|
+typedef struct _CREncHandler CREncHandler ;
|
|
+
|
|
+typedef enum CRStatus (*CREncInputFunc) (const guchar * a_in,
|
|
+ gulong *a_in_len,
|
|
+ guchar *a_out,
|
|
+ gulong *a_out_len) ;
|
|
+
|
|
+typedef enum CRStatus (*CREncOutputFunc) (const guchar * a_in,
|
|
+ gulong *a_in_len,
|
|
+ guchar *a_out,
|
|
+ gulong *a_out_len) ;
|
|
+
|
|
+typedef enum CRStatus (*CREncInputStrLenAsUtf8Func)
|
|
+(const guchar *a_in_start,
|
|
+ const guchar *a_in_end,
|
|
+ gulong *a_in_size);
|
|
+
|
|
+typedef enum CRStatus (*CREncUtf8StrLenAsOutputFunc)
|
|
+(const guchar *a_in_start,
|
|
+ const guchar *a_in_end,
|
|
+ gulong *a_in_size) ;
|
|
+
|
|
+/**
|
|
+ *This class is responsible of the
|
|
+ *the encoding conversions stuffs in
|
|
+ *libcroco.
|
|
+ */
|
|
+
|
|
+struct _CREncHandler
|
|
+{
|
|
+ enum CREncoding encoding ;
|
|
+ CREncInputFunc decode_input ;
|
|
+ CREncInputFunc encode_output ;
|
|
+ CREncInputStrLenAsUtf8Func enc_str_len_as_utf8 ;
|
|
+ CREncUtf8StrLenAsOutputFunc utf8_str_len_as_enc ;
|
|
+} ;
|
|
+
|
|
+CREncHandler *
|
|
+cr_enc_handler_get_instance (enum CREncoding a_enc) ;
|
|
+
|
|
+enum CRStatus
|
|
+cr_enc_handler_resolve_enc_alias (const guchar *a_alias_name,
|
|
+ enum CREncoding *a_enc) ;
|
|
+
|
|
+enum CRStatus
|
|
+cr_enc_handler_convert_input (CREncHandler *a_this,
|
|
+ const guchar *a_in,
|
|
+ gulong *a_in_len,
|
|
+ guchar **a_out,
|
|
+ gulong *a_out_len) ;
|
|
+
|
|
+G_END_DECLS
|
|
+
|
|
+#endif /*__CR_ENC_HANDLER_H__*/
|
|
diff --git a/src/st/croco/cr-fonts.c b/src/st/croco/cr-fonts.c
|
|
new file mode 100644
|
|
index 000000000..3a5788cea
|
|
--- /dev/null
|
|
+++ b/src/st/croco/cr-fonts.c
|
|
@@ -0,0 +1,949 @@
|
|
+/* -*- 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
|
|
+ *
|
|
+ *See COPYRIGHTS file for copyright information
|
|
+ */
|
|
+
|
|
+#include "cr-fonts.h"
|
|
+#include <string.h>
|
|
+
|
|
+static enum CRStatus
|
|
+cr_font_family_to_string_real (CRFontFamily const * a_this,
|
|
+ gboolean a_walk_list, GString ** a_string)
|
|
+{
|
|
+ guchar const *name = NULL;
|
|
+ enum CRStatus result = CR_OK;
|
|
+
|
|
+ if (!*a_string) {
|
|
+ *a_string = g_string_new (NULL);
|
|
+ g_return_val_if_fail (*a_string,
|
|
+ CR_INSTANCIATION_FAILED_ERROR);
|
|
+ }
|
|
+
|
|
+ if (!a_this) {
|
|
+ g_string_append (*a_string, "NULL");
|
|
+ return CR_OK;
|
|
+ }
|
|
+
|
|
+ switch (a_this->type) {
|
|
+ case FONT_FAMILY_SANS_SERIF:
|
|
+ name = (guchar const *) "sans-serif";
|
|
+ break;
|
|
+
|
|
+ case FONT_FAMILY_SERIF:
|
|
+ name = (guchar const *) "sans-serif";
|
|
+ break;
|
|
+
|
|
+ case FONT_FAMILY_CURSIVE:
|
|
+ name = (guchar const *) "cursive";
|
|
+ break;
|
|
+
|
|
+ case FONT_FAMILY_FANTASY:
|
|
+ name = (guchar const *) "fantasy";
|
|
+ break;
|
|
+
|
|
+ case FONT_FAMILY_MONOSPACE:
|
|
+ name = (guchar const *) "monospace";
|
|
+ break;
|
|
+
|
|
+ case FONT_FAMILY_NON_GENERIC:
|
|
+ name = (guchar const *) a_this->name;
|
|
+ break;
|
|
+
|
|
+ default:
|
|
+ name = NULL;
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ if (name) {
|
|
+ if (a_this->prev) {
|
|
+ g_string_append_printf (*a_string, ", %s", name);
|
|
+ } else {
|
|
+ g_string_append (*a_string, (const gchar *) name);
|
|
+ }
|
|
+ }
|
|
+ if (a_walk_list == TRUE && a_this->next) {
|
|
+ result = cr_font_family_to_string_real (a_this->next,
|
|
+ TRUE, a_string);
|
|
+ }
|
|
+ return result;
|
|
+}
|
|
+
|
|
+static const gchar *
|
|
+cr_predefined_absolute_font_size_to_string (enum CRPredefinedAbsoluteFontSize
|
|
+ a_code)
|
|
+{
|
|
+ gchar const *str = NULL;
|
|
+
|
|
+ switch (a_code) {
|
|
+ case FONT_SIZE_XX_SMALL:
|
|
+ str = "xx-small";
|
|
+ break;
|
|
+ case FONT_SIZE_X_SMALL:
|
|
+ str = "x-small";
|
|
+ break;
|
|
+ case FONT_SIZE_SMALL:
|
|
+ str = "small";
|
|
+ break;
|
|
+ case FONT_SIZE_MEDIUM:
|
|
+ str = "medium";
|
|
+ break;
|
|
+ case FONT_SIZE_LARGE:
|
|
+ str = "large";
|
|
+ break;
|
|
+ case FONT_SIZE_X_LARGE:
|
|
+ str = "x-large";
|
|
+ break;
|
|
+ case FONT_SIZE_XX_LARGE:
|
|
+ str = "xx-large";
|
|
+ break;
|
|
+ default:
|
|
+ str = "unknown absolute font size value";
|
|
+ }
|
|
+ return str;
|
|
+}
|
|
+
|
|
+static const gchar *
|
|
+cr_relative_font_size_to_string (enum CRRelativeFontSize a_code)
|
|
+{
|
|
+ gchar const *str = NULL;
|
|
+
|
|
+ switch (a_code) {
|
|
+ case FONT_SIZE_LARGER:
|
|
+ str = "larger";
|
|
+ break;
|
|
+ case FONT_SIZE_SMALLER:
|
|
+ str = "smaller";
|
|
+ break;
|
|
+ default:
|
|
+ str = "unknown relative font size value";
|
|
+ break;
|
|
+ }
|
|
+ return str;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_font_family_new:
|
|
+ * @a_type: the type of font family to create.
|
|
+ * @a_name: the name of the font family.
|
|
+ *
|
|
+ * create a font family.
|
|
+ *
|
|
+ * Returns the newly built font family.
|
|
+ */
|
|
+CRFontFamily *
|
|
+cr_font_family_new (enum CRFontFamilyType a_type, guchar * a_name)
|
|
+{
|
|
+ CRFontFamily *result = NULL;
|
|
+
|
|
+ result = g_try_malloc (sizeof (CRFontFamily));
|
|
+
|
|
+ if (!result) {
|
|
+ cr_utils_trace_info ("Out of memory");
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
+ memset (result, 0, sizeof (CRFontFamily));
|
|
+ result->type = a_type;
|
|
+
|
|
+ cr_font_family_set_name (result, a_name);
|
|
+
|
|
+ return result;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_font_family_to_string:
|
|
+ * @a_this: the current instance of #CRFontFamily.
|
|
+ * @a_walk_font_family_list: wether the serialize the entire list.
|
|
+ *
|
|
+ * Returns the seriliazed font family. The caller has to free it using
|
|
+ * g_free().
|
|
+ */
|
|
+guchar *
|
|
+cr_font_family_to_string (CRFontFamily const * a_this,
|
|
+ gboolean a_walk_font_family_list)
|
|
+{
|
|
+ enum CRStatus status = CR_OK;
|
|
+ guchar *result = NULL;
|
|
+ GString *stringue = NULL;
|
|
+
|
|
+ if (!a_this) {
|
|
+ result = (guchar *) g_strdup ("NULL");
|
|
+ g_return_val_if_fail (result, NULL);
|
|
+ return result;
|
|
+ }
|
|
+ status = cr_font_family_to_string_real (a_this,
|
|
+ a_walk_font_family_list,
|
|
+ &stringue);
|
|
+
|
|
+ if (status == CR_OK && stringue) {
|
|
+ result = (guchar *) stringue->str;
|
|
+ g_string_free (stringue, FALSE);
|
|
+ stringue = NULL;
|
|
+
|
|
+ } else {
|
|
+ if (stringue) {
|
|
+ g_string_free (stringue, TRUE);
|
|
+ stringue = NULL;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return result;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_font_family_set_name:
|
|
+ * @a_this: the current instance of #CRFontFamily.
|
|
+ * @a_name: the new name
|
|
+ *
|
|
+ * Returns CR_OK upon sucessful completion, an error code otherwise.
|
|
+ */
|
|
+enum CRStatus
|
|
+cr_font_family_set_name (CRFontFamily * a_this, guchar * a_name)
|
|
+{
|
|
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ /*
|
|
+ *only non generic font families can have a name
|
|
+ */
|
|
+
|
|
+ if (a_this->type != FONT_FAMILY_NON_GENERIC) {
|
|
+ return CR_BAD_PARAM_ERROR;
|
|
+ }
|
|
+
|
|
+ if (a_this->name) {
|
|
+ g_free (a_this->name);
|
|
+ a_this->name = NULL;
|
|
+ }
|
|
+
|
|
+ a_this->name = a_name;
|
|
+ return CR_OK;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_font_family_append:
|
|
+ * @a_this: the current instance of #CRFontFamily.
|
|
+ * @a_family_to_append: the font family to append to the list
|
|
+ *
|
|
+ * Returns the new font family list.
|
|
+ */
|
|
+CRFontFamily *
|
|
+cr_font_family_append (CRFontFamily * a_this,
|
|
+ CRFontFamily * a_family_to_append)
|
|
+{
|
|
+ CRFontFamily *cur_ff = NULL;
|
|
+
|
|
+ g_return_val_if_fail (a_family_to_append, NULL);
|
|
+
|
|
+ if (!a_this)
|
|
+ return a_family_to_append;
|
|
+
|
|
+ for (cur_ff = a_this; cur_ff && cur_ff->next; cur_ff = cur_ff->next) ;
|
|
+
|
|
+ cur_ff->next = a_family_to_append;
|
|
+ a_family_to_append->prev = cur_ff;
|
|
+
|
|
+ return a_this;
|
|
+
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_font_family_prepend:
|
|
+ * @a_this: the current instance #CRFontFamily.
|
|
+ * @a_family_to_prepend: the font family to prepend to the list.
|
|
+ *
|
|
+ * Returns the font family list.
|
|
+ */
|
|
+CRFontFamily *
|
|
+cr_font_family_prepend (CRFontFamily * a_this,
|
|
+ CRFontFamily * a_family_to_prepend)
|
|
+{
|
|
+ g_return_val_if_fail (a_this && a_family_to_prepend, NULL);
|
|
+
|
|
+ if (!a_this)
|
|
+ return a_family_to_prepend;
|
|
+
|
|
+ a_family_to_prepend->next = a_this;
|
|
+ a_this->prev = a_family_to_prepend;
|
|
+
|
|
+ return a_family_to_prepend;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_font_family_destroy:
|
|
+ * @a_this: the current instance of #CRFontFamily.
|
|
+ *
|
|
+ * Returns CR_OK upon sucessful completion, an error code otherwise.
|
|
+ */
|
|
+enum CRStatus
|
|
+cr_font_family_destroy (CRFontFamily * a_this)
|
|
+{
|
|
+ CRFontFamily *cur_ff = NULL;
|
|
+
|
|
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ for (cur_ff = a_this; cur_ff && cur_ff->next; cur_ff = cur_ff->next) ;
|
|
+
|
|
+ for (; cur_ff; cur_ff = cur_ff->prev) {
|
|
+ if (a_this->name) {
|
|
+ g_free (a_this->name);
|
|
+ a_this->name = NULL;
|
|
+ }
|
|
+
|
|
+ if (cur_ff->next) {
|
|
+ g_free (cur_ff->next);
|
|
+
|
|
+ }
|
|
+
|
|
+ if (cur_ff->prev == NULL) {
|
|
+ g_free (a_this);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return CR_OK;
|
|
+}
|
|
+
|
|
+/***************************************************
|
|
+ *'font-size' manipulation functions definitions
|
|
+ ***************************************************/
|
|
+
|
|
+/**
|
|
+ * cr_font_size_new:
|
|
+ *
|
|
+ * Returns the newly created font size.
|
|
+ */
|
|
+CRFontSize *
|
|
+cr_font_size_new (void)
|
|
+{
|
|
+ CRFontSize *result = NULL;
|
|
+
|
|
+ result = g_try_malloc (sizeof (CRFontSize));
|
|
+ if (!result) {
|
|
+ cr_utils_trace_info ("Out of memory");
|
|
+ return NULL;
|
|
+ }
|
|
+ memset (result, 0, sizeof (CRFontSize));
|
|
+
|
|
+ return result;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_font_size_clear:
|
|
+ * @a_this: the current instance of #CRFontSize
|
|
+ *
|
|
+ * Returns CR_OK upon successful completion, an error code otherwise.
|
|
+ */
|
|
+enum CRStatus
|
|
+cr_font_size_clear (CRFontSize * a_this)
|
|
+{
|
|
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ switch (a_this->type) {
|
|
+ case PREDEFINED_ABSOLUTE_FONT_SIZE:
|
|
+ case RELATIVE_FONT_SIZE:
|
|
+ case INHERITED_FONT_SIZE:
|
|
+ memset (a_this, 0, sizeof (CRFontSize));
|
|
+ break;
|
|
+
|
|
+ case ABSOLUTE_FONT_SIZE:
|
|
+ memset (a_this, 0, sizeof (CRFontSize));
|
|
+ break;
|
|
+
|
|
+ default:
|
|
+ return CR_UNKNOWN_TYPE_ERROR;
|
|
+ }
|
|
+
|
|
+ return CR_OK;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_font_size_copy:
|
|
+ * @a_dst: the destination #CRFontSize (where to copy to).
|
|
+ * @a_src: the source #CRFontSize (where to copy from).
|
|
+ *
|
|
+ * Returns CR_OK upon successful completion, an error code otherwise.
|
|
+ */
|
|
+enum CRStatus
|
|
+cr_font_size_copy (CRFontSize * a_dst, CRFontSize const * a_src)
|
|
+{
|
|
+ g_return_val_if_fail (a_dst && a_src, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ switch (a_src->type) {
|
|
+ case PREDEFINED_ABSOLUTE_FONT_SIZE:
|
|
+ case RELATIVE_FONT_SIZE:
|
|
+ case INHERITED_FONT_SIZE:
|
|
+ cr_font_size_clear (a_dst);
|
|
+ memcpy (a_dst, a_src, sizeof (CRFontSize));
|
|
+ break;
|
|
+
|
|
+ case ABSOLUTE_FONT_SIZE:
|
|
+ cr_font_size_clear (a_dst);
|
|
+ cr_num_copy (&a_dst->value.absolute,
|
|
+ &a_src->value.absolute);
|
|
+ a_dst->type = a_src->type;
|
|
+ break;
|
|
+
|
|
+ default:
|
|
+ return CR_UNKNOWN_TYPE_ERROR;
|
|
+ }
|
|
+ return CR_OK;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_font_size_set_predefined_absolute_font_size:
|
|
+ * @a_this: the current instance of #CRFontSize.
|
|
+ * @a_predefined: what to set.
|
|
+ *
|
|
+ * Returns CR_OK upon sucessful completion, an error code otherwise.
|
|
+ */
|
|
+enum CRStatus
|
|
+cr_font_size_set_predefined_absolute_font_size (CRFontSize *a_this,
|
|
+ enum CRPredefinedAbsoluteFontSize a_predefined)
|
|
+{
|
|
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR) ;
|
|
+ g_return_val_if_fail (a_predefined >= FONT_SIZE_XX_SMALL
|
|
+ && a_predefined < NB_PREDEFINED_ABSOLUTE_FONT_SIZES,
|
|
+ CR_BAD_PARAM_ERROR) ;
|
|
+
|
|
+ a_this->type = PREDEFINED_ABSOLUTE_FONT_SIZE ;
|
|
+ a_this->value.predefined = a_predefined ;
|
|
+
|
|
+ return CR_OK ;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_font_size_set_relative_font_size:
|
|
+ * @a_this: the current instance of #CRFontSize
|
|
+ * @a_relative: the new relative font size
|
|
+ *
|
|
+ * Returns CR_OK upon successful completion, an error code otherwise.
|
|
+ */
|
|
+enum CRStatus
|
|
+cr_font_size_set_relative_font_size (CRFontSize *a_this,
|
|
+ enum CRRelativeFontSize a_relative)
|
|
+{
|
|
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR) ;
|
|
+ g_return_val_if_fail (a_relative >= FONT_SIZE_LARGER
|
|
+ && a_relative < NB_RELATIVE_FONT_SIZE,
|
|
+ CR_BAD_PARAM_ERROR) ;
|
|
+
|
|
+ a_this->type = RELATIVE_FONT_SIZE ;
|
|
+ a_this->value.relative = a_relative ;
|
|
+ return CR_OK ;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_font_size_set_absolute_font_size:
|
|
+ * @a_this: the current instance of #CRFontSize
|
|
+ * @a_num_type: the type of number to set.
|
|
+ * @a_value: the actual value to set.
|
|
+ *
|
|
+ * Returns CR_OK upon succesful completion, an error code otherwise.
|
|
+ */
|
|
+enum CRStatus
|
|
+cr_font_size_set_absolute_font_size (CRFontSize *a_this,
|
|
+ enum CRNumType a_num_type,
|
|
+ gdouble a_value)
|
|
+{
|
|
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR) ;
|
|
+ g_return_val_if_fail (a_num_type >= NUM_AUTO
|
|
+ && a_num_type < NB_NUM_TYPE,
|
|
+ CR_BAD_PARAM_ERROR) ;
|
|
+
|
|
+ a_this->type = ABSOLUTE_FONT_SIZE ;
|
|
+ cr_num_set (&a_this->value.absolute,
|
|
+ a_value, a_num_type) ;
|
|
+ return CR_OK ;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_font_size_set_to_inherit:
|
|
+ * @a_this: the current instance of #CRFontSize
|
|
+ *
|
|
+ * Returns CR_OK upon succesful completion, an error code otherwise.
|
|
+ */
|
|
+enum CRStatus
|
|
+cr_font_size_set_to_inherit (CRFontSize *a_this)
|
|
+{
|
|
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR) ;
|
|
+
|
|
+ cr_font_size_clear (a_this) ;
|
|
+ a_this->type = INHERITED_FONT_SIZE ;
|
|
+
|
|
+ return CR_OK ;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_font_size_is_set_to_inherit:
|
|
+ * @a_this: the current instance of #CRFontSize.
|
|
+ *
|
|
+ * Returns TRUE if the current instance is set to 'inherit'.
|
|
+ */
|
|
+gboolean
|
|
+cr_font_size_is_set_to_inherit (CRFontSize const *a_this)
|
|
+{
|
|
+ g_return_val_if_fail (a_this, FALSE) ;
|
|
+
|
|
+ return a_this->type == INHERITED_FONT_SIZE ;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_font_size_to_string:
|
|
+ * @a_this: the current instance of #CRFontSize
|
|
+ *
|
|
+ * Returns the serialized form of #CRFontSize. The returned string
|
|
+ * has to bee freed using g_free().
|
|
+ */
|
|
+gchar *
|
|
+cr_font_size_to_string (CRFontSize const * a_this)
|
|
+{
|
|
+ gchar *str = NULL;
|
|
+
|
|
+ if (!a_this) {
|
|
+ str = g_strdup ("NULL");
|
|
+ g_return_val_if_fail (str, NULL);
|
|
+ return str;
|
|
+ }
|
|
+ switch (a_this->type) {
|
|
+ case PREDEFINED_ABSOLUTE_FONT_SIZE:
|
|
+ str = g_strdup (cr_predefined_absolute_font_size_to_string
|
|
+ (a_this->value.predefined));
|
|
+ break;
|
|
+ case ABSOLUTE_FONT_SIZE:
|
|
+ str = (gchar *) cr_num_to_string (&a_this->value.absolute);
|
|
+ break;
|
|
+ case RELATIVE_FONT_SIZE:
|
|
+ str = g_strdup (cr_relative_font_size_to_string
|
|
+ (a_this->value.relative));
|
|
+ break;
|
|
+ case INHERITED_FONT_SIZE:
|
|
+ str = g_strdup ("inherit");
|
|
+ break;
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+ return str;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_font_size_get_smaller_predefined:
|
|
+ * @a_font_size: the font size to consider.
|
|
+ * @a_smaller_size: out parameter. The a smaller value than @a_font_size.
|
|
+ */
|
|
+void
|
|
+cr_font_size_get_smaller_predefined_font_size
|
|
+ (enum CRPredefinedAbsoluteFontSize a_font_size,
|
|
+ enum CRPredefinedAbsoluteFontSize *a_smaller_size)
|
|
+{
|
|
+ enum CRPredefinedAbsoluteFontSize result = FONT_SIZE_MEDIUM ;
|
|
+
|
|
+ g_return_if_fail (a_smaller_size) ;
|
|
+ g_return_if_fail (a_font_size < NB_PREDEFINED_ABSOLUTE_FONT_SIZES
|
|
+ && a_font_size >= FONT_SIZE_XX_SMALL) ;
|
|
+
|
|
+ switch (a_font_size) {
|
|
+ case FONT_SIZE_XX_SMALL:
|
|
+ result = FONT_SIZE_XX_SMALL ;
|
|
+ break ;
|
|
+ case FONT_SIZE_X_SMALL:
|
|
+ result = FONT_SIZE_XX_SMALL ;
|
|
+ break ;
|
|
+ case FONT_SIZE_SMALL:
|
|
+ result = FONT_SIZE_X_SMALL;
|
|
+ break ;
|
|
+ case FONT_SIZE_MEDIUM:
|
|
+ result = FONT_SIZE_SMALL;
|
|
+ break ;
|
|
+ case FONT_SIZE_LARGE:
|
|
+ result = FONT_SIZE_MEDIUM;
|
|
+ break ;
|
|
+ case FONT_SIZE_X_LARGE:
|
|
+ result = FONT_SIZE_LARGE;
|
|
+ break ;
|
|
+ case FONT_SIZE_XX_LARGE:
|
|
+ result = FONT_SIZE_XX_LARGE;
|
|
+ break ;
|
|
+ case FONT_SIZE_INHERIT:
|
|
+ cr_utils_trace_info ("can't return a smaller size for FONT_SIZE_INHERIT") ;
|
|
+ result = FONT_SIZE_MEDIUM ;
|
|
+ break ;
|
|
+ default:
|
|
+ cr_utils_trace_info ("Unknown FONT_SIZE") ;
|
|
+ result = FONT_SIZE_MEDIUM ;
|
|
+ break ;
|
|
+ }
|
|
+ *a_smaller_size = result ;
|
|
+}
|
|
+
|
|
+
|
|
+/**
|
|
+ * cr_font_size_get_larger_predefined_font_size:
|
|
+ * @a_font_size: the font size to consider.
|
|
+ * @a_larger_size: out parameter. the font size considered larger than
|
|
+ * @a_font_size.
|
|
+ *
|
|
+ */
|
|
+void
|
|
+cr_font_size_get_larger_predefined_font_size
|
|
+ (enum CRPredefinedAbsoluteFontSize a_font_size,
|
|
+ enum CRPredefinedAbsoluteFontSize *a_larger_size)
|
|
+{
|
|
+ enum CRPredefinedAbsoluteFontSize result = FONT_SIZE_MEDIUM ;
|
|
+
|
|
+ g_return_if_fail (a_larger_size) ;
|
|
+ g_return_if_fail (a_font_size >= FONT_SIZE_XX_SMALL
|
|
+ && a_font_size < NB_PREDEFINED_ABSOLUTE_FONT_SIZES) ;
|
|
+
|
|
+ switch (a_font_size) {
|
|
+ case FONT_SIZE_XX_SMALL:
|
|
+ result = FONT_SIZE_X_SMALL ;
|
|
+ break ;
|
|
+ case FONT_SIZE_X_SMALL:
|
|
+ result = FONT_SIZE_SMALL ;
|
|
+ break ;
|
|
+ case FONT_SIZE_SMALL:
|
|
+ result = FONT_SIZE_MEDIUM;
|
|
+ break ;
|
|
+ case FONT_SIZE_MEDIUM:
|
|
+ result = FONT_SIZE_LARGE;
|
|
+ break ;
|
|
+ case FONT_SIZE_LARGE:
|
|
+ result = FONT_SIZE_X_LARGE;
|
|
+ break ;
|
|
+ case FONT_SIZE_X_LARGE:
|
|
+ result = FONT_SIZE_XX_LARGE ;
|
|
+ break ;
|
|
+ case FONT_SIZE_XX_LARGE:
|
|
+ result = FONT_SIZE_XX_LARGE;
|
|
+ break ;
|
|
+ case FONT_SIZE_INHERIT:
|
|
+ cr_utils_trace_info ("can't return a bigger size for FONT_SIZE_INHERIT") ;
|
|
+ result = FONT_SIZE_MEDIUM ;
|
|
+ break ;
|
|
+ default:
|
|
+ cr_utils_trace_info ("Unknown FONT_SIZE") ;
|
|
+ result = FONT_SIZE_MEDIUM ;
|
|
+ break ;
|
|
+ }
|
|
+ *a_larger_size = result ;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_font_size_is_predefined_absolute_font_size:
|
|
+ * @a_font_size: the font size to consider.
|
|
+ *
|
|
+ * Returns TRUE if the instance is an predefined absolute font size, FALSE
|
|
+ * otherwise.
|
|
+ */
|
|
+gboolean
|
|
+cr_font_size_is_predefined_absolute_font_size
|
|
+ (enum CRPredefinedAbsoluteFontSize a_font_size)
|
|
+{
|
|
+ if (a_font_size >= FONT_SIZE_XX_SMALL
|
|
+ && a_font_size < NB_PREDEFINED_ABSOLUTE_FONT_SIZES) {
|
|
+ return TRUE ;
|
|
+ } else {
|
|
+ return FALSE ;
|
|
+ }
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_font_size_adjust_to_string:
|
|
+ * @a_this: the instance of #CRFontSizeAdjust.
|
|
+ *
|
|
+ * Returns the serialized form of #CRFontSizeAdjust
|
|
+ */
|
|
+gchar *
|
|
+cr_font_size_adjust_to_string (CRFontSizeAdjust const * a_this)
|
|
+{
|
|
+ gchar *str = NULL;
|
|
+
|
|
+ if (!a_this) {
|
|
+ str = g_strdup ("NULL");
|
|
+ g_return_val_if_fail (str, NULL);
|
|
+ return str;
|
|
+ }
|
|
+
|
|
+ switch (a_this->type) {
|
|
+ case FONT_SIZE_ADJUST_NONE:
|
|
+ str = g_strdup ("none");
|
|
+ break;
|
|
+ case FONT_SIZE_ADJUST_NUMBER:
|
|
+ if (a_this->num)
|
|
+ str = (gchar *) cr_num_to_string (a_this->num);
|
|
+ else
|
|
+ str = g_strdup ("unknown font-size-adjust property value"); /* Should raise an error no?*/
|
|
+ break;
|
|
+ case FONT_SIZE_ADJUST_INHERIT:
|
|
+ str = g_strdup ("inherit");
|
|
+ }
|
|
+ return str;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_font_style_to_string:
|
|
+ * @a_code: the current instance of #CRFontStyle .
|
|
+ *
|
|
+ * Returns the serialized #CRFontStyle. The caller must free the returned
|
|
+ * string using g_free().
|
|
+ */
|
|
+const gchar *
|
|
+cr_font_style_to_string (enum CRFontStyle a_code)
|
|
+{
|
|
+ gchar *str = NULL;
|
|
+
|
|
+ switch (a_code) {
|
|
+ case FONT_STYLE_NORMAL:
|
|
+ str = (gchar *) "normal";
|
|
+ break;
|
|
+ case FONT_STYLE_ITALIC:
|
|
+ str = (gchar *) "italic";
|
|
+ break;
|
|
+ case FONT_STYLE_OBLIQUE:
|
|
+ str = (gchar *) "oblique";
|
|
+ break;
|
|
+ case FONT_STYLE_INHERIT:
|
|
+ str = (gchar *) "inherit";
|
|
+ break;
|
|
+ default:
|
|
+ str = (gchar *) "unknown font style value";
|
|
+ break;
|
|
+ }
|
|
+ return str;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_font_variant_to_string:
|
|
+ * @a_code: the current instance of #CRFontVariant.
|
|
+ *
|
|
+ * Returns the serialized form of #CRFontVariant. The caller has
|
|
+ * to free the returned string using g_free().
|
|
+ */
|
|
+const gchar *
|
|
+cr_font_variant_to_string (enum CRFontVariant a_code)
|
|
+{
|
|
+ gchar *str = NULL;
|
|
+
|
|
+ switch (a_code) {
|
|
+ case FONT_VARIANT_NORMAL:
|
|
+ str = (gchar *) "normal";
|
|
+ break;
|
|
+ case FONT_VARIANT_SMALL_CAPS:
|
|
+ str = (gchar *) "small-caps";
|
|
+ break;
|
|
+ case FONT_VARIANT_INHERIT:
|
|
+ str = (gchar *) "inherit";
|
|
+ break;
|
|
+ }
|
|
+ return str;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_font_weight_get_bolder:
|
|
+ * @a_weight: the #CRFontWeight to consider.
|
|
+ *
|
|
+ * Returns a font weight bolder than @a_weight
|
|
+ */
|
|
+enum CRFontWeight
|
|
+cr_font_weight_get_bolder (enum CRFontWeight a_weight)
|
|
+{
|
|
+ if (a_weight == FONT_WEIGHT_INHERIT) {
|
|
+ cr_utils_trace_info ("can't return a bolder weight for FONT_WEIGHT_INHERIT") ;
|
|
+ return a_weight;
|
|
+ } else if (a_weight >= FONT_WEIGHT_900) {
|
|
+ return FONT_WEIGHT_900 ;
|
|
+ } else if (a_weight < FONT_WEIGHT_NORMAL) {
|
|
+ return FONT_WEIGHT_NORMAL ;
|
|
+ } else if (a_weight == FONT_WEIGHT_BOLDER
|
|
+ || a_weight == FONT_WEIGHT_LIGHTER) {
|
|
+ cr_utils_trace_info ("FONT_WEIGHT_BOLDER or FONT_WEIGHT_LIGHTER should not appear here") ;
|
|
+ return FONT_WEIGHT_NORMAL ;
|
|
+ } else {
|
|
+ return a_weight << 1 ;
|
|
+ }
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_font_weight_to_string:
|
|
+ * @a_code: the font weight to consider.
|
|
+ *
|
|
+ * Returns the serialized form of #CRFontWeight.
|
|
+ */
|
|
+const gchar *
|
|
+cr_font_weight_to_string (enum CRFontWeight a_code)
|
|
+{
|
|
+ gchar *str = NULL;
|
|
+
|
|
+ switch (a_code) {
|
|
+ case FONT_WEIGHT_NORMAL:
|
|
+ str = (gchar *) "normal";
|
|
+ break;
|
|
+ case FONT_WEIGHT_BOLD:
|
|
+ str = (gchar *) "bold";
|
|
+ break;
|
|
+ case FONT_WEIGHT_BOLDER:
|
|
+ str = (gchar *) "bolder";
|
|
+ break;
|
|
+ case FONT_WEIGHT_LIGHTER:
|
|
+ str = (gchar *) "lighter";
|
|
+ break;
|
|
+ case FONT_WEIGHT_100:
|
|
+ str = (gchar *) "100";
|
|
+ break;
|
|
+ case FONT_WEIGHT_200:
|
|
+ str = (gchar *) "200";
|
|
+ break;
|
|
+ case FONT_WEIGHT_300:
|
|
+ str = (gchar *) "300";
|
|
+ break;
|
|
+ case FONT_WEIGHT_400:
|
|
+ str = (gchar *) "400";
|
|
+ break;
|
|
+ case FONT_WEIGHT_500:
|
|
+ str = (gchar *) "500";
|
|
+ break;
|
|
+ case FONT_WEIGHT_600:
|
|
+ str = (gchar *) "600";
|
|
+ break;
|
|
+ case FONT_WEIGHT_700:
|
|
+ str = (gchar *) "700";
|
|
+ break;
|
|
+ case FONT_WEIGHT_800:
|
|
+ str = (gchar *) "800";
|
|
+ break;
|
|
+ case FONT_WEIGHT_900:
|
|
+ str = (gchar *) "900";
|
|
+ break;
|
|
+ case FONT_WEIGHT_INHERIT:
|
|
+ str = (gchar *) "inherit";
|
|
+ break;
|
|
+ default:
|
|
+ str = (gchar *) "unknown font-weight property value";
|
|
+ break;
|
|
+ }
|
|
+ return str;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_font_stretch_to_string:
|
|
+ * @a_code: the instance of #CRFontStretch to consider.
|
|
+ *
|
|
+ * Returns the serialized form of #CRFontStretch.
|
|
+ */
|
|
+const gchar *
|
|
+cr_font_stretch_to_string (enum CRFontStretch a_code)
|
|
+{
|
|
+ gchar *str = NULL;
|
|
+
|
|
+ switch (a_code) {
|
|
+ case FONT_STRETCH_NORMAL:
|
|
+ str = (gchar *) "normal";
|
|
+ break;
|
|
+ case FONT_STRETCH_WIDER:
|
|
+ str = (gchar *) "wider";
|
|
+ break;
|
|
+ case FONT_STRETCH_NARROWER:
|
|
+ str = (gchar *) "narrower";
|
|
+ break;
|
|
+ case FONT_STRETCH_ULTRA_CONDENSED:
|
|
+ str = (gchar *) "ultra-condensed";
|
|
+ break;
|
|
+ case FONT_STRETCH_EXTRA_CONDENSED:
|
|
+ str = (gchar *) "extra-condensed";
|
|
+ break;
|
|
+ case FONT_STRETCH_CONDENSED:
|
|
+ str = (gchar *) "condensed";
|
|
+ break;
|
|
+ case FONT_STRETCH_SEMI_CONDENSED:
|
|
+ str = (gchar *) "semi-condensed";
|
|
+ break;
|
|
+ case FONT_STRETCH_SEMI_EXPANDED:
|
|
+ str = (gchar *) "semi-expanded";
|
|
+ break;
|
|
+ case FONT_STRETCH_EXPANDED:
|
|
+ str = (gchar *) "expanded";
|
|
+ break;
|
|
+ case FONT_STRETCH_EXTRA_EXPANDED:
|
|
+ str = (gchar *) "extra-expaned";
|
|
+ break;
|
|
+ case FONT_STRETCH_ULTRA_EXPANDED:
|
|
+ str = (gchar *) "ultra-expanded";
|
|
+ break;
|
|
+ case FONT_STRETCH_INHERIT:
|
|
+ str = (gchar *) "inherit";
|
|
+ break;
|
|
+ }
|
|
+ return str;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_font_size_destroy:
|
|
+ * @a_font_size: the font size to destroy
|
|
+ *
|
|
+ */
|
|
+void
|
|
+cr_font_size_destroy (CRFontSize * a_font_size)
|
|
+{
|
|
+ g_return_if_fail (a_font_size);
|
|
+
|
|
+ g_free (a_font_size) ;
|
|
+}
|
|
+
|
|
+/*******************************************************
|
|
+ *'font-size-adjust' manipulation function definition
|
|
+ *******************************************************/
|
|
+
|
|
+/**
|
|
+ * cr_font_size_adjust_new:
|
|
+ *
|
|
+ * Returns a newly built instance of #CRFontSizeAdjust
|
|
+ */
|
|
+CRFontSizeAdjust *
|
|
+cr_font_size_adjust_new (void)
|
|
+{
|
|
+ CRFontSizeAdjust *result = NULL;
|
|
+
|
|
+ result = g_try_malloc (sizeof (CRFontSizeAdjust));
|
|
+ if (!result) {
|
|
+ cr_utils_trace_info ("Out of memory");
|
|
+ return NULL;
|
|
+ }
|
|
+ memset (result, 0, sizeof (CRFontSizeAdjust));
|
|
+
|
|
+ return result;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_font_size_adjust_destroy:
|
|
+ * @a_this: the current instance of #CRFontSizeAdjust.
|
|
+ *
|
|
+ */
|
|
+void
|
|
+cr_font_size_adjust_destroy (CRFontSizeAdjust * a_this)
|
|
+{
|
|
+ g_return_if_fail (a_this);
|
|
+
|
|
+ if (a_this->type == FONT_SIZE_ADJUST_NUMBER && a_this->num) {
|
|
+ cr_num_destroy (a_this->num);
|
|
+ a_this->num = NULL;
|
|
+ }
|
|
+}
|
|
diff --git a/src/st/croco/cr-fonts.h b/src/st/croco/cr-fonts.h
|
|
new file mode 100644
|
|
index 000000000..9eaeeeb98
|
|
--- /dev/null
|
|
+++ b/src/st/croco/cr-fonts.h
|
|
@@ -0,0 +1,315 @@
|
|
+/* -*- 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.
|
|
+ */
|
|
+
|
|
+#ifndef __CR_FONTS_H__
|
|
+#define __CR_FONTS_H__
|
|
+
|
|
+#include "cr-utils.h"
|
|
+#include "cr-num.h"
|
|
+
|
|
+/**
|
|
+ *@file
|
|
+ *Various type declarations about font selection related
|
|
+ *properties.
|
|
+ */
|
|
+G_BEGIN_DECLS
|
|
+
|
|
+
|
|
+enum CRFontFamilyType
|
|
+{
|
|
+ FONT_FAMILY_SANS_SERIF,
|
|
+ FONT_FAMILY_SERIF,
|
|
+ FONT_FAMILY_CURSIVE,
|
|
+ FONT_FAMILY_FANTASY,
|
|
+ FONT_FAMILY_MONOSPACE,
|
|
+ FONT_FAMILY_NON_GENERIC,
|
|
+ FONT_FAMILY_INHERIT,
|
|
+ /**/
|
|
+ NB_FONT_FAMILIE_TYPES
|
|
+} ;
|
|
+
|
|
+typedef struct _CRFontFamily CRFontFamily ;
|
|
+
|
|
+struct _CRFontFamily
|
|
+{
|
|
+ enum CRFontFamilyType type ;
|
|
+
|
|
+ /*
|
|
+ *The name of the font family, in case
|
|
+ *it is non generic.
|
|
+ *Is set only if the type is FONT_FAMILY_NON_GENERIC.
|
|
+ */
|
|
+ guchar *name ;
|
|
+
|
|
+ CRFontFamily *next ;
|
|
+ CRFontFamily *prev ;
|
|
+} ;
|
|
+
|
|
+
|
|
+/**
|
|
+ *The different types
|
|
+ *of absolute font size.
|
|
+ *This is used by the 'font-size'
|
|
+ *property defined in css2 spec
|
|
+ *in chapter 15.2.4 .
|
|
+ *These values a indexes of
|
|
+ *table of size so please, do not
|
|
+ *change their definition order unless
|
|
+ *you know what you are doing.
|
|
+ */
|
|
+enum CRPredefinedAbsoluteFontSize
|
|
+{
|
|
+ FONT_SIZE_XX_SMALL=0,
|
|
+ FONT_SIZE_X_SMALL,
|
|
+ FONT_SIZE_SMALL,
|
|
+ FONT_SIZE_MEDIUM,
|
|
+ FONT_SIZE_LARGE,
|
|
+ FONT_SIZE_X_LARGE,
|
|
+ FONT_SIZE_XX_LARGE,
|
|
+ FONT_SIZE_INHERIT,
|
|
+ NB_PREDEFINED_ABSOLUTE_FONT_SIZES
|
|
+} ;
|
|
+
|
|
+/**
|
|
+ *The different types
|
|
+ *of relative font size.
|
|
+ *This is used by the 'font-size'
|
|
+ *property defined in css2 spec
|
|
+ *in chapter 15.2.4 .
|
|
+ *These values a indexes of
|
|
+ *table of size so please, do not
|
|
+ *change their definition order unless
|
|
+ *you know what you are doing.
|
|
+ */
|
|
+enum CRRelativeFontSize
|
|
+{
|
|
+ FONT_SIZE_LARGER,
|
|
+ FONT_SIZE_SMALLER,
|
|
+ NB_RELATIVE_FONT_SIZE
|
|
+} ;
|
|
+
|
|
+/**
|
|
+ *The type of font-size property.
|
|
+ *Used to define the type of #CRFontSize .
|
|
+ *See css2 spec chapter 15.2.4 to understand.
|
|
+ */
|
|
+enum CRFontSizeType {
|
|
+ /**
|
|
+ *If the type of #CRFontSize is
|
|
+ *PREDEFINED_ABSOLUTE_FONT_SIZE,
|
|
+ *the CRFontSize::value.predefined_absolute
|
|
+ *field will be defined.
|
|
+ */
|
|
+ PREDEFINED_ABSOLUTE_FONT_SIZE,
|
|
+
|
|
+ /**
|
|
+ *If the type of #CRFontSize is
|
|
+ *ABSOLUTE_FONT_SIZE,
|
|
+ *the CRFontSize::value.absolute
|
|
+ *field will be defined.
|
|
+ */
|
|
+ ABSOLUTE_FONT_SIZE,
|
|
+
|
|
+ /**
|
|
+ *If the type of #CRFontSize is
|
|
+ *RELATIVE_FONT_SIZE,
|
|
+ *the CRFontSize::value.relative
|
|
+ *field will be defined.
|
|
+ */
|
|
+ RELATIVE_FONT_SIZE,
|
|
+
|
|
+ /**
|
|
+ *If the type of #CRFontSize is
|
|
+ *INHERITED_FONT_SIZE,
|
|
+ *the None of the field of the CRFontSize::value enum
|
|
+ *will be defined.
|
|
+ */
|
|
+ INHERITED_FONT_SIZE,
|
|
+
|
|
+ NB_FONT_SIZE_TYPE
|
|
+} ;
|
|
+
|
|
+typedef struct _CRFontSize CRFontSize ;
|
|
+struct _CRFontSize {
|
|
+ enum CRFontSizeType type ;
|
|
+ union {
|
|
+ enum CRPredefinedAbsoluteFontSize predefined ;
|
|
+ enum CRRelativeFontSize relative ;
|
|
+ CRNum absolute ;
|
|
+ } value;
|
|
+} ;
|
|
+
|
|
+enum CRFontSizeAdjustType
|
|
+{
|
|
+ FONT_SIZE_ADJUST_NONE = 0,
|
|
+ FONT_SIZE_ADJUST_NUMBER,
|
|
+ FONT_SIZE_ADJUST_INHERIT
|
|
+} ;
|
|
+typedef struct _CRFontSizeAdjust CRFontSizeAdjust ;
|
|
+struct _CRFontSizeAdjust
|
|
+{
|
|
+ enum CRFontSizeAdjustType type ;
|
|
+ CRNum *num ;
|
|
+} ;
|
|
+
|
|
+enum CRFontStyle
|
|
+{
|
|
+ FONT_STYLE_NORMAL=0,
|
|
+ FONT_STYLE_ITALIC,
|
|
+ FONT_STYLE_OBLIQUE,
|
|
+ FONT_STYLE_INHERIT
|
|
+} ;
|
|
+
|
|
+enum CRFontVariant
|
|
+{
|
|
+ FONT_VARIANT_NORMAL=0,
|
|
+ FONT_VARIANT_SMALL_CAPS,
|
|
+ FONT_VARIANT_INHERIT
|
|
+} ;
|
|
+
|
|
+enum CRFontWeight
|
|
+{
|
|
+ FONT_WEIGHT_NORMAL = 1,
|
|
+ FONT_WEIGHT_BOLD = 1<<1,
|
|
+ FONT_WEIGHT_BOLDER = 1<<2,
|
|
+ FONT_WEIGHT_LIGHTER = 1<<3,
|
|
+ FONT_WEIGHT_100 = 1<<4,
|
|
+ FONT_WEIGHT_200 = 1<<5,
|
|
+ FONT_WEIGHT_300 = 1<<6,
|
|
+ FONT_WEIGHT_400 = 1<<7,
|
|
+ FONT_WEIGHT_500 = 1<<8,
|
|
+ FONT_WEIGHT_600 = 1<<9,
|
|
+ FONT_WEIGHT_700 = 1<<10,
|
|
+ FONT_WEIGHT_800 = 1<<11,
|
|
+ FONT_WEIGHT_900 = 1<<12,
|
|
+ FONT_WEIGHT_INHERIT = 1<<13,
|
|
+ NB_FONT_WEIGHTS
|
|
+} ;
|
|
+
|
|
+enum CRFontStretch
|
|
+{
|
|
+ FONT_STRETCH_NORMAL=0,
|
|
+ FONT_STRETCH_WIDER,
|
|
+ FONT_STRETCH_NARROWER,
|
|
+ FONT_STRETCH_ULTRA_CONDENSED,
|
|
+ FONT_STRETCH_EXTRA_CONDENSED,
|
|
+ FONT_STRETCH_CONDENSED,
|
|
+ FONT_STRETCH_SEMI_CONDENSED,
|
|
+ FONT_STRETCH_SEMI_EXPANDED,
|
|
+ FONT_STRETCH_EXPANDED,
|
|
+ FONT_STRETCH_EXTRA_EXPANDED,
|
|
+ FONT_STRETCH_ULTRA_EXPANDED,
|
|
+ FONT_STRETCH_INHERIT
|
|
+} ;
|
|
+
|
|
+/**************************************
|
|
+ *'font-family' manipulation functions
|
|
+ ***************************************/
|
|
+CRFontFamily *
|
|
+cr_font_family_new (enum CRFontFamilyType a_type, guchar *a_name) ;
|
|
+
|
|
+CRFontFamily *
|
|
+cr_font_family_append (CRFontFamily *a_this,
|
|
+ CRFontFamily *a_family_to_append) ;
|
|
+
|
|
+guchar *
|
|
+cr_font_family_to_string (CRFontFamily const *a_this,
|
|
+ gboolean a_walk_font_family_list) ;
|
|
+
|
|
+CRFontFamily *
|
|
+cr_font_family_prepend (CRFontFamily *a_this,
|
|
+ CRFontFamily *a_family_to_prepend);
|
|
+
|
|
+enum CRStatus
|
|
+cr_font_family_destroy (CRFontFamily *a_this) ;
|
|
+
|
|
+enum CRStatus
|
|
+cr_font_family_set_name (CRFontFamily *a_this, guchar *a_name) ;
|
|
+
|
|
+
|
|
+/************************************
|
|
+ *'font-size' manipulation functions
|
|
+ ***********************************/
|
|
+
|
|
+CRFontSize * cr_font_size_new (void) ;
|
|
+
|
|
+enum CRStatus cr_font_size_clear (CRFontSize *a_this) ;
|
|
+
|
|
+enum CRStatus cr_font_size_copy (CRFontSize *a_dst,
|
|
+ CRFontSize const *a_src) ;
|
|
+enum CRStatus cr_font_size_set_predefined_absolute_font_size (CRFontSize *a_this,
|
|
+ enum CRPredefinedAbsoluteFontSize a_predefined) ;
|
|
+enum CRStatus cr_font_size_set_relative_font_size (CRFontSize *a_this,
|
|
+ enum CRRelativeFontSize a_relative) ;
|
|
+
|
|
+enum CRStatus cr_font_size_set_absolute_font_size (CRFontSize *a_this,
|
|
+ enum CRNumType a_num_type,
|
|
+ gdouble a_value) ;
|
|
+
|
|
+enum CRStatus cr_font_size_set_to_inherit (CRFontSize *a_this) ;
|
|
+
|
|
+gboolean cr_font_size_is_set_to_inherit (CRFontSize const *a_this) ;
|
|
+
|
|
+gchar* cr_font_size_to_string (CRFontSize const *a_this) ;
|
|
+
|
|
+void cr_font_size_destroy (CRFontSize *a_font_size) ;
|
|
+
|
|
+/*******************************************************
|
|
+ *'font-size-adjust' manipulation function declarations
|
|
+ *******************************************************/
|
|
+
|
|
+CRFontSizeAdjust * cr_font_size_adjust_new (void) ;
|
|
+
|
|
+gchar * cr_font_size_adjust_to_string (CRFontSizeAdjust const *a_this) ;
|
|
+
|
|
+void cr_font_size_adjust_destroy (CRFontSizeAdjust *a_this) ;
|
|
+
|
|
+void
|
|
+cr_font_size_get_smaller_predefined_font_size (enum CRPredefinedAbsoluteFontSize a_font_size,
|
|
+ enum CRPredefinedAbsoluteFontSize *a_smaller_size) ;
|
|
+void
|
|
+cr_font_size_get_larger_predefined_font_size (enum CRPredefinedAbsoluteFontSize a_font_size,
|
|
+ enum CRPredefinedAbsoluteFontSize *a_larger_size) ;
|
|
+
|
|
+gboolean
|
|
+cr_font_size_is_predefined_absolute_font_size (enum CRPredefinedAbsoluteFontSize a_font_size) ;
|
|
+
|
|
+/***********************************
|
|
+ *various other font related functions
|
|
+ ***********************************/
|
|
+const gchar * cr_font_style_to_string (enum CRFontStyle a_code) ;
|
|
+
|
|
+const gchar * cr_font_weight_to_string (enum CRFontWeight a_code) ;
|
|
+
|
|
+enum CRFontWeight
|
|
+cr_font_weight_get_bolder (enum CRFontWeight a_weight) ;
|
|
+
|
|
+const gchar * cr_font_variant_to_string (enum CRFontVariant a_code) ;
|
|
+
|
|
+const gchar * cr_font_stretch_to_string (enum CRFontStretch a_code) ;
|
|
+
|
|
+G_END_DECLS
|
|
+
|
|
+#endif
|
|
diff --git a/src/st/croco/cr-input.c b/src/st/croco/cr-input.c
|
|
new file mode 100644
|
|
index 000000000..3b63a88ee
|
|
--- /dev/null
|
|
+++ b/src/st/croco/cr-input.c
|
|
@@ -0,0 +1,1191 @@
|
|
+/* -*- 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 "stdio.h"
|
|
+#include <string.h>
|
|
+#include "cr-input.h"
|
|
+#include "cr-enc-handler.h"
|
|
+
|
|
+/**
|
|
+ *@CRInput:
|
|
+ *
|
|
+ *The definition of the #CRInput class.
|
|
+ */
|
|
+
|
|
+/*******************
|
|
+ *Private type defs
|
|
+ *******************/
|
|
+
|
|
+/**
|
|
+ *The private attributes of
|
|
+ *the #CRInputPriv class.
|
|
+ */
|
|
+struct _CRInputPriv {
|
|
+ /*
|
|
+ *The input buffer
|
|
+ */
|
|
+ guchar *in_buf;
|
|
+ gulong in_buf_size;
|
|
+
|
|
+ gulong nb_bytes;
|
|
+
|
|
+ /*
|
|
+ *The index of the next byte
|
|
+ *to be read.
|
|
+ */
|
|
+ gulong next_byte_index;
|
|
+
|
|
+ /*
|
|
+ *The current line number
|
|
+ */
|
|
+ gulong line;
|
|
+
|
|
+ /*
|
|
+ *The current col number
|
|
+ */
|
|
+ gulong col;
|
|
+
|
|
+ gboolean end_of_line;
|
|
+ gboolean end_of_input;
|
|
+
|
|
+ /*
|
|
+ *the reference count of this
|
|
+ *instance.
|
|
+ */
|
|
+ guint ref_count;
|
|
+ gboolean free_in_buf;
|
|
+};
|
|
+
|
|
+#define PRIVATE(object) (object)->priv
|
|
+
|
|
+/***************************
|
|
+ *private constants
|
|
+ **************************/
|
|
+#define CR_INPUT_MEM_CHUNK_SIZE 1024 * 4
|
|
+
|
|
+static CRInput *cr_input_new_real (void);
|
|
+
|
|
+static CRInput *
|
|
+cr_input_new_real (void)
|
|
+{
|
|
+ CRInput *result = NULL;
|
|
+
|
|
+ result = g_try_malloc (sizeof (CRInput));
|
|
+ if (!result) {
|
|
+ cr_utils_trace_info ("Out of memory");
|
|
+ return NULL;
|
|
+ }
|
|
+ memset (result, 0, sizeof (CRInput));
|
|
+
|
|
+ PRIVATE (result) = g_try_malloc (sizeof (CRInputPriv));
|
|
+ if (!PRIVATE (result)) {
|
|
+ cr_utils_trace_info ("Out of memory");
|
|
+ g_free (result);
|
|
+ return NULL;
|
|
+ }
|
|
+ memset (PRIVATE (result), 0, sizeof (CRInputPriv));
|
|
+ PRIVATE (result)->free_in_buf = TRUE;
|
|
+ return result;
|
|
+}
|
|
+
|
|
+/****************
|
|
+ *Public methods
|
|
+ ***************/
|
|
+
|
|
+/**
|
|
+ * cr_input_new_from_buf:
|
|
+ *@a_buf: the memory buffer to create the input stream from.
|
|
+ *The #CRInput keeps this pointer so user should not free it !.
|
|
+ *@a_len: the size of the input buffer.
|
|
+ *@a_enc: the buffer's encoding.
|
|
+ *@a_free_buf: if set to TRUE, this a_buf will be freed
|
|
+ *at the destruction of this instance. If set to false, it is up
|
|
+ *to the caller to free it.
|
|
+ *
|
|
+ *Creates a new input stream from a memory buffer.
|
|
+ *Returns the newly built instance of #CRInput.
|
|
+ */
|
|
+CRInput *
|
|
+cr_input_new_from_buf (guchar * a_buf,
|
|
+ gulong a_len,
|
|
+ enum CREncoding a_enc,
|
|
+ gboolean a_free_buf)
|
|
+{
|
|
+ CRInput *result = NULL;
|
|
+ enum CRStatus status = CR_OK;
|
|
+ CREncHandler *enc_handler = NULL;
|
|
+ gulong len = a_len;
|
|
+
|
|
+ g_return_val_if_fail (a_buf, NULL);
|
|
+
|
|
+ result = cr_input_new_real ();
|
|
+ g_return_val_if_fail (result, NULL);
|
|
+
|
|
+ /*transform the encoding in utf8 */
|
|
+ if (a_enc != CR_UTF_8) {
|
|
+ enc_handler = cr_enc_handler_get_instance (a_enc);
|
|
+ if (!enc_handler) {
|
|
+ goto error;
|
|
+ }
|
|
+
|
|
+ status = cr_enc_handler_convert_input
|
|
+ (enc_handler, a_buf, &len,
|
|
+ &PRIVATE (result)->in_buf,
|
|
+ &PRIVATE (result)->in_buf_size);
|
|
+ if (status != CR_OK)
|
|
+ goto error;
|
|
+ PRIVATE (result)->free_in_buf = TRUE;
|
|
+ if (a_free_buf == TRUE && a_buf) {
|
|
+ g_free (a_buf) ;
|
|
+ a_buf = NULL ;
|
|
+ }
|
|
+ PRIVATE (result)->nb_bytes = PRIVATE (result)->in_buf_size;
|
|
+ } else {
|
|
+ PRIVATE (result)->in_buf = (guchar *) a_buf;
|
|
+ PRIVATE (result)->in_buf_size = a_len;
|
|
+ PRIVATE (result)->nb_bytes = a_len;
|
|
+ PRIVATE (result)->free_in_buf = a_free_buf;
|
|
+ }
|
|
+ PRIVATE (result)->line = 1;
|
|
+ PRIVATE (result)->col = 0;
|
|
+ return result;
|
|
+
|
|
+ error:
|
|
+ if (result) {
|
|
+ cr_input_destroy (result);
|
|
+ result = NULL;
|
|
+ }
|
|
+
|
|
+ return NULL;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_input_new_from_uri:
|
|
+ *@a_file_uri: the file to create *the input stream from.
|
|
+ *@a_enc: the encoding of the file *to create the input from.
|
|
+ *
|
|
+ *Creates a new input stream from
|
|
+ *a file.
|
|
+ *
|
|
+ *Returns the newly created input stream if
|
|
+ *this method could read the file and create it,
|
|
+ *NULL otherwise.
|
|
+ */
|
|
+
|
|
+CRInput *
|
|
+cr_input_new_from_uri (const gchar * a_file_uri, enum CREncoding a_enc)
|
|
+{
|
|
+ CRInput *result = NULL;
|
|
+ enum CRStatus status = CR_OK;
|
|
+ FILE *file_ptr = NULL;
|
|
+ guchar tmp_buf[CR_INPUT_MEM_CHUNK_SIZE] = { 0 };
|
|
+ gulong nb_read = 0,
|
|
+ len = 0,
|
|
+ buf_size = 0;
|
|
+ gboolean loop = TRUE;
|
|
+ guchar *buf = NULL;
|
|
+
|
|
+ g_return_val_if_fail (a_file_uri, NULL);
|
|
+
|
|
+ file_ptr = fopen (a_file_uri, "r");
|
|
+
|
|
+ if (file_ptr == NULL) {
|
|
+
|
|
+#ifdef CR_DEBUG
|
|
+ cr_utils_trace_debug ("could not open file");
|
|
+#endif
|
|
+ g_warning ("Could not open file %s\n", a_file_uri);
|
|
+
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
+ /*load the file */
|
|
+ while (loop) {
|
|
+ nb_read = fread (tmp_buf, 1 /*read bytes */ ,
|
|
+ CR_INPUT_MEM_CHUNK_SIZE /*nb of bytes */ ,
|
|
+ file_ptr);
|
|
+
|
|
+ if (nb_read != CR_INPUT_MEM_CHUNK_SIZE) {
|
|
+ /*we read less chars than we wanted */
|
|
+ if (feof (file_ptr)) {
|
|
+ /*we reached eof */
|
|
+ loop = FALSE;
|
|
+ } else {
|
|
+ /*a pb occurred !! */
|
|
+ cr_utils_trace_debug ("an io error occurred");
|
|
+ status = CR_ERROR;
|
|
+ goto cleanup;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (status == CR_OK) {
|
|
+ /*read went well */
|
|
+ buf = g_realloc (buf, len + CR_INPUT_MEM_CHUNK_SIZE);
|
|
+ memcpy (buf + len, tmp_buf, nb_read);
|
|
+ len += nb_read;
|
|
+ buf_size += CR_INPUT_MEM_CHUNK_SIZE;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (status == CR_OK) {
|
|
+ result = cr_input_new_from_buf (buf, len, a_enc, TRUE);
|
|
+ if (!result) {
|
|
+ goto cleanup;
|
|
+ }
|
|
+ /*
|
|
+ *we should free buf here because it's own by CRInput.
|
|
+ *(see the last parameter of cr_input_new_from_buf().
|
|
+ */
|
|
+ buf = NULL;
|
|
+ }
|
|
+
|
|
+ cleanup:
|
|
+ if (file_ptr) {
|
|
+ fclose (file_ptr);
|
|
+ file_ptr = NULL;
|
|
+ }
|
|
+
|
|
+ if (buf) {
|
|
+ g_free (buf);
|
|
+ buf = NULL;
|
|
+ }
|
|
+
|
|
+ return result;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_input_destroy:
|
|
+ *@a_this: the current instance of #CRInput.
|
|
+ *
|
|
+ *The destructor of the #CRInput class.
|
|
+ */
|
|
+void
|
|
+cr_input_destroy (CRInput * a_this)
|
|
+{
|
|
+ if (a_this == NULL)
|
|
+ return;
|
|
+
|
|
+ if (PRIVATE (a_this)) {
|
|
+ if (PRIVATE (a_this)->in_buf && PRIVATE (a_this)->free_in_buf) {
|
|
+ g_free (PRIVATE (a_this)->in_buf);
|
|
+ PRIVATE (a_this)->in_buf = NULL;
|
|
+ }
|
|
+
|
|
+ g_free (PRIVATE (a_this));
|
|
+ PRIVATE (a_this) = NULL;
|
|
+ }
|
|
+
|
|
+ g_free (a_this);
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_input_ref:
|
|
+ *@a_this: the current instance of #CRInput.
|
|
+ *
|
|
+ *Increments the reference count of the current
|
|
+ *instance of #CRInput.
|
|
+ */
|
|
+void
|
|
+cr_input_ref (CRInput * a_this)
|
|
+{
|
|
+ g_return_if_fail (a_this && PRIVATE (a_this));
|
|
+
|
|
+ PRIVATE (a_this)->ref_count++;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_input_unref:
|
|
+ *@a_this: the current instance of #CRInput.
|
|
+ *
|
|
+ *Decrements the reference count of this instance
|
|
+ *of #CRInput. If the reference count goes down to
|
|
+ *zero, this instance is destroyed.
|
|
+ *
|
|
+ * Returns TRUE if the instance of #CRInput got destroyed, false otherwise.
|
|
+ */
|
|
+gboolean
|
|
+cr_input_unref (CRInput * a_this)
|
|
+{
|
|
+ g_return_val_if_fail (a_this && PRIVATE (a_this), FALSE);
|
|
+
|
|
+ if (PRIVATE (a_this)->ref_count) {
|
|
+ PRIVATE (a_this)->ref_count--;
|
|
+ }
|
|
+
|
|
+ if (PRIVATE (a_this)->ref_count == 0) {
|
|
+ cr_input_destroy (a_this);
|
|
+ return TRUE;
|
|
+ }
|
|
+ return FALSE;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_input_end_of_input:
|
|
+ *@a_this: the current instance of #CRInput.
|
|
+ *@a_end_of_input: out parameter. Is set to TRUE if
|
|
+ *the current instance has reached the end of its input buffer,
|
|
+ *FALSE otherwise.
|
|
+ *
|
|
+ *Tests wether the current instance of
|
|
+ *#CRInput has reached its input buffer.
|
|
+ *
|
|
+ * Returns CR_OK upon successful completion, an error code otherwise.
|
|
+ * Note that all the out parameters of this method are valid if
|
|
+ * and only if this method returns CR_OK.
|
|
+ */
|
|
+enum CRStatus
|
|
+cr_input_end_of_input (CRInput const * a_this, gboolean * a_end_of_input)
|
|
+{
|
|
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
|
|
+ && a_end_of_input, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ *a_end_of_input = (PRIVATE (a_this)->next_byte_index
|
|
+ >= PRIVATE (a_this)->in_buf_size) ? TRUE : FALSE;
|
|
+
|
|
+ return CR_OK;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_input_get_nb_bytes_left:
|
|
+ *@a_this: the current instance of #CRInput.
|
|
+ *
|
|
+ *Returns the number of bytes left in the input stream
|
|
+ *before the end, -1 in case of error.
|
|
+ */
|
|
+glong
|
|
+cr_input_get_nb_bytes_left (CRInput const * a_this)
|
|
+{
|
|
+ g_return_val_if_fail (a_this && PRIVATE (a_this), -1);
|
|
+ g_return_val_if_fail (PRIVATE (a_this)->nb_bytes
|
|
+ <= PRIVATE (a_this)->in_buf_size, -1);
|
|
+ g_return_val_if_fail (PRIVATE (a_this)->next_byte_index
|
|
+ <= PRIVATE (a_this)->nb_bytes, -1);
|
|
+
|
|
+ if (PRIVATE (a_this)->end_of_input)
|
|
+ return 0;
|
|
+
|
|
+ return PRIVATE (a_this)->nb_bytes - PRIVATE (a_this)->next_byte_index;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_input_read_byte:
|
|
+ *@a_this: the current instance of #CRInput.
|
|
+ *@a_byte: out parameter the returned byte.
|
|
+ *
|
|
+ *Gets the next byte of the input.
|
|
+ *Updates the state of the input so that
|
|
+ *the next invocation of this method returns
|
|
+ *the next coming byte.
|
|
+ *
|
|
+ *Returns CR_OK upon successful completion, an error code
|
|
+ *otherwise. All the out parameters of this method are valid if
|
|
+ *and only if this method returns CR_OK.
|
|
+ */
|
|
+enum CRStatus
|
|
+cr_input_read_byte (CRInput * a_this, guchar * a_byte)
|
|
+{
|
|
+ gulong nb_bytes_left = 0;
|
|
+
|
|
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
|
|
+ && a_byte, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ g_return_val_if_fail (PRIVATE (a_this)->next_byte_index <=
|
|
+ PRIVATE (a_this)->nb_bytes, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ if (PRIVATE (a_this)->end_of_input == TRUE)
|
|
+ return CR_END_OF_INPUT_ERROR;
|
|
+
|
|
+ nb_bytes_left = cr_input_get_nb_bytes_left (a_this);
|
|
+
|
|
+ if (nb_bytes_left < 1) {
|
|
+ return CR_END_OF_INPUT_ERROR;
|
|
+ }
|
|
+
|
|
+ *a_byte = PRIVATE (a_this)->in_buf[PRIVATE (a_this)->next_byte_index];
|
|
+
|
|
+ if (PRIVATE (a_this)->nb_bytes -
|
|
+ PRIVATE (a_this)->next_byte_index < 2) {
|
|
+ PRIVATE (a_this)->end_of_input = TRUE;
|
|
+ } else {
|
|
+ PRIVATE (a_this)->next_byte_index++;
|
|
+ }
|
|
+
|
|
+ return CR_OK;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_input_read_char:
|
|
+ *@a_this: the current instance of CRInput.
|
|
+ *@a_char: out parameter. The read character.
|
|
+ *
|
|
+ *Reads an unicode character from the current instance of
|
|
+ *#CRInput.
|
|
+ *
|
|
+ *Returns CR_OK upon successful completion, an error code
|
|
+ *otherwise.
|
|
+ */
|
|
+enum CRStatus
|
|
+cr_input_read_char (CRInput * a_this, guint32 * a_char)
|
|
+{
|
|
+ enum CRStatus status = CR_OK;
|
|
+ gulong consumed = 0,
|
|
+ nb_bytes_left = 0;
|
|
+
|
|
+ g_return_val_if_fail (a_this && PRIVATE (a_this) && a_char,
|
|
+ CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ if (PRIVATE (a_this)->end_of_input == TRUE)
|
|
+ return CR_END_OF_INPUT_ERROR;
|
|
+
|
|
+ nb_bytes_left = cr_input_get_nb_bytes_left (a_this);
|
|
+
|
|
+ if (nb_bytes_left < 1) {
|
|
+ return CR_END_OF_INPUT_ERROR;
|
|
+ }
|
|
+
|
|
+ status = cr_utils_read_char_from_utf8_buf
|
|
+ (PRIVATE (a_this)->in_buf
|
|
+ +
|
|
+ PRIVATE (a_this)->next_byte_index,
|
|
+ nb_bytes_left, a_char, &consumed);
|
|
+
|
|
+ if (status == CR_OK) {
|
|
+ /*update next byte index */
|
|
+ PRIVATE (a_this)->next_byte_index += consumed;
|
|
+
|
|
+ /*update line and column number */
|
|
+ if (PRIVATE (a_this)->end_of_line == TRUE) {
|
|
+ PRIVATE (a_this)->col = 1;
|
|
+ PRIVATE (a_this)->line++;
|
|
+ PRIVATE (a_this)->end_of_line = FALSE;
|
|
+ } else if (*a_char != '\n') {
|
|
+ PRIVATE (a_this)->col++;
|
|
+ }
|
|
+
|
|
+ if (*a_char == '\n') {
|
|
+ PRIVATE (a_this)->end_of_line = TRUE;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return status;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_input_set_line_num:
|
|
+ *@a_this: the "this pointer" of the current instance of #CRInput.
|
|
+ *@a_line_num: the new line number.
|
|
+ *
|
|
+ *Setter of the current line number.
|
|
+ *
|
|
+ *Return CR_OK upon successful completion, an error code otherwise.
|
|
+ */
|
|
+enum CRStatus
|
|
+cr_input_set_line_num (CRInput * a_this, glong a_line_num)
|
|
+{
|
|
+ g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ PRIVATE (a_this)->line = a_line_num;
|
|
+
|
|
+ return CR_OK;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_input_get_line_num:
|
|
+ *@a_this: the "this pointer" of the current instance of #CRInput.
|
|
+ *@a_line_num: the returned line number.
|
|
+ *
|
|
+ *Getter of the current line number.
|
|
+ *
|
|
+ *Returns CR_OK upon successful completion, an error code otherwise.
|
|
+ */
|
|
+enum CRStatus
|
|
+cr_input_get_line_num (CRInput const * a_this, glong * a_line_num)
|
|
+{
|
|
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
|
|
+ && a_line_num, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ *a_line_num = PRIVATE (a_this)->line;
|
|
+
|
|
+ return CR_OK;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_input_set_column_num:
|
|
+ *@a_this: the "this pointer" of the current instance of #CRInput.
|
|
+ *@a_col: the new column number.
|
|
+ *
|
|
+ *Setter of the current column number.
|
|
+ *
|
|
+ *Returns CR_OK upon successful completion, an error code otherwise.
|
|
+ */
|
|
+enum CRStatus
|
|
+cr_input_set_column_num (CRInput * a_this, glong a_col)
|
|
+{
|
|
+ g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ PRIVATE (a_this)->col = a_col;
|
|
+
|
|
+ return CR_OK;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_input_get_column_num:
|
|
+ *@a_this: the "this pointer" of the current instance of #CRInput.
|
|
+ *@a_col: out parameter
|
|
+ *
|
|
+ *Getter of the current column number.
|
|
+ *
|
|
+ *Returns CR_OK upon successful completion, an error code otherwise.
|
|
+ */
|
|
+enum CRStatus
|
|
+cr_input_get_column_num (CRInput const * a_this, glong * a_col)
|
|
+{
|
|
+ g_return_val_if_fail (a_this && PRIVATE (a_this) && a_col,
|
|
+ CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ *a_col = PRIVATE (a_this)->col;
|
|
+
|
|
+ return CR_OK;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_input_increment_line_num:
|
|
+ *@a_this: the "this pointer" of the current instance of #CRInput.
|
|
+ *@a_increment: the increment to add to the line number.
|
|
+ *
|
|
+ *Increments the current line number.
|
|
+ *
|
|
+ *Returns CR_OK upon successful completion, an error code otherwise.
|
|
+ */
|
|
+enum CRStatus
|
|
+cr_input_increment_line_num (CRInput * a_this, glong a_increment)
|
|
+{
|
|
+ g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ PRIVATE (a_this)->line += a_increment;
|
|
+
|
|
+ return CR_OK;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_input_increment_col_num:
|
|
+ *@a_this: the "this pointer" of the current instance of #CRInput.
|
|
+ *@a_increment: the increment to add to the column number.
|
|
+ *
|
|
+ *Increments the current column number.
|
|
+ *
|
|
+ *Returns CR_OK upon successful completion, an error code otherwise.
|
|
+ */
|
|
+enum CRStatus
|
|
+cr_input_increment_col_num (CRInput * a_this, glong a_increment)
|
|
+{
|
|
+ g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ PRIVATE (a_this)->col += a_increment;
|
|
+
|
|
+ return CR_OK;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_input_consume_char:
|
|
+ *@a_this: the this pointer.
|
|
+ *@a_char: the character to consume. If set to zero,
|
|
+ *consumes any character.
|
|
+ *
|
|
+ *Consumes the next character of the input stream if
|
|
+ *and only if that character equals a_char.
|
|
+ *
|
|
+ *Returns CR_OK upon successful completion, CR_PARSING_ERROR if
|
|
+ *next char is different from a_char, an other error code otherwise
|
|
+ */
|
|
+enum CRStatus
|
|
+cr_input_consume_char (CRInput * a_this, guint32 a_char)
|
|
+{
|
|
+ guint32 c;
|
|
+ enum CRStatus status;
|
|
+
|
|
+ g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ if ((status = cr_input_peek_char (a_this, &c)) != CR_OK) {
|
|
+ return status;
|
|
+ }
|
|
+
|
|
+ if (c == a_char || a_char == 0) {
|
|
+ status = cr_input_read_char (a_this, &c);
|
|
+ } else {
|
|
+ return CR_PARSING_ERROR;
|
|
+ }
|
|
+
|
|
+ return status;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_input_consume_chars:
|
|
+ *@a_this: the this pointer of the current instance of #CRInput.
|
|
+ *@a_char: the character to consume.
|
|
+ *@a_nb_char: in/out parameter. The number of characters to consume.
|
|
+ *If set to a negative value, the function will consume all the occurences
|
|
+ *of a_char found.
|
|
+ *After return, if the return value equals CR_OK, this variable contains
|
|
+ *the number of characters actually consumed.
|
|
+ *
|
|
+ *Consumes up to a_nb_char occurences of the next contiguous characters
|
|
+ *which equal a_char. Note that the next character of the input stream
|
|
+ **MUST* equal a_char to trigger the consumption, or else, the error
|
|
+ *code CR_PARSING_ERROR is returned.
|
|
+ *If the number of contiguous characters that equals a_char is less than
|
|
+ *a_nb_char, then this function consumes all the characters it can consume.
|
|
+ *
|
|
+ *Returns CR_OK if at least one character has been consumed, an error code
|
|
+ *otherwise.
|
|
+ */
|
|
+enum CRStatus
|
|
+cr_input_consume_chars (CRInput * a_this, guint32 a_char, gulong * a_nb_char)
|
|
+{
|
|
+ enum CRStatus status = CR_OK;
|
|
+ gulong nb_consumed = 0;
|
|
+
|
|
+ g_return_val_if_fail (a_this && PRIVATE (a_this) && a_nb_char,
|
|
+ CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ g_return_val_if_fail (a_char != 0 || a_nb_char != NULL,
|
|
+ CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ for (nb_consumed = 0; ((status == CR_OK)
|
|
+ && (*a_nb_char > 0
|
|
+ && nb_consumed < *a_nb_char));
|
|
+ nb_consumed++) {
|
|
+ status = cr_input_consume_char (a_this, a_char);
|
|
+ }
|
|
+
|
|
+ *a_nb_char = nb_consumed;
|
|
+
|
|
+ if ((nb_consumed > 0)
|
|
+ && ((status == CR_PARSING_ERROR)
|
|
+ || (status == CR_END_OF_INPUT_ERROR))) {
|
|
+ status = CR_OK;
|
|
+ }
|
|
+
|
|
+ return status;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_input_consume_white_spaces:
|
|
+ *@a_this: the "this pointer" of the current instance of #CRInput.
|
|
+ *@a_nb_chars: in/out parameter. The number of white spaces to
|
|
+ *consume. After return, holds the number of white spaces actually consumed.
|
|
+ *
|
|
+ *Same as cr_input_consume_chars() but this one consumes white
|
|
+ *spaces.
|
|
+ *
|
|
+ *Returns CR_OK upon successful completion, an error code otherwise.
|
|
+ */
|
|
+enum CRStatus
|
|
+cr_input_consume_white_spaces (CRInput * a_this, gulong * a_nb_chars)
|
|
+{
|
|
+ enum CRStatus status = CR_OK;
|
|
+ guint32 cur_char = 0,
|
|
+ nb_consumed = 0;
|
|
+
|
|
+ g_return_val_if_fail (a_this && PRIVATE (a_this) && a_nb_chars,
|
|
+ CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ for (nb_consumed = 0;
|
|
+ ((*a_nb_chars > 0) && (nb_consumed < *a_nb_chars));
|
|
+ nb_consumed++) {
|
|
+ status = cr_input_peek_char (a_this, &cur_char);
|
|
+ if (status != CR_OK)
|
|
+ break;
|
|
+
|
|
+ /*if the next char is a white space, consume it ! */
|
|
+ if (cr_utils_is_white_space (cur_char) == TRUE) {
|
|
+ status = cr_input_read_char (a_this, &cur_char);
|
|
+ if (status != CR_OK)
|
|
+ break;
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ break;
|
|
+
|
|
+ }
|
|
+
|
|
+ *a_nb_chars = (gulong) nb_consumed;
|
|
+
|
|
+ if (nb_consumed && status == CR_END_OF_INPUT_ERROR) {
|
|
+ status = CR_OK;
|
|
+ }
|
|
+
|
|
+ return status;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_input_peek_char:
|
|
+ *@a_this: the current instance of #CRInput.
|
|
+ *@a_char: out parameter. The returned character.
|
|
+ *
|
|
+ *Same as cr_input_read_char() but does not update the
|
|
+ *internal state of the input stream. The next call
|
|
+ *to cr_input_peek_char() or cr_input_read_char() will thus
|
|
+ *return the same character as the current one.
|
|
+ *
|
|
+ *Returns CR_OK upon successful completion, an error code
|
|
+ *otherwise.
|
|
+ */
|
|
+enum CRStatus
|
|
+cr_input_peek_char (CRInput const * a_this, guint32 * a_char)
|
|
+{
|
|
+ enum CRStatus status = CR_OK;
|
|
+ gulong consumed = 0,
|
|
+ nb_bytes_left = 0;
|
|
+
|
|
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
|
|
+ && a_char, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ if (PRIVATE (a_this)->next_byte_index >=
|
|
+ PRIVATE (a_this)->in_buf_size) {
|
|
+ return CR_END_OF_INPUT_ERROR;
|
|
+ }
|
|
+
|
|
+ nb_bytes_left = cr_input_get_nb_bytes_left (a_this);
|
|
+
|
|
+ if (nb_bytes_left < 1) {
|
|
+ return CR_END_OF_INPUT_ERROR;
|
|
+ }
|
|
+
|
|
+ status = cr_utils_read_char_from_utf8_buf
|
|
+ (PRIVATE (a_this)->in_buf +
|
|
+ PRIVATE (a_this)->next_byte_index,
|
|
+ nb_bytes_left, a_char, &consumed);
|
|
+
|
|
+ return status;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_input_peek_byte:
|
|
+ *@a_this: the current instance of #CRInput.
|
|
+ *@a_origin: the origin to consider in the calculation
|
|
+ *of the position of the byte to peek.
|
|
+ *@a_offset: the offset of the byte to peek, starting from
|
|
+ *the origin specified by a_origin.
|
|
+ *@a_byte: out parameter the peeked byte.
|
|
+ *
|
|
+ *Gets a byte from the input stream,
|
|
+ *starting from the current position in the input stream.
|
|
+ *Unlike cr_input_peek_next_byte() this method
|
|
+ *does not update the state of the current input stream.
|
|
+ *Subsequent calls to cr_input_peek_byte with the same arguments
|
|
+ *will return the same byte.
|
|
+ *
|
|
+ *Returns CR_OK upon successful completion or,
|
|
+ *CR_BAD_PARAM_ERROR if at least one of the parameters is invalid;
|
|
+ *CR_OUT_OF_BOUNDS_ERROR if the indexed byte is out of bounds.
|
|
+ */
|
|
+enum CRStatus
|
|
+cr_input_peek_byte (CRInput const * a_this, enum CRSeekPos a_origin,
|
|
+ gulong a_offset, guchar * a_byte)
|
|
+{
|
|
+ gulong abs_offset = 0;
|
|
+
|
|
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
|
|
+ && a_byte, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ switch (a_origin) {
|
|
+
|
|
+ case CR_SEEK_CUR:
|
|
+ abs_offset = PRIVATE (a_this)->next_byte_index - 1 + a_offset;
|
|
+ break;
|
|
+
|
|
+ case CR_SEEK_BEGIN:
|
|
+ abs_offset = a_offset;
|
|
+ break;
|
|
+
|
|
+ case CR_SEEK_END:
|
|
+ abs_offset = PRIVATE (a_this)->in_buf_size - 1 - a_offset;
|
|
+ break;
|
|
+
|
|
+ default:
|
|
+ return CR_BAD_PARAM_ERROR;
|
|
+ }
|
|
+
|
|
+ if (abs_offset < PRIVATE (a_this)->in_buf_size) {
|
|
+
|
|
+ *a_byte = PRIVATE (a_this)->in_buf[abs_offset];
|
|
+
|
|
+ return CR_OK;
|
|
+
|
|
+ } else {
|
|
+ return CR_END_OF_INPUT_ERROR;
|
|
+ }
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_input_peek_byte2:
|
|
+ *@a_this: the current byte input stream.
|
|
+ *@a_offset: the offset of the byte to peek, starting
|
|
+ *from the current input position pointer.
|
|
+ *@a_eof: out parameter. Is set to true is we reach end of
|
|
+ *stream. If set to NULL by the caller, this parameter is not taken
|
|
+ *in account.
|
|
+ *
|
|
+ *Same as cr_input_peek_byte() but with a simplified
|
|
+ *interface.
|
|
+ *
|
|
+ *Returns the read byte or 0 if something bad happened.
|
|
+ */
|
|
+guchar
|
|
+cr_input_peek_byte2 (CRInput const * a_this, gulong a_offset, gboolean * a_eof)
|
|
+{
|
|
+ guchar result = 0;
|
|
+ enum CRStatus status = CR_ERROR;
|
|
+
|
|
+ g_return_val_if_fail (a_this && PRIVATE (a_this), 0);
|
|
+
|
|
+ if (a_eof)
|
|
+ *a_eof = FALSE;
|
|
+
|
|
+ status = cr_input_peek_byte (a_this, CR_SEEK_CUR, a_offset, &result);
|
|
+
|
|
+ if ((status == CR_END_OF_INPUT_ERROR)
|
|
+ && a_eof)
|
|
+ *a_eof = TRUE;
|
|
+
|
|
+ return result;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_input_get_byte_addr:
|
|
+ *@a_this: the current instance of #CRInput.
|
|
+ *@a_offset: the offset of the byte in the input stream starting
|
|
+ *from the beginning of the stream.
|
|
+ *
|
|
+ *Gets the memory address of the byte located at a given offset
|
|
+ *in the input stream.
|
|
+ *
|
|
+ *Returns the address, otherwise NULL if an error occurred.
|
|
+ */
|
|
+guchar *
|
|
+cr_input_get_byte_addr (CRInput * a_this, gulong a_offset)
|
|
+{
|
|
+ g_return_val_if_fail (a_this && PRIVATE (a_this), NULL);
|
|
+
|
|
+ if (a_offset >= PRIVATE (a_this)->nb_bytes) {
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
+ return &PRIVATE (a_this)->in_buf[a_offset];
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_input_get_cur_byte_addr:
|
|
+ *@a_this: the current input stream
|
|
+ *@a_offset: out parameter. The returned address.
|
|
+ *
|
|
+ *Gets the address of the current character pointer.
|
|
+ *
|
|
+ *Returns CR_OK upon successful completion, an error code otherwise.
|
|
+ */
|
|
+enum CRStatus
|
|
+cr_input_get_cur_byte_addr (CRInput * a_this, guchar ** a_offset)
|
|
+{
|
|
+ g_return_val_if_fail (a_this && PRIVATE (a_this) && a_offset,
|
|
+ CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ if (!PRIVATE (a_this)->next_byte_index) {
|
|
+ return CR_START_OF_INPUT_ERROR;
|
|
+ }
|
|
+
|
|
+ *a_offset = cr_input_get_byte_addr
|
|
+ (a_this, PRIVATE (a_this)->next_byte_index - 1);
|
|
+
|
|
+ return CR_OK;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_input_seek_index:
|
|
+ *@a_this: the current instance of #CRInput.
|
|
+ *@a_origin: the origin to consider during the calculation
|
|
+ *of the absolute position of the new "current byte index".
|
|
+ *@a_pos: the relative offset of the new "current byte index."
|
|
+ *This offset is relative to the origin a_origin.
|
|
+ *
|
|
+ *Sets the "current byte index" of the current instance
|
|
+ *of #CRInput. Next call to cr_input_get_byte() will return
|
|
+ *the byte next after the new "current byte index".
|
|
+ *
|
|
+ *Returns CR_OK upon successful completion otherwise returns
|
|
+ *CR_BAD_PARAM_ERROR if at least one of the parameters is not valid
|
|
+ *or CR_OUT_BOUNDS_ERROR in case of error.
|
|
+ */
|
|
+enum CRStatus
|
|
+cr_input_seek_index (CRInput * a_this, enum CRSeekPos a_origin, gint a_pos)
|
|
+{
|
|
+
|
|
+ glong abs_offset = 0;
|
|
+
|
|
+ g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ switch (a_origin) {
|
|
+
|
|
+ case CR_SEEK_CUR:
|
|
+ abs_offset = PRIVATE (a_this)->next_byte_index - 1 + a_pos;
|
|
+ break;
|
|
+
|
|
+ case CR_SEEK_BEGIN:
|
|
+ abs_offset = a_pos;
|
|
+ break;
|
|
+
|
|
+ case CR_SEEK_END:
|
|
+ abs_offset = PRIVATE (a_this)->in_buf_size - 1 - a_pos;
|
|
+ break;
|
|
+
|
|
+ default:
|
|
+ return CR_BAD_PARAM_ERROR;
|
|
+ }
|
|
+
|
|
+ if ((abs_offset > 0)
|
|
+ && (gulong) abs_offset < PRIVATE (a_this)->nb_bytes) {
|
|
+
|
|
+ /*update the input stream's internal state */
|
|
+ PRIVATE (a_this)->next_byte_index = abs_offset + 1;
|
|
+
|
|
+ return CR_OK;
|
|
+ }
|
|
+
|
|
+ return CR_OUT_OF_BOUNDS_ERROR;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_input_get_cur_pos:
|
|
+ *@a_this: the current instance of #CRInput.
|
|
+ *@a_pos: out parameter. The returned position.
|
|
+ *
|
|
+ *Gets the position of the "current byte index" which
|
|
+ *is basically the position of the last returned byte in the
|
|
+ *input stream.
|
|
+ *
|
|
+ *Returns CR_OK upon successful completion. Otherwise,
|
|
+ *CR_BAD_PARAMETER_ERROR if at least one of the arguments is invalid.
|
|
+ *CR_START_OF_INPUT if no call to either cr_input_read_byte()
|
|
+ *or cr_input_seek_index() have been issued before calling
|
|
+ *cr_input_get_cur_pos()
|
|
+ *Note that the out parameters of this function are valid if and only if this
|
|
+ *function returns CR_OK.
|
|
+ */
|
|
+enum CRStatus
|
|
+cr_input_get_cur_pos (CRInput const * a_this, CRInputPos * a_pos)
|
|
+{
|
|
+ g_return_val_if_fail (a_this && PRIVATE (a_this) && a_pos,
|
|
+ CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ a_pos->next_byte_index = PRIVATE (a_this)->next_byte_index;
|
|
+ a_pos->line = PRIVATE (a_this)->line;
|
|
+ a_pos->col = PRIVATE (a_this)->col;
|
|
+ a_pos->end_of_line = PRIVATE (a_this)->end_of_line;
|
|
+ a_pos->end_of_file = PRIVATE (a_this)->end_of_input;
|
|
+
|
|
+ return CR_OK;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_input_get_parsing_location:
|
|
+ *@a_this: the current instance of #CRInput
|
|
+ *@a_loc: the set parsing location.
|
|
+ *
|
|
+ *Gets the current parsing location.
|
|
+ *The Parsing location is a public datastructure that
|
|
+ *represents the current line/column/byte offset/ in the input
|
|
+ *stream.
|
|
+ *
|
|
+ *Returns CR_OK upon successful completion, an error
|
|
+ *code otherwise.
|
|
+ */
|
|
+enum CRStatus
|
|
+cr_input_get_parsing_location (CRInput const *a_this,
|
|
+ CRParsingLocation *a_loc)
|
|
+{
|
|
+ g_return_val_if_fail (a_this
|
|
+ && PRIVATE (a_this)
|
|
+ && a_loc,
|
|
+ CR_BAD_PARAM_ERROR) ;
|
|
+
|
|
+ a_loc->line = PRIVATE (a_this)->line ;
|
|
+ a_loc->column = PRIVATE (a_this)->col ;
|
|
+ if (PRIVATE (a_this)->next_byte_index) {
|
|
+ a_loc->byte_offset = PRIVATE (a_this)->next_byte_index - 1 ;
|
|
+ } else {
|
|
+ a_loc->byte_offset = PRIVATE (a_this)->next_byte_index ;
|
|
+ }
|
|
+ return CR_OK ;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_input_get_cur_index:
|
|
+ *@a_this: the "this pointer" of the current instance of
|
|
+ *#CRInput
|
|
+ *@a_index: out parameter. The returned index.
|
|
+ *
|
|
+ *Getter of the next byte index.
|
|
+ *It actually returns the index of the
|
|
+ *next byte to be read.
|
|
+ *
|
|
+ *Returns CR_OK upon successful completion, an error code
|
|
+ *otherwise.
|
|
+ */
|
|
+enum CRStatus
|
|
+cr_input_get_cur_index (CRInput const * a_this, glong * a_index)
|
|
+{
|
|
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
|
|
+ && a_index, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ *a_index = PRIVATE (a_this)->next_byte_index;
|
|
+
|
|
+ return CR_OK;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_input_set_cur_index:
|
|
+ *@a_this: the "this pointer" of the current instance
|
|
+ *of #CRInput .
|
|
+ *@a_index: the new index to set.
|
|
+ *
|
|
+ *Setter of the next byte index.
|
|
+ *It sets the index of the next byte to be read.
|
|
+ *
|
|
+ *Returns CR_OK upon successful completion, an error code otherwise.
|
|
+ */
|
|
+enum CRStatus
|
|
+cr_input_set_cur_index (CRInput * a_this, glong a_index)
|
|
+{
|
|
+ g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ PRIVATE (a_this)->next_byte_index = a_index;
|
|
+
|
|
+ return CR_OK;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_input_set_end_of_file:
|
|
+ *@a_this: the current instance of #CRInput.
|
|
+ *@a_eof: the new end of file flag.
|
|
+ *
|
|
+ *Sets the end of file flag.
|
|
+ *
|
|
+ *Returns CR_OK upon successful completion, an error code otherwise.
|
|
+ */
|
|
+enum CRStatus
|
|
+cr_input_set_end_of_file (CRInput * a_this, gboolean a_eof)
|
|
+{
|
|
+ g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ PRIVATE (a_this)->end_of_input = a_eof;
|
|
+
|
|
+ return CR_OK;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_input_get_end_of_file:
|
|
+ *@a_this: the current instance of #CRInput.
|
|
+ *@a_eof: out parameter the place to put the end of
|
|
+ *file flag.
|
|
+ *
|
|
+ *Gets the end of file flag.
|
|
+ *
|
|
+ *Returns CR_OK upon successful completion, an error code otherwise.
|
|
+ */
|
|
+enum CRStatus
|
|
+cr_input_get_end_of_file (CRInput const * a_this, gboolean * a_eof)
|
|
+{
|
|
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
|
|
+ && a_eof, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ *a_eof = PRIVATE (a_this)->end_of_input;
|
|
+
|
|
+ return CR_OK;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_input_set_end_of_line:
|
|
+ *@a_this: the current instance of #CRInput.
|
|
+ *@a_eol: the new end of line flag.
|
|
+ *
|
|
+ *Sets the end of line flag.
|
|
+ *
|
|
+ *Returns CR_OK upon successful completion, an error code
|
|
+ *otherwise.
|
|
+ */
|
|
+enum CRStatus
|
|
+cr_input_set_end_of_line (CRInput * a_this, gboolean a_eol)
|
|
+{
|
|
+ g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ PRIVATE (a_this)->end_of_line = a_eol;
|
|
+
|
|
+ return CR_OK;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_input_get_end_of_line:
|
|
+ *@a_this: the current instance of #CRInput
|
|
+ *@a_eol: out parameter. The place to put
|
|
+ *the returned flag
|
|
+ *
|
|
+ *Gets the end of line flag of the current input.
|
|
+ *
|
|
+ *Returns CR_OK upon successful completion, an error code
|
|
+ *otherwise.
|
|
+ */
|
|
+enum CRStatus
|
|
+cr_input_get_end_of_line (CRInput const * a_this, gboolean * a_eol)
|
|
+{
|
|
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
|
|
+ && a_eol, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ *a_eol = PRIVATE (a_this)->end_of_line;
|
|
+
|
|
+ return CR_OK;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_input_set_cur_pos:
|
|
+ *@a_this: the "this pointer" of the current instance of
|
|
+ *#CRInput.
|
|
+ *@a_pos: the new position.
|
|
+ *
|
|
+ *Sets the current position in the input stream.
|
|
+ *
|
|
+ * Returns CR_OK upon successful completion, an error code otherwise.
|
|
+ */
|
|
+enum CRStatus
|
|
+cr_input_set_cur_pos (CRInput * a_this, CRInputPos const * a_pos)
|
|
+{
|
|
+ g_return_val_if_fail (a_this && PRIVATE (a_this) && a_pos,
|
|
+ CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ cr_input_set_column_num (a_this, a_pos->col);
|
|
+ cr_input_set_line_num (a_this, a_pos->line);
|
|
+ cr_input_set_cur_index (a_this, a_pos->next_byte_index);
|
|
+ cr_input_set_end_of_line (a_this, a_pos->end_of_line);
|
|
+ cr_input_set_end_of_file (a_this, a_pos->end_of_file);
|
|
+
|
|
+ return CR_OK;
|
|
+}
|
|
diff --git a/src/st/croco/cr-input.h b/src/st/croco/cr-input.h
|
|
new file mode 100644
|
|
index 000000000..9eb402a87
|
|
--- /dev/null
|
|
+++ b/src/st/croco/cr-input.h
|
|
@@ -0,0 +1,174 @@
|
|
+/* -*- 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 the COPYRIGHTS file for copyrights information.
|
|
+ */
|
|
+
|
|
+#ifndef __CR_INPUT_SRC_H__
|
|
+#define __CR_INPUT_SRC_H__
|
|
+
|
|
+
|
|
+#include <glib.h>
|
|
+#include "cr-utils.h"
|
|
+#include "cr-parsing-location.h"
|
|
+
|
|
+G_BEGIN_DECLS
|
|
+
|
|
+/**
|
|
+ *@file
|
|
+ *The libcroco basic input stream class
|
|
+ *declaration file.
|
|
+ */
|
|
+
|
|
+typedef struct _CRInput CRInput ;
|
|
+typedef struct _CRInputPriv CRInputPriv ;
|
|
+
|
|
+/**
|
|
+ *The #CRInput class provides the abstraction of
|
|
+ *an utf8-encoded character stream.
|
|
+ */
|
|
+struct _CRInput
|
|
+{
|
|
+ CRInputPriv *priv ;
|
|
+} ;
|
|
+
|
|
+typedef struct _CRInputPos CRInputPos ;
|
|
+
|
|
+struct _CRInputPos
|
|
+{
|
|
+ glong line ;
|
|
+ glong col ;
|
|
+ gboolean end_of_file ;
|
|
+ gboolean end_of_line ;
|
|
+ glong next_byte_index ;
|
|
+} ;
|
|
+
|
|
+CRInput *
|
|
+cr_input_new_from_buf (guchar *a_buf, gulong a_len,
|
|
+ enum CREncoding a_enc, gboolean a_free_buf) ;
|
|
+CRInput *
|
|
+cr_input_new_from_uri (const gchar *a_file_uri,
|
|
+ enum CREncoding a_enc) ;
|
|
+
|
|
+void
|
|
+cr_input_destroy (CRInput *a_this) ;
|
|
+
|
|
+void
|
|
+cr_input_ref (CRInput *a_this) ;
|
|
+
|
|
+gboolean
|
|
+cr_input_unref (CRInput *a_this) ;
|
|
+
|
|
+enum CRStatus
|
|
+cr_input_read_byte (CRInput *a_this, guchar *a_byte) ;
|
|
+
|
|
+enum CRStatus
|
|
+cr_input_read_char (CRInput *a_this, guint32 *a_char) ;
|
|
+
|
|
+enum CRStatus
|
|
+cr_input_consume_chars (CRInput *a_this, guint32 a_char,
|
|
+ gulong *a_nb_char) ;
|
|
+
|
|
+enum CRStatus
|
|
+cr_input_consume_char (CRInput *a_this, guint32 a_char) ;
|
|
+
|
|
+enum CRStatus
|
|
+cr_input_consume_white_spaces (CRInput *a_this, gulong *a_nb_chars) ;
|
|
+
|
|
+enum CRStatus
|
|
+cr_input_peek_byte (CRInput const *a_this, enum CRSeekPos a_origin,
|
|
+ gulong a_offset, guchar *a_byte) ;
|
|
+
|
|
+guchar
|
|
+cr_input_peek_byte2 (CRInput const *a_this, gulong a_offset,
|
|
+ gboolean *a_eof) ;
|
|
+
|
|
+enum CRStatus
|
|
+cr_input_peek_char (CRInput const *a_this, guint32 *a_char) ;
|
|
+
|
|
+guchar *
|
|
+cr_input_get_byte_addr (CRInput *a_this,
|
|
+ gulong a_offset) ;
|
|
+
|
|
+enum CRStatus
|
|
+cr_input_get_cur_byte_addr (CRInput *a_this, guchar ** a_offset) ;
|
|
+
|
|
+enum CRStatus
|
|
+cr_input_seek_index (CRInput *a_this,
|
|
+ enum CRSeekPos a_origin, gint a_pos) ;
|
|
+
|
|
+enum CRStatus
|
|
+cr_input_get_cur_index (CRInput const *a_this, glong *a_index) ;
|
|
+
|
|
+enum CRStatus
|
|
+cr_input_set_cur_index (CRInput *a_this, glong a_index) ;
|
|
+
|
|
+enum CRStatus
|
|
+cr_input_get_cur_pos (CRInput const *a_this, CRInputPos * a_pos) ;
|
|
+
|
|
+enum CRStatus
|
|
+cr_input_set_cur_pos (CRInput *a_this, CRInputPos const *a_pos) ;
|
|
+
|
|
+enum CRStatus
|
|
+cr_input_get_parsing_location (CRInput const *a_this,
|
|
+ CRParsingLocation *a_loc) ;
|
|
+
|
|
+enum CRStatus
|
|
+cr_input_get_end_of_line (CRInput const *a_this, gboolean *a_eol) ;
|
|
+
|
|
+enum CRStatus
|
|
+cr_input_set_end_of_line (CRInput *a_this, gboolean a_eol) ;
|
|
+
|
|
+enum CRStatus
|
|
+cr_input_get_end_of_file (CRInput const *a_this, gboolean *a_eof) ;
|
|
+
|
|
+enum CRStatus
|
|
+cr_input_set_end_of_file (CRInput *a_this, gboolean a_eof) ;
|
|
+
|
|
+enum CRStatus
|
|
+cr_input_set_line_num (CRInput *a_this, glong a_line_num) ;
|
|
+
|
|
+enum CRStatus
|
|
+cr_input_get_line_num (CRInput const *a_this, glong *a_line_num) ;
|
|
+
|
|
+enum CRStatus
|
|
+cr_input_set_column_num (CRInput *a_this, glong a_col) ;
|
|
+
|
|
+enum CRStatus
|
|
+cr_input_get_column_num (CRInput const *a_this, glong *a_col) ;
|
|
+
|
|
+enum CRStatus
|
|
+cr_input_increment_line_num (CRInput *a_this,
|
|
+ glong a_increment) ;
|
|
+
|
|
+enum CRStatus
|
|
+cr_input_increment_col_num (CRInput *a_this,
|
|
+ glong a_increment) ;
|
|
+
|
|
+glong
|
|
+cr_input_get_nb_bytes_left (CRInput const *a_this) ;
|
|
+
|
|
+enum CRStatus
|
|
+cr_input_end_of_input (CRInput const *a_this, gboolean *a_end_of_input) ;
|
|
+
|
|
+G_END_DECLS
|
|
+
|
|
+#endif /*__CR_INPUT_SRC_H__*/
|
|
+
|
|
diff --git a/src/st/croco/cr-num.c b/src/st/croco/cr-num.c
|
|
new file mode 100644
|
|
index 000000000..d5dbd5fb0
|
|
--- /dev/null
|
|
+++ b/src/st/croco/cr-num.c
|
|
@@ -0,0 +1,313 @@
|
|
+/* -*- 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 copyrights information.
|
|
+ */
|
|
+
|
|
+/**
|
|
+ *@CRNum:
|
|
+ *
|
|
+ *The definition
|
|
+ *of the #CRNum class.
|
|
+ */
|
|
+
|
|
+#include "cr-num.h"
|
|
+#include "string.h"
|
|
+
|
|
+/**
|
|
+ * cr_num_new:
|
|
+ *
|
|
+ *#CRNum.
|
|
+ *
|
|
+ *Returns the newly built instance of
|
|
+ *#CRNum.
|
|
+ */
|
|
+CRNum *
|
|
+cr_num_new (void)
|
|
+{
|
|
+ CRNum *result = NULL;
|
|
+
|
|
+ result = g_try_malloc (sizeof (CRNum));
|
|
+
|
|
+ if (result == NULL) {
|
|
+ cr_utils_trace_info ("Out of memory");
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
+ memset (result, 0, sizeof (CRNum));
|
|
+
|
|
+ return result;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_num_new_with_val:
|
|
+ * @a_val: the numerical value of the number.
|
|
+ * @a_type: the type of number.
|
|
+ *
|
|
+ * A constructor of #CRNum.
|
|
+ *
|
|
+ * Returns the newly built instance of #CRNum or
|
|
+ * NULL if an error arises.
|
|
+ */
|
|
+CRNum *
|
|
+cr_num_new_with_val (gdouble a_val, enum CRNumType a_type)
|
|
+{
|
|
+ CRNum *result = NULL;
|
|
+
|
|
+ result = cr_num_new ();
|
|
+
|
|
+ g_return_val_if_fail (result, NULL);
|
|
+
|
|
+ result->val = a_val;
|
|
+ result->type = a_type;
|
|
+
|
|
+ return result;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_num_to_string:
|
|
+ *@a_this: the current instance of #CRNum.
|
|
+ *
|
|
+ *Returns the newly built string representation
|
|
+ *of the current instance of #CRNum. The returned
|
|
+ *string is NULL terminated. The caller *must*
|
|
+ *free the returned string.
|
|
+ */
|
|
+guchar *
|
|
+cr_num_to_string (CRNum const * a_this)
|
|
+{
|
|
+ gdouble test_val = 0.0;
|
|
+
|
|
+ guchar *tmp_char1 = NULL,
|
|
+ *tmp_char2 = NULL,
|
|
+ *result = NULL;
|
|
+
|
|
+ g_return_val_if_fail (a_this, NULL);
|
|
+
|
|
+ test_val = a_this->val - (glong) a_this->val;
|
|
+
|
|
+ if (!test_val) {
|
|
+ tmp_char1 = (guchar *) g_strdup_printf ("%ld", (glong) a_this->val);
|
|
+ } else {
|
|
+ tmp_char1 = (guchar *) g_new0 (char, G_ASCII_DTOSTR_BUF_SIZE + 1);
|
|
+ if (tmp_char1 != NULL)
|
|
+ g_ascii_dtostr ((gchar *) tmp_char1, G_ASCII_DTOSTR_BUF_SIZE, a_this->val);
|
|
+ }
|
|
+
|
|
+ g_return_val_if_fail (tmp_char1, NULL);
|
|
+
|
|
+ switch (a_this->type) {
|
|
+ case NUM_LENGTH_EM:
|
|
+ tmp_char2 = (guchar *) "em";
|
|
+ break;
|
|
+
|
|
+ case NUM_LENGTH_EX:
|
|
+ tmp_char2 = (guchar *) "ex";
|
|
+ break;
|
|
+
|
|
+ case NUM_LENGTH_PX:
|
|
+ tmp_char2 = (guchar *) "px";
|
|
+ break;
|
|
+
|
|
+ case NUM_LENGTH_IN:
|
|
+ tmp_char2 = (guchar *) "in";
|
|
+ break;
|
|
+
|
|
+ case NUM_LENGTH_CM:
|
|
+ tmp_char2 = (guchar *) "cm";
|
|
+ break;
|
|
+
|
|
+ case NUM_LENGTH_MM:
|
|
+ tmp_char2 = (guchar *) "mm";
|
|
+ break;
|
|
+
|
|
+ case NUM_LENGTH_PT:
|
|
+ tmp_char2 = (guchar *) "pt";
|
|
+ break;
|
|
+
|
|
+ case NUM_LENGTH_PC:
|
|
+ tmp_char2 = (guchar *) "pc";
|
|
+ break;
|
|
+
|
|
+ case NUM_ANGLE_DEG:
|
|
+ tmp_char2 = (guchar *) "deg";
|
|
+ break;
|
|
+
|
|
+ case NUM_ANGLE_RAD:
|
|
+ tmp_char2 = (guchar *) "rad";
|
|
+ break;
|
|
+
|
|
+ case NUM_ANGLE_GRAD:
|
|
+ tmp_char2 = (guchar *) "grad";
|
|
+ break;
|
|
+
|
|
+ case NUM_TIME_MS:
|
|
+ tmp_char2 = (guchar *) "ms";
|
|
+ break;
|
|
+
|
|
+ case NUM_TIME_S:
|
|
+ tmp_char2 = (guchar *) "s";
|
|
+ break;
|
|
+
|
|
+ case NUM_FREQ_HZ:
|
|
+ tmp_char2 = (guchar *) "Hz";
|
|
+ break;
|
|
+
|
|
+ case NUM_FREQ_KHZ:
|
|
+ tmp_char2 = (guchar *) "KHz";
|
|
+ break;
|
|
+
|
|
+ case NUM_PERCENTAGE:
|
|
+ tmp_char2 = (guchar *) "%";
|
|
+ break;
|
|
+ case NUM_INHERIT:
|
|
+ tmp_char2 = (guchar *) "inherit";
|
|
+ break ;
|
|
+ case NUM_AUTO:
|
|
+ tmp_char2 = (guchar *) "auto";
|
|
+ break ;
|
|
+ case NUM_GENERIC:
|
|
+ tmp_char2 = NULL ;
|
|
+ break ;
|
|
+ default:
|
|
+ tmp_char2 = (guchar *) "unknown";
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ if (tmp_char2) {
|
|
+ result = (guchar *) g_strconcat ((gchar *) tmp_char1, tmp_char2, NULL);
|
|
+ g_free (tmp_char1);
|
|
+ } else {
|
|
+ result = tmp_char1;
|
|
+ }
|
|
+
|
|
+ return result;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_num_copy:
|
|
+ *@a_src: the instance of #CRNum to copy.
|
|
+ *Must be non NULL.
|
|
+ *@a_dest: the destination of the copy.
|
|
+ *Must be non NULL
|
|
+ *
|
|
+ *Copies an instance of #CRNum.
|
|
+ *
|
|
+ *Returns CR_OK upon successful completion, an
|
|
+ *error code otherwise.
|
|
+ */
|
|
+enum CRStatus
|
|
+cr_num_copy (CRNum * a_dest, CRNum const * a_src)
|
|
+{
|
|
+ g_return_val_if_fail (a_dest && a_src, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ memcpy (a_dest, a_src, sizeof (CRNum));
|
|
+
|
|
+ return CR_OK;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_num_dup:
|
|
+ *@a_this: the instance of #CRNum to duplicate.
|
|
+ *
|
|
+ *Duplicates an instance of #CRNum
|
|
+ *
|
|
+ *Returns the newly created (duplicated) instance of #CRNum.
|
|
+ *Must be freed by cr_num_destroy().
|
|
+ */
|
|
+CRNum *
|
|
+cr_num_dup (CRNum const * a_this)
|
|
+{
|
|
+ CRNum *result = NULL;
|
|
+ enum CRStatus status = CR_OK;
|
|
+
|
|
+ g_return_val_if_fail (a_this, NULL);
|
|
+
|
|
+ result = cr_num_new ();
|
|
+ g_return_val_if_fail (result, NULL);
|
|
+
|
|
+ status = cr_num_copy (result, a_this);
|
|
+ g_return_val_if_fail (status == CR_OK, NULL);
|
|
+
|
|
+ return result;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_num_set:
|
|
+ *Sets an instance of #CRNum.
|
|
+ *@a_this: the current instance of #CRNum to be set.
|
|
+ *@a_val: the new numerical value to be hold by the current
|
|
+ *instance of #CRNum
|
|
+ *@a_type: the new type of #CRNum.
|
|
+ *
|
|
+ * Returns CR_OK upon succesful completion, an error code otherwise.
|
|
+ */
|
|
+enum CRStatus
|
|
+cr_num_set (CRNum * a_this, gdouble a_val, enum CRNumType a_type)
|
|
+{
|
|
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ a_this->val = a_val;
|
|
+ a_this->type = a_type;
|
|
+
|
|
+ return CR_OK;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_num_is_fixed_length:
|
|
+ * @a_this: the current instance of #CRNum .
|
|
+ *
|
|
+ *Tests if the current instance of #CRNum is a fixed
|
|
+ *length value or not. Typically a fixed length value
|
|
+ *is anything from NUM_LENGTH_EM to NUM_LENGTH_PC.
|
|
+ *See the definition of #CRNumType to see what we mean.
|
|
+ *
|
|
+ *Returns TRUE if the instance of #CRNum is a fixed length number,
|
|
+ *FALSE otherwise.
|
|
+ */
|
|
+gboolean
|
|
+cr_num_is_fixed_length (CRNum const * a_this)
|
|
+{
|
|
+ gboolean result = FALSE;
|
|
+
|
|
+ g_return_val_if_fail (a_this, FALSE);
|
|
+
|
|
+ if (a_this->type >= NUM_LENGTH_EM
|
|
+ && a_this->type <= NUM_LENGTH_PC) {
|
|
+ result = TRUE ;
|
|
+ }
|
|
+ return result ;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_num_destroy:
|
|
+ *@a_this: the this pointer of
|
|
+ *the current instance of #CRNum.
|
|
+ *
|
|
+ *The destructor of #CRNum.
|
|
+ */
|
|
+void
|
|
+cr_num_destroy (CRNum * a_this)
|
|
+{
|
|
+ g_return_if_fail (a_this);
|
|
+
|
|
+ g_free (a_this);
|
|
+}
|
|
diff --git a/src/st/croco/cr-num.h b/src/st/croco/cr-num.h
|
|
new file mode 100644
|
|
index 000000000..2b73aaf79
|
|
--- /dev/null
|
|
+++ b/src/st/croco/cr-num.h
|
|
@@ -0,0 +1,127 @@
|
|
+/* -*- 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
|
|
+ */
|
|
+
|
|
+
|
|
+/**
|
|
+ *@file
|
|
+ *The declaration
|
|
+ *of the #CRNum class.
|
|
+ */
|
|
+
|
|
+#ifndef __CR_NUM_H__
|
|
+#define __CR_NUM_H__
|
|
+
|
|
+#include <glib.h>
|
|
+#include "cr-utils.h"
|
|
+#include "cr-parsing-location.h"
|
|
+
|
|
+G_BEGIN_DECLS
|
|
+
|
|
+/**
|
|
+ *@file
|
|
+ *The declaration of the #CRNum class.
|
|
+ *
|
|
+ */
|
|
+
|
|
+/**
|
|
+ *The different types
|
|
+ *of numbers.
|
|
+ *Please, do not modify
|
|
+ *the declaration order of the enum
|
|
+ *members, unless you know
|
|
+ *what you are doing.
|
|
+ */
|
|
+enum CRNumType
|
|
+{
|
|
+ NUM_AUTO = 0,
|
|
+ NUM_GENERIC,
|
|
+ NUM_LENGTH_EM,
|
|
+ NUM_LENGTH_EX,
|
|
+ NUM_LENGTH_PX,
|
|
+ NUM_LENGTH_IN,
|
|
+ NUM_LENGTH_CM,
|
|
+ NUM_LENGTH_MM,
|
|
+ NUM_LENGTH_PT,
|
|
+ NUM_LENGTH_PC,
|
|
+ NUM_ANGLE_DEG,
|
|
+ NUM_ANGLE_RAD,
|
|
+ NUM_ANGLE_GRAD,
|
|
+ NUM_TIME_MS,
|
|
+ NUM_TIME_S,
|
|
+ NUM_FREQ_HZ,
|
|
+ NUM_FREQ_KHZ,
|
|
+ NUM_PERCENTAGE,
|
|
+ NUM_INHERIT,
|
|
+ NUM_UNKNOWN_TYPE,
|
|
+ NB_NUM_TYPE
|
|
+} ;
|
|
+
|
|
+
|
|
+/**
|
|
+ *An abstraction of a number (num)
|
|
+ *as defined in the css2 spec.
|
|
+ */
|
|
+typedef struct _CRNum CRNum ;
|
|
+
|
|
+/**
|
|
+ *An abstraction of a number (num)
|
|
+ *as defined in the css2 spec.
|
|
+ */
|
|
+struct _CRNum
|
|
+{
|
|
+ enum CRNumType type ;
|
|
+ gdouble val ;
|
|
+ CRParsingLocation location ;
|
|
+} ;
|
|
+
|
|
+CRNum *
|
|
+cr_num_new (void) ;
|
|
+
|
|
+CRNum *
|
|
+cr_num_new_with_val (gdouble a_val,
|
|
+ enum CRNumType a_type) ;
|
|
+
|
|
+CRNum *
|
|
+cr_num_dup (CRNum const *a_this) ;
|
|
+
|
|
+guchar *
|
|
+cr_num_to_string (CRNum const *a_this) ;
|
|
+
|
|
+enum CRStatus
|
|
+cr_num_copy (CRNum *a_dest, CRNum const *a_src) ;
|
|
+
|
|
+enum CRStatus
|
|
+cr_num_set (CRNum *a_this, gdouble a_val,
|
|
+ enum CRNumType a_type) ;
|
|
+
|
|
+gboolean
|
|
+cr_num_is_fixed_length (CRNum const *a_this) ;
|
|
+
|
|
+void
|
|
+cr_num_destroy (CRNum *a_this) ;
|
|
+
|
|
+
|
|
+G_END_DECLS
|
|
+
|
|
+
|
|
+#endif /*__CR_NUM_H__*/
|
|
diff --git a/src/st/croco/cr-om-parser.c b/src/st/croco/cr-om-parser.c
|
|
new file mode 100644
|
|
index 000000000..ccc45b3e9
|
|
--- /dev/null
|
|
+++ b/src/st/croco/cr-om-parser.c
|
|
@@ -0,0 +1,1142 @@
|
|
+/* -*- 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;
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ *initialyze 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);
|
|
+ }
|
|
+
|
|
+ /*instanciates 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 successfull 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 successfull 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 suppported 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 succesful 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 successfull 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;
|
|
+ }
|
|
+}
|
|
diff --git a/src/st/croco/cr-om-parser.h b/src/st/croco/cr-om-parser.h
|
|
new file mode 100644
|
|
index 000000000..13d35b1cd
|
|
--- /dev/null
|
|
+++ b/src/st/croco/cr-om-parser.h
|
|
@@ -0,0 +1,98 @@
|
|
+/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */
|
|
+
|
|
+/*
|
|
+ * This file is part of The Croco Library
|
|
+ *
|
|
+ * Copyright (C) 2002-2003 Dodji Seketeli <dodji@seketeli.org>
|
|
+ *
|
|
+ * 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
|
|
+ */
|
|
+
|
|
+/*
|
|
+ *$Id$
|
|
+ */
|
|
+
|
|
+#ifndef __CR_OM_PARSER_H__
|
|
+#define __CR_OM_PARSER_H__
|
|
+
|
|
+#include "cr-parser.h"
|
|
+#include "cr-cascade.h"
|
|
+
|
|
+
|
|
+/**
|
|
+ *@file
|
|
+ *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
|
|
+ */
|
|
+
|
|
+G_BEGIN_DECLS
|
|
+
|
|
+typedef struct _CROMParser CROMParser ;
|
|
+typedef struct _CROMParserPriv CROMParserPriv ;
|
|
+
|
|
+/**
|
|
+ *The Object model parser.
|
|
+ *Can parse a css file and build a css object model.
|
|
+ *This parser uses an instance of #CRParser and defines
|
|
+ *a set of SAC callbacks to build the Object Model.
|
|
+ */
|
|
+struct _CROMParser
|
|
+{
|
|
+ CROMParserPriv *priv ;
|
|
+} ;
|
|
+
|
|
+CROMParser * cr_om_parser_new (CRInput *a_input) ;
|
|
+
|
|
+
|
|
+enum CRStatus cr_om_parser_simply_parse_file (const guchar *a_file_path,
|
|
+ enum CREncoding a_enc,
|
|
+ CRStyleSheet **a_result) ;
|
|
+
|
|
+enum CRStatus cr_om_parser_parse_file (CROMParser *a_this,
|
|
+ const guchar *a_file_uri,
|
|
+ enum CREncoding a_enc,
|
|
+ CRStyleSheet **a_result) ;
|
|
+
|
|
+enum CRStatus cr_om_parser_simply_parse_buf (const guchar *a_buf,
|
|
+ gulong a_len,
|
|
+ enum CREncoding a_enc,
|
|
+ CRStyleSheet **a_result) ;
|
|
+
|
|
+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 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 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) ;
|
|
+
|
|
+void cr_om_parser_destroy (CROMParser *a_this) ;
|
|
+
|
|
+G_END_DECLS
|
|
+
|
|
+#endif /*__CR_OM_PARSER_H__*/
|
|
diff --git a/src/st/croco/cr-parser.c b/src/st/croco/cr-parser.c
|
|
new file mode 100644
|
|
index 000000000..07f4ed9e8
|
|
--- /dev/null
|
|
+++ b/src/st/croco/cr-parser.c
|
|
@@ -0,0 +1,4525 @@
|
|
+/* -*- 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 copyrights information.
|
|
+ */
|
|
+
|
|
+/**
|
|
+ *@CRParser:
|
|
+ *
|
|
+ *The definition of the #CRParser class.
|
|
+ */
|
|
+
|
|
+#include "string.h"
|
|
+#include "cr-parser.h"
|
|
+#include "cr-num.h"
|
|
+#include "cr-term.h"
|
|
+#include "cr-simple-sel.h"
|
|
+#include "cr-attr-sel.h"
|
|
+
|
|
+/*
|
|
+ *Random notes:
|
|
+ *CSS core syntax vs CSS level 2 syntax
|
|
+ *=====================================
|
|
+ *
|
|
+ *One must keep in mind
|
|
+ *that css UA must comply with two syntaxes.
|
|
+ *
|
|
+ *1/the specific syntax that defines the css language
|
|
+ *for a given level of specificatin (e.g css2 syntax
|
|
+ *defined in appendix D.1 of the css2 spec)
|
|
+ *
|
|
+ *2/the core (general) syntax that is there to allow
|
|
+ *UAs to parse style sheets written in levels of CSS that
|
|
+ *didn't exist at the time the UAs were created.
|
|
+ *
|
|
+ *the name of parsing functions (or methods) contained in this file
|
|
+ *follows the following scheme: cr_parser_parse_<production_name> (...) ;
|
|
+ *where <production_name> is the name
|
|
+ *of a production of the css2 language.
|
|
+ *When a given production is
|
|
+ *defined by the css2 level grammar *and* by the
|
|
+ *css core syntax, there will be two functions to parse that production:
|
|
+ *one will parse the production defined by the css2 level grammar and the
|
|
+ *other will parse the production defined by the css core grammar.
|
|
+ *The css2 level grammar related parsing function will be called:
|
|
+ *cr_parser_parse_<production_name> (...) ;
|
|
+ *Then css core grammar related parsing function will be called:
|
|
+ *cr_parser_parse_<production_name>_core (...) ;
|
|
+ *
|
|
+ *If a production is defined only by the css core grammar, then
|
|
+ *it will be named:
|
|
+ *cr_parser_parse_<production_name>_core (...) ;
|
|
+ */
|
|
+
|
|
+typedef struct _CRParserError CRParserError;
|
|
+
|
|
+/**
|
|
+ *An abstraction of an error reported by by the
|
|
+ *parsing routines.
|
|
+ */
|
|
+struct _CRParserError {
|
|
+ guchar *msg;
|
|
+ enum CRStatus status;
|
|
+ glong line;
|
|
+ glong column;
|
|
+ glong byte_num;
|
|
+};
|
|
+
|
|
+enum CRParserState {
|
|
+ READY_STATE = 0,
|
|
+ TRY_PARSE_CHARSET_STATE,
|
|
+ CHARSET_PARSED_STATE,
|
|
+ TRY_PARSE_IMPORT_STATE,
|
|
+ IMPORT_PARSED_STATE,
|
|
+ TRY_PARSE_RULESET_STATE,
|
|
+ RULESET_PARSED_STATE,
|
|
+ TRY_PARSE_MEDIA_STATE,
|
|
+ MEDIA_PARSED_STATE,
|
|
+ TRY_PARSE_PAGE_STATE,
|
|
+ PAGE_PARSED_STATE,
|
|
+ TRY_PARSE_FONT_FACE_STATE,
|
|
+ FONT_FACE_PARSED_STATE
|
|
+} ;
|
|
+
|
|
+/**
|
|
+ *The private attributes of
|
|
+ *#CRParser.
|
|
+ */
|
|
+struct _CRParserPriv {
|
|
+ /**
|
|
+ *The tokenizer
|
|
+ */
|
|
+ CRTknzr *tknzr;
|
|
+
|
|
+ /**
|
|
+ *The sac handlers to call
|
|
+ *to notify the parsing of
|
|
+ *the css2 constructions.
|
|
+ */
|
|
+ CRDocHandler *sac_handler;
|
|
+
|
|
+ /**
|
|
+ *A stack of errors reported
|
|
+ *by the parsing routines.
|
|
+ *Contains instance of #CRParserError.
|
|
+ *This pointer is the top of the stack.
|
|
+ */
|
|
+ GList *err_stack;
|
|
+
|
|
+ enum CRParserState state;
|
|
+ gboolean resolve_import;
|
|
+ gboolean is_case_sensitive;
|
|
+ gboolean use_core_grammar;
|
|
+};
|
|
+
|
|
+#define PRIVATE(obj) ((obj)->priv)
|
|
+
|
|
+#define CHARS_TAB_SIZE 12
|
|
+
|
|
+/**
|
|
+ * IS_NUM:
|
|
+ *@a_char: the char to test.
|
|
+ *return TRUE if the character is a number ([0-9]), FALSE otherwise
|
|
+ */
|
|
+#define IS_NUM(a_char) (((a_char) >= '0' && (a_char) <= '9')?TRUE:FALSE)
|
|
+
|
|
+/**
|
|
+ *Checks if 'status' equals CR_OK. If not, goto the 'error' label.
|
|
+ *
|
|
+ *@param status the status (of type enum CRStatus) to test.
|
|
+ *@param is_exception if set to FALSE, the final status returned
|
|
+ *by the current function will be CR_PARSING_ERROR. If set to TRUE, the
|
|
+ *current status will be the current value of the 'status' variable.
|
|
+ *
|
|
+ */
|
|
+#define CHECK_PARSING_STATUS(status, is_exception) \
|
|
+if ((status) != CR_OK) \
|
|
+{ \
|
|
+ if (is_exception == FALSE) \
|
|
+ { \
|
|
+ status = CR_PARSING_ERROR ; \
|
|
+ } \
|
|
+ goto error ; \
|
|
+}
|
|
+
|
|
+/**
|
|
+ * CHECK_PARSING_STATUS_ERR:
|
|
+ *@a_this: the current instance of #CRParser .
|
|
+ *@a_status: the status to check. Is of type enum #CRStatus.
|
|
+ *@a_is_exception: in case of error, if is TRUE, the status
|
|
+ *is set to CR_PARSING_ERROR before goto error. If is false, the
|
|
+ *real low level status is kept and will be returned by the
|
|
+ *upper level function that called this macro. Usally,this must
|
|
+ *be set to FALSE.
|
|
+ *
|
|
+ *same as CHECK_PARSING_STATUS() but this one pushes an error
|
|
+ *on the parser error stack when an error arises.
|
|
+ *
|
|
+ */
|
|
+#define CHECK_PARSING_STATUS_ERR(a_this, a_status, a_is_exception,\
|
|
+ a_err_msg, a_err_status) \
|
|
+if ((a_status) != CR_OK) \
|
|
+{ \
|
|
+ if (a_is_exception == FALSE) a_status = CR_PARSING_ERROR ; \
|
|
+ cr_parser_push_error (a_this, a_err_msg, a_err_status) ; \
|
|
+ goto error ; \
|
|
+}
|
|
+
|
|
+/**
|
|
+ *Peeks the next char from the input stream of the current parser
|
|
+ *by invoking cr_tknzr_input_peek_char().
|
|
+ *invokes CHECK_PARSING_STATUS on the status returned by
|
|
+ *cr_tknzr_peek_char().
|
|
+ *
|
|
+ *@param a_this the current instance of #CRParser.
|
|
+ *@param a_to_char a pointer to the char where to store the
|
|
+ *char peeked.
|
|
+ */
|
|
+#define PEEK_NEXT_CHAR(a_this, a_to_char) \
|
|
+{\
|
|
+status = cr_tknzr_peek_char (PRIVATE (a_this)->tknzr, a_to_char) ; \
|
|
+CHECK_PARSING_STATUS (status, TRUE) \
|
|
+}
|
|
+
|
|
+/**
|
|
+ *Reads the next char from the input stream of the current parser.
|
|
+ *In case of error, jumps to the "error:" label located in the
|
|
+ *function where this macro is called.
|
|
+ *@param a_this the curent instance of #CRParser
|
|
+ *@param to_char a pointer to the guint32 char where to store
|
|
+ *the character read.
|
|
+ */
|
|
+#define READ_NEXT_CHAR(a_this, a_to_char) \
|
|
+status = cr_tknzr_read_char (PRIVATE (a_this)->tknzr, a_to_char) ; \
|
|
+CHECK_PARSING_STATUS (status, TRUE)
|
|
+
|
|
+/**
|
|
+ *Gets information about the current position in
|
|
+ *the input of the parser.
|
|
+ *In case of failure, this macro returns from the
|
|
+ *calling function and
|
|
+ *returns a status code of type enum #CRStatus.
|
|
+ *@param a_this the current instance of #CRParser.
|
|
+ *@param a_pos out parameter. A pointer to the position
|
|
+ *inside the current parser input. Must
|
|
+ */
|
|
+#define RECORD_INITIAL_POS(a_this, a_pos) \
|
|
+status = cr_tknzr_get_cur_pos (PRIVATE \
|
|
+(a_this)->tknzr, a_pos) ; \
|
|
+g_return_val_if_fail (status == CR_OK, status)
|
|
+
|
|
+/**
|
|
+ *Gets the address of the current byte inside the
|
|
+ *parser input.
|
|
+ *@param parser the current instance of #CRParser.
|
|
+ *@param addr out parameter a pointer (guchar*)
|
|
+ *to where the address must be put.
|
|
+ */
|
|
+#define RECORD_CUR_BYTE_ADDR(a_this, a_addr) \
|
|
+status = cr_tknzr_get_cur_byte_addr \
|
|
+ (PRIVATE (a_this)->tknzr, a_addr) ; \
|
|
+CHECK_PARSING_STATUS (status, TRUE)
|
|
+
|
|
+/**
|
|
+ *Peeks a byte from the topmost parser input at
|
|
+ *a given offset from the current position.
|
|
+ *If it fails, goto the "error:" label.
|
|
+ *
|
|
+ *@param a_parser the current instance of #CRParser.
|
|
+ *@param a_offset the offset of the byte to peek, the
|
|
+ *current byte having the offset '0'.
|
|
+ *@param a_byte_ptr out parameter a pointer (guchar*) to
|
|
+ *where the peeked char is to be stored.
|
|
+ */
|
|
+#define PEEK_BYTE(a_parser, a_offset, a_byte_ptr) \
|
|
+status = cr_tknzr_peek_byte (PRIVATE (a_this)->tknzr, \
|
|
+ a_offset, \
|
|
+ a_byte_ptr) ; \
|
|
+CHECK_PARSING_STATUS (status, TRUE) ;
|
|
+
|
|
+#define BYTE(a_parser, a_offset, a_eof) \
|
|
+cr_tknzr_peek_byte2 (PRIVATE (a_this)->tknzr, a_offset, a_eof)
|
|
+
|
|
+/**
|
|
+ *Reads a byte from the topmost parser input
|
|
+ *steam.
|
|
+ *If it fails, goto the "error" label.
|
|
+ *@param a_this the current instance of #CRParser.
|
|
+ *@param a_byte_ptr the guchar * where to put the read char.
|
|
+ */
|
|
+#define READ_NEXT_BYTE(a_this, a_byte_ptr) \
|
|
+status = cr_tknzr_read_byte (PRIVATE (a_this)->tknzr, a_byte_ptr) ; \
|
|
+CHECK_PARSING_STATUS (status, TRUE) ;
|
|
+
|
|
+/**
|
|
+ *Skips a given number of byte in the topmost
|
|
+ *parser input. Don't update line and column number.
|
|
+ *In case of error, jumps to the "error:" label
|
|
+ *of the surrounding function.
|
|
+ *@param a_parser the current instance of #CRParser.
|
|
+ *@param a_nb_bytes the number of bytes to skip.
|
|
+ */
|
|
+#define SKIP_BYTES(a_this, a_nb_bytes) \
|
|
+status = cr_tknzr_seek_index (PRIVATE (a_this)->tknzr, \
|
|
+ CR_SEEK_CUR, a_nb_bytes) ; \
|
|
+CHECK_PARSING_STATUS (status, TRUE) ;
|
|
+
|
|
+/**
|
|
+ *Skip utf8 encoded characters.
|
|
+ *Updates line and column numbers.
|
|
+ *@param a_parser the current instance of #CRParser.
|
|
+ *@param a_nb_chars the number of chars to skip. Must be of
|
|
+ *type glong.
|
|
+ */
|
|
+#define SKIP_CHARS(a_parser, a_nb_chars) \
|
|
+{ \
|
|
+glong nb_chars = a_nb_chars ; \
|
|
+status = cr_tknzr_consume_chars \
|
|
+ (PRIVATE (a_parser)->tknzr,0, &nb_chars) ; \
|
|
+CHECK_PARSING_STATUS (status, TRUE) ; \
|
|
+}
|
|
+
|
|
+/**
|
|
+ *Tests the condition and if it is false, sets
|
|
+ *status to "CR_PARSING_ERROR" and goto the 'error'
|
|
+ *label.
|
|
+ *@param condition the condition to test.
|
|
+ */
|
|
+#define ENSURE_PARSING_COND(condition) \
|
|
+if (! (condition)) {status = CR_PARSING_ERROR; goto error ;}
|
|
+
|
|
+#define ENSURE_PARSING_COND_ERR(a_this, a_condition, \
|
|
+ a_err_msg, a_err_status) \
|
|
+if (! (a_condition)) \
|
|
+{ \
|
|
+ status = CR_PARSING_ERROR; \
|
|
+ cr_parser_push_error (a_this, a_err_msg, a_err_status) ; \
|
|
+ goto error ; \
|
|
+}
|
|
+
|
|
+#define GET_NEXT_TOKEN(a_this, a_token_ptr) \
|
|
+status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, \
|
|
+ a_token_ptr) ; \
|
|
+ENSURE_PARSING_COND (status == CR_OK) ;
|
|
+
|
|
+#ifdef WITH_UNICODE_ESCAPE_AND_RANGE
|
|
+static enum CRStatus cr_parser_parse_unicode_escape (CRParser * a_this,
|
|
+ guint32 * a_unicode);
|
|
+static enum CRStatus cr_parser_parse_escape (CRParser * a_this,
|
|
+ guint32 * a_esc_code);
|
|
+
|
|
+static enum CRStatus cr_parser_parse_unicode_range (CRParser * a_this,
|
|
+ CRString ** a_inf,
|
|
+ CRString ** a_sup);
|
|
+#endif
|
|
+
|
|
+static enum CRStatus cr_parser_parse_stylesheet_core (CRParser * a_this);
|
|
+
|
|
+static enum CRStatus cr_parser_parse_atrule_core (CRParser * a_this);
|
|
+
|
|
+static enum CRStatus cr_parser_parse_ruleset_core (CRParser * a_this);
|
|
+
|
|
+static enum CRStatus cr_parser_parse_selector_core (CRParser * a_this);
|
|
+
|
|
+static enum CRStatus cr_parser_parse_declaration_core (CRParser * a_this);
|
|
+
|
|
+static enum CRStatus cr_parser_parse_any_core (CRParser * a_this);
|
|
+
|
|
+static enum CRStatus cr_parser_parse_block_core (CRParser * a_this);
|
|
+
|
|
+static enum CRStatus cr_parser_parse_value_core (CRParser * a_this);
|
|
+
|
|
+static enum CRStatus cr_parser_parse_string (CRParser * a_this,
|
|
+ CRString ** a_str);
|
|
+
|
|
+static enum CRStatus cr_parser_parse_ident (CRParser * a_this,
|
|
+ CRString ** a_str);
|
|
+
|
|
+static enum CRStatus cr_parser_parse_uri (CRParser * a_this,
|
|
+ CRString ** a_str);
|
|
+
|
|
+static enum CRStatus cr_parser_parse_function (CRParser * a_this,
|
|
+ CRString ** a_func_name,
|
|
+ CRTerm ** a_expr);
|
|
+static enum CRStatus cr_parser_parse_property (CRParser * a_this,
|
|
+ CRString ** a_property);
|
|
+
|
|
+static enum CRStatus cr_parser_parse_attribute_selector (CRParser * a_this,
|
|
+ CRAttrSel ** a_sel);
|
|
+
|
|
+static enum CRStatus cr_parser_parse_simple_selector (CRParser * a_this,
|
|
+ CRSimpleSel ** a_sel);
|
|
+
|
|
+static enum CRStatus cr_parser_parse_simple_sels (CRParser * a_this,
|
|
+ CRSimpleSel ** a_sel);
|
|
+
|
|
+static CRParserError *cr_parser_error_new (const guchar * a_msg,
|
|
+ enum CRStatus);
|
|
+
|
|
+static void cr_parser_error_set_msg (CRParserError * a_this,
|
|
+ const guchar * a_msg);
|
|
+
|
|
+static void cr_parser_error_dump (CRParserError * a_this);
|
|
+
|
|
+static void cr_parser_error_set_status (CRParserError * a_this,
|
|
+ enum CRStatus a_status);
|
|
+
|
|
+static void cr_parser_error_set_pos (CRParserError * a_this,
|
|
+ glong a_line,
|
|
+ glong a_column, glong a_byte_num);
|
|
+static void
|
|
+ cr_parser_error_destroy (CRParserError * a_this);
|
|
+
|
|
+static enum CRStatus cr_parser_push_error (CRParser * a_this,
|
|
+ const guchar * a_msg,
|
|
+ enum CRStatus a_status);
|
|
+
|
|
+static enum CRStatus cr_parser_dump_err_stack (CRParser * a_this,
|
|
+ gboolean a_clear_errs);
|
|
+static enum CRStatus
|
|
+ cr_parser_clear_errors (CRParser * a_this);
|
|
+
|
|
+/*****************************
|
|
+ *error managemet methods
|
|
+ *****************************/
|
|
+
|
|
+/**
|
|
+ *Constructor of #CRParserError class.
|
|
+ *@param a_msg the brute error message.
|
|
+ *@param a_status the error status.
|
|
+ *@return the newly built instance of #CRParserError.
|
|
+ */
|
|
+static CRParserError *
|
|
+cr_parser_error_new (const guchar * a_msg, enum CRStatus a_status)
|
|
+{
|
|
+ CRParserError *result = NULL;
|
|
+
|
|
+ result = g_try_malloc (sizeof (CRParserError));
|
|
+
|
|
+ if (result == NULL) {
|
|
+ cr_utils_trace_info ("Out of memory");
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
+ memset (result, 0, sizeof (CRParserError));
|
|
+
|
|
+ cr_parser_error_set_msg (result, a_msg);
|
|
+ cr_parser_error_set_status (result, a_status);
|
|
+
|
|
+ return result;
|
|
+}
|
|
+
|
|
+/**
|
|
+ *Sets the message associated to this instance of #CRError.
|
|
+ *@param a_this the current instance of #CRParserError.
|
|
+ *@param a_msg the new message.
|
|
+ */
|
|
+static void
|
|
+cr_parser_error_set_msg (CRParserError * a_this, const guchar * a_msg)
|
|
+{
|
|
+ g_return_if_fail (a_this);
|
|
+
|
|
+ if (a_this->msg) {
|
|
+ g_free (a_this->msg);
|
|
+ }
|
|
+
|
|
+ a_this->msg = (guchar *) g_strdup ((const gchar *) a_msg);
|
|
+}
|
|
+
|
|
+/**
|
|
+ *Sets the error status.
|
|
+ *@param a_this the current instance of #CRParserError.
|
|
+ *@param a_status the new error status.
|
|
+ *
|
|
+ */
|
|
+static void
|
|
+cr_parser_error_set_status (CRParserError * a_this, enum CRStatus a_status)
|
|
+{
|
|
+ g_return_if_fail (a_this);
|
|
+
|
|
+ a_this->status = a_status;
|
|
+}
|
|
+
|
|
+/**
|
|
+ *Sets the position of the parser error.
|
|
+ *@param a_this the current instance of #CRParserError.
|
|
+ *@param a_line the line number.
|
|
+ *@param a_column the column number.
|
|
+ *@param a_byte_num the byte number.
|
|
+ */
|
|
+static void
|
|
+cr_parser_error_set_pos (CRParserError * a_this,
|
|
+ glong a_line, glong a_column, glong a_byte_num)
|
|
+{
|
|
+ g_return_if_fail (a_this);
|
|
+
|
|
+ a_this->line = a_line;
|
|
+ a_this->column = a_column;
|
|
+ a_this->byte_num = a_byte_num;
|
|
+}
|
|
+
|
|
+static void
|
|
+cr_parser_error_dump (CRParserError * a_this)
|
|
+{
|
|
+ g_return_if_fail (a_this);
|
|
+
|
|
+ g_printerr ("parsing error: %ld:%ld:", a_this->line, a_this->column);
|
|
+
|
|
+ g_printerr ("%s\n", a_this->msg);
|
|
+}
|
|
+
|
|
+/**
|
|
+ *The destructor of #CRParserError.
|
|
+ *@param a_this the current instance of #CRParserError.
|
|
+ */
|
|
+static void
|
|
+cr_parser_error_destroy (CRParserError * a_this)
|
|
+{
|
|
+ g_return_if_fail (a_this);
|
|
+
|
|
+ if (a_this->msg) {
|
|
+ g_free (a_this->msg);
|
|
+ a_this->msg = NULL;
|
|
+ }
|
|
+
|
|
+ g_free (a_this);
|
|
+}
|
|
+
|
|
+/**
|
|
+ *Pushes an error on the parser error stack.
|
|
+ *@param a_this the current instance of #CRParser.
|
|
+ *@param a_msg the error message.
|
|
+ *@param a_status the error status.
|
|
+ *@return CR_OK upon successfull completion, an error code otherwise.
|
|
+ */
|
|
+static enum CRStatus
|
|
+cr_parser_push_error (CRParser * a_this,
|
|
+ const guchar * a_msg, enum CRStatus a_status)
|
|
+{
|
|
+ enum CRStatus status = CR_OK;
|
|
+
|
|
+ CRParserError *error = NULL;
|
|
+ CRInputPos pos;
|
|
+
|
|
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
|
|
+ && a_msg, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ error = cr_parser_error_new (a_msg, a_status);
|
|
+
|
|
+ g_return_val_if_fail (error, CR_ERROR);
|
|
+
|
|
+ RECORD_INITIAL_POS (a_this, &pos);
|
|
+
|
|
+ cr_parser_error_set_pos
|
|
+ (error, pos.line, pos.col, pos.next_byte_index - 1);
|
|
+
|
|
+ PRIVATE (a_this)->err_stack =
|
|
+ g_list_prepend (PRIVATE (a_this)->err_stack, error);
|
|
+
|
|
+ if (PRIVATE (a_this)->err_stack == NULL)
|
|
+ goto error;
|
|
+
|
|
+ return CR_OK;
|
|
+
|
|
+ error:
|
|
+
|
|
+ if (error) {
|
|
+ cr_parser_error_destroy (error);
|
|
+ error = NULL;
|
|
+ }
|
|
+
|
|
+ return status;
|
|
+}
|
|
+
|
|
+/**
|
|
+ *Dumps the error stack on stdout.
|
|
+ *@param a_this the current instance of #CRParser.
|
|
+ *@param a_clear_errs whether to clear the error stack
|
|
+ *after the dump or not.
|
|
+ *@return CR_OK upon successfull completion, an error code
|
|
+ *otherwise.
|
|
+ */
|
|
+static enum CRStatus
|
|
+cr_parser_dump_err_stack (CRParser * a_this, gboolean a_clear_errs)
|
|
+{
|
|
+ GList *cur = NULL;
|
|
+
|
|
+ g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ if (PRIVATE (a_this)->err_stack == NULL)
|
|
+ return CR_OK;
|
|
+
|
|
+ for (cur = PRIVATE (a_this)->err_stack; cur; cur = cur->next) {
|
|
+ cr_parser_error_dump ((CRParserError *) cur->data);
|
|
+ }
|
|
+
|
|
+ if (a_clear_errs == TRUE) {
|
|
+ cr_parser_clear_errors (a_this);
|
|
+ }
|
|
+
|
|
+ return CR_OK;
|
|
+}
|
|
+
|
|
+/**
|
|
+ *Clears all the errors contained in the parser error stack.
|
|
+ *Frees all the errors, and the stack that contains'em.
|
|
+ *@param a_this the current instance of #CRParser.
|
|
+ */
|
|
+static enum CRStatus
|
|
+cr_parser_clear_errors (CRParser * a_this)
|
|
+{
|
|
+ GList *cur = NULL;
|
|
+
|
|
+ g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ for (cur = PRIVATE (a_this)->err_stack; cur; cur = cur->next) {
|
|
+ if (cur->data) {
|
|
+ cr_parser_error_destroy ((CRParserError *)
|
|
+ cur->data);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (PRIVATE (a_this)->err_stack) {
|
|
+ g_list_free (PRIVATE (a_this)->err_stack);
|
|
+ PRIVATE (a_this)->err_stack = NULL;
|
|
+ }
|
|
+
|
|
+ return CR_OK;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_parser_try_to_skip_spaces_and_comments:
|
|
+ *@a_this: the current instance of #CRParser.
|
|
+ *
|
|
+ *Same as cr_parser_try_to_skip_spaces() but this one skips
|
|
+ *spaces and comments.
|
|
+ *
|
|
+ *Returns CR_OK upon successfull completion, an error code otherwise.
|
|
+ */
|
|
+enum CRStatus
|
|
+cr_parser_try_to_skip_spaces_and_comments (CRParser * a_this)
|
|
+{
|
|
+ enum CRStatus status = CR_ERROR;
|
|
+ CRToken *token = NULL;
|
|
+
|
|
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
|
|
+ && PRIVATE (a_this)->tknzr, CR_BAD_PARAM_ERROR);
|
|
+ do {
|
|
+ if (token) {
|
|
+ cr_token_destroy (token);
|
|
+ token = NULL;
|
|
+ }
|
|
+
|
|
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr,
|
|
+ &token);
|
|
+ if (status != CR_OK)
|
|
+ goto error;
|
|
+ }
|
|
+ while ((token != NULL)
|
|
+ && (token->type == COMMENT_TK || token->type == S_TK));
|
|
+
|
|
+ cr_tknzr_unget_token (PRIVATE (a_this)->tknzr, token);
|
|
+
|
|
+ return status;
|
|
+
|
|
+ error:
|
|
+
|
|
+ if (token) {
|
|
+ cr_token_destroy (token);
|
|
+ token = NULL;
|
|
+ }
|
|
+
|
|
+ return status;
|
|
+}
|
|
+
|
|
+/***************************************
|
|
+ *End of Parser input handling routines
|
|
+ ***************************************/
|
|
+
|
|
+
|
|
+/*************************************
|
|
+ *Non trivial terminal productions
|
|
+ *parsing routines
|
|
+ *************************************/
|
|
+
|
|
+/**
|
|
+ *Parses a css stylesheet following the core css grammar.
|
|
+ *This is mainly done for test purposes.
|
|
+ *During the parsing, no callback is called. This is just
|
|
+ *to validate that the stylesheet is well formed according to the
|
|
+ *css core syntax.
|
|
+ *stylesheet : [ CDO | CDC | S | statement ]*;
|
|
+ *@param a_this the current instance of #CRParser.
|
|
+ *@return CR_OK upon successful completion, an error code otherwise.
|
|
+ */
|
|
+static enum CRStatus
|
|
+cr_parser_parse_stylesheet_core (CRParser * a_this)
|
|
+{
|
|
+ CRToken *token = NULL;
|
|
+ CRInputPos init_pos;
|
|
+ enum CRStatus status = CR_ERROR;
|
|
+
|
|
+ g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ RECORD_INITIAL_POS (a_this, &init_pos);
|
|
+
|
|
+ continue_parsing:
|
|
+
|
|
+ if (token) {
|
|
+ cr_token_destroy (token);
|
|
+ token = NULL;
|
|
+ }
|
|
+
|
|
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
|
|
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
|
|
+ if (status == CR_END_OF_INPUT_ERROR) {
|
|
+ status = CR_OK;
|
|
+ goto done;
|
|
+ } else if (status != CR_OK) {
|
|
+ goto error;
|
|
+ }
|
|
+
|
|
+ switch (token->type) {
|
|
+
|
|
+ case CDO_TK:
|
|
+ case CDC_TK:
|
|
+ goto continue_parsing;
|
|
+ break;
|
|
+ default:
|
|
+ status = cr_tknzr_unget_token (PRIVATE (a_this)->tknzr,
|
|
+ token);
|
|
+ CHECK_PARSING_STATUS (status, TRUE);
|
|
+ token = NULL;
|
|
+ status = cr_parser_parse_statement_core (a_this);
|
|
+ cr_parser_clear_errors (a_this);
|
|
+ if (status == CR_OK) {
|
|
+ goto continue_parsing;
|
|
+ } else if (status == CR_END_OF_INPUT_ERROR) {
|
|
+ goto done;
|
|
+ } else {
|
|
+ goto error;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ done:
|
|
+ if (token) {
|
|
+ cr_token_destroy (token);
|
|
+ token = NULL;
|
|
+ }
|
|
+
|
|
+ cr_parser_clear_errors (a_this);
|
|
+ return CR_OK;
|
|
+
|
|
+ error:
|
|
+ cr_parser_push_error
|
|
+ (a_this, (const guchar *) "could not recognize next production", CR_ERROR);
|
|
+
|
|
+ cr_parser_dump_err_stack (a_this, TRUE);
|
|
+
|
|
+ if (token) {
|
|
+ cr_token_destroy (token);
|
|
+ token = NULL;
|
|
+ }
|
|
+
|
|
+ cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
|
|
+
|
|
+ return status;
|
|
+}
|
|
+
|
|
+/**
|
|
+ *Parses an at-rule as defined by the css core grammar
|
|
+ *in chapter 4.1 in the css2 spec.
|
|
+ *at-rule : ATKEYWORD S* any* [ block | ';' S* ];
|
|
+ *@param a_this the current instance of #CRParser.
|
|
+ *@return CR_OK upon successfull completion, an error code
|
|
+ *otherwise.
|
|
+ */
|
|
+static enum CRStatus
|
|
+cr_parser_parse_atrule_core (CRParser * a_this)
|
|
+{
|
|
+ CRToken *token = NULL;
|
|
+ CRInputPos init_pos;
|
|
+ enum CRStatus status = CR_ERROR;
|
|
+
|
|
+ g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ RECORD_INITIAL_POS (a_this, &init_pos);
|
|
+
|
|
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr,
|
|
+ &token);
|
|
+ ENSURE_PARSING_COND (status == CR_OK
|
|
+ && token
|
|
+ &&
|
|
+ (token->type == ATKEYWORD_TK
|
|
+ || token->type == IMPORT_SYM_TK
|
|
+ || token->type == PAGE_SYM_TK
|
|
+ || token->type == MEDIA_SYM_TK
|
|
+ || token->type == FONT_FACE_SYM_TK
|
|
+ || token->type == CHARSET_SYM_TK));
|
|
+
|
|
+ cr_token_destroy (token);
|
|
+ token = NULL;
|
|
+
|
|
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
|
|
+
|
|
+ do {
|
|
+ status = cr_parser_parse_any_core (a_this);
|
|
+ } while (status == CR_OK);
|
|
+
|
|
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr,
|
|
+ &token);
|
|
+ ENSURE_PARSING_COND (status == CR_OK && token);
|
|
+
|
|
+ if (token->type == CBO_TK) {
|
|
+ cr_tknzr_unget_token (PRIVATE (a_this)->tknzr,
|
|
+ token);
|
|
+ token = NULL;
|
|
+ status = cr_parser_parse_block_core (a_this);
|
|
+ CHECK_PARSING_STATUS (status,
|
|
+ FALSE);
|
|
+ goto done;
|
|
+ } else if (token->type == SEMICOLON_TK) {
|
|
+ goto done;
|
|
+ } else {
|
|
+ status = CR_PARSING_ERROR ;
|
|
+ goto error;
|
|
+ }
|
|
+
|
|
+ done:
|
|
+ if (token) {
|
|
+ cr_token_destroy (token);
|
|
+ token = NULL;
|
|
+ }
|
|
+ return CR_OK;
|
|
+
|
|
+ error:
|
|
+ if (token) {
|
|
+ cr_token_destroy (token);
|
|
+ token = NULL;
|
|
+ }
|
|
+ cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr,
|
|
+ &init_pos);
|
|
+ return status;
|
|
+}
|
|
+
|
|
+/**
|
|
+ *Parses a ruleset as defined by the css core grammar in chapter
|
|
+ *4.1 of the css2 spec.
|
|
+ *ruleset ::= selector? '{' S* declaration? [ ';' S* declaration? ]* '}' S*;
|
|
+ *@param a_this the current instance of #CRParser.
|
|
+ *@return CR_OK upon successfull completion, an error code otherwise.
|
|
+ */
|
|
+static enum CRStatus
|
|
+cr_parser_parse_ruleset_core (CRParser * a_this)
|
|
+{
|
|
+ CRToken *token = NULL;
|
|
+ CRInputPos init_pos;
|
|
+ enum CRStatus status = CR_ERROR;
|
|
+
|
|
+ g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
|
|
+ RECORD_INITIAL_POS (a_this, &init_pos);
|
|
+
|
|
+ status = cr_parser_parse_selector_core (a_this);
|
|
+
|
|
+ ENSURE_PARSING_COND (status == CR_OK
|
|
+ || status == CR_PARSING_ERROR
|
|
+ || status == CR_END_OF_INPUT_ERROR);
|
|
+
|
|
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
|
|
+ ENSURE_PARSING_COND (status == CR_OK && token
|
|
+ && token->type == CBO_TK);
|
|
+ cr_token_destroy (token);
|
|
+ token = NULL;
|
|
+
|
|
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
|
|
+ status = cr_parser_parse_declaration_core (a_this);
|
|
+
|
|
+ parse_declaration_list:
|
|
+ if (token) {
|
|
+ cr_token_destroy (token);
|
|
+ token = NULL;
|
|
+ }
|
|
+
|
|
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
|
|
+ ENSURE_PARSING_COND (status == CR_OK && token);
|
|
+ if (token->type == CBC_TK) {
|
|
+ goto done;
|
|
+ }
|
|
+
|
|
+ ENSURE_PARSING_COND (status == CR_OK
|
|
+ && token && token->type == SEMICOLON_TK);
|
|
+
|
|
+ cr_token_destroy (token);
|
|
+ token = NULL;
|
|
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
|
|
+ status = cr_parser_parse_declaration_core (a_this);
|
|
+ cr_parser_clear_errors (a_this);
|
|
+ ENSURE_PARSING_COND (status == CR_OK || status == CR_PARSING_ERROR);
|
|
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
|
|
+ ENSURE_PARSING_COND (status == CR_OK && token);
|
|
+ if (token->type == CBC_TK) {
|
|
+ cr_token_destroy (token);
|
|
+ token = NULL;
|
|
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
|
|
+ goto done;
|
|
+ } else {
|
|
+ status = cr_tknzr_unget_token (PRIVATE (a_this)->tknzr,
|
|
+ token);
|
|
+ token = NULL;
|
|
+ goto parse_declaration_list;
|
|
+ }
|
|
+
|
|
+ done:
|
|
+ if (token) {
|
|
+ cr_token_destroy (token);
|
|
+ token = NULL;
|
|
+ }
|
|
+
|
|
+ if (status == CR_OK) {
|
|
+ return CR_OK;
|
|
+ }
|
|
+
|
|
+ error:
|
|
+ if (token) {
|
|
+ cr_token_destroy (token);
|
|
+ token = NULL;
|
|
+ }
|
|
+
|
|
+ cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
|
|
+
|
|
+ return status;
|
|
+}
|
|
+
|
|
+/**
|
|
+ *Parses a "selector" as specified by the css core
|
|
+ *grammar.
|
|
+ *selector : any+;
|
|
+ *@param a_this the current instance of #CRParser.
|
|
+ *@return CR_OK upon successfull completion, an error code
|
|
+ *otherwise.
|
|
+ */
|
|
+static enum CRStatus
|
|
+cr_parser_parse_selector_core (CRParser * a_this)
|
|
+{
|
|
+ CRToken *token = NULL;
|
|
+ CRInputPos init_pos;
|
|
+ enum CRStatus status = CR_ERROR;
|
|
+
|
|
+ g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ RECORD_INITIAL_POS (a_this, &init_pos);
|
|
+
|
|
+ status = cr_parser_parse_any_core (a_this);
|
|
+ CHECK_PARSING_STATUS (status, FALSE);
|
|
+
|
|
+ do {
|
|
+ status = cr_parser_parse_any_core (a_this);
|
|
+
|
|
+ } while (status == CR_OK);
|
|
+
|
|
+ return CR_OK;
|
|
+
|
|
+ error:
|
|
+ if (token) {
|
|
+ cr_token_destroy (token);
|
|
+ token = NULL;
|
|
+ }
|
|
+
|
|
+ cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
|
|
+
|
|
+ return status;
|
|
+}
|
|
+
|
|
+/**
|
|
+ *Parses a "block" as defined in the css core grammar
|
|
+ *in chapter 4.1 of the css2 spec.
|
|
+ *block ::= '{' S* [ any | block | ATKEYWORD S* | ';' ]* '}' S*;
|
|
+ *@param a_this the current instance of #CRParser.
|
|
+ *FIXME: code this function.
|
|
+ */
|
|
+static enum CRStatus
|
|
+cr_parser_parse_block_core (CRParser * a_this)
|
|
+{
|
|
+ CRToken *token = NULL;
|
|
+ CRInputPos init_pos;
|
|
+ enum CRStatus status = CR_ERROR;
|
|
+
|
|
+ g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ RECORD_INITIAL_POS (a_this, &init_pos);
|
|
+
|
|
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
|
|
+ ENSURE_PARSING_COND (status == CR_OK && token
|
|
+ && token->type == CBO_TK);
|
|
+
|
|
+ parse_block_content:
|
|
+
|
|
+ if (token) {
|
|
+ cr_token_destroy (token);
|
|
+ token = NULL;
|
|
+ }
|
|
+
|
|
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
|
|
+
|
|
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
|
|
+ ENSURE_PARSING_COND (status == CR_OK && token);
|
|
+
|
|
+ if (token->type == CBC_TK) {
|
|
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
|
|
+ goto done;
|
|
+ } else if (token->type == SEMICOLON_TK) {
|
|
+ goto parse_block_content;
|
|
+ } else if (token->type == ATKEYWORD_TK) {
|
|
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
|
|
+ goto parse_block_content;
|
|
+ } else if (token->type == CBO_TK) {
|
|
+ cr_tknzr_unget_token (PRIVATE (a_this)->tknzr, token);
|
|
+ token = NULL;
|
|
+ status = cr_parser_parse_block_core (a_this);
|
|
+ CHECK_PARSING_STATUS (status, FALSE);
|
|
+ goto parse_block_content;
|
|
+ } else {
|
|
+ cr_tknzr_unget_token (PRIVATE (a_this)->tknzr, token);
|
|
+ token = NULL;
|
|
+ status = cr_parser_parse_any_core (a_this);
|
|
+ CHECK_PARSING_STATUS (status, FALSE);
|
|
+ goto parse_block_content;
|
|
+ }
|
|
+
|
|
+ done:
|
|
+ if (token) {
|
|
+ cr_token_destroy (token);
|
|
+ token = NULL;
|
|
+ }
|
|
+
|
|
+ if (status == CR_OK)
|
|
+ return CR_OK;
|
|
+
|
|
+ error:
|
|
+ if (token) {
|
|
+ cr_token_destroy (token);
|
|
+ token = NULL;
|
|
+ }
|
|
+
|
|
+ cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
|
|
+
|
|
+ return status;
|
|
+}
|
|
+
|
|
+static enum CRStatus
|
|
+cr_parser_parse_declaration_core (CRParser * a_this)
|
|
+{
|
|
+ CRToken *token = NULL;
|
|
+ CRInputPos init_pos;
|
|
+ enum CRStatus status = CR_ERROR;
|
|
+ CRString *prop = NULL;
|
|
+
|
|
+ g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ RECORD_INITIAL_POS (a_this, &init_pos);
|
|
+
|
|
+ status = cr_parser_parse_property (a_this, &prop);
|
|
+ CHECK_PARSING_STATUS (status, FALSE);
|
|
+ cr_parser_clear_errors (a_this);
|
|
+ ENSURE_PARSING_COND (status == CR_OK && prop);
|
|
+ cr_string_destroy (prop);
|
|
+ prop = NULL;
|
|
+
|
|
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
|
|
+ ENSURE_PARSING_COND (status == CR_OK
|
|
+ && token
|
|
+ && token->type == DELIM_TK
|
|
+ && token->u.unichar == ':');
|
|
+ cr_token_destroy (token);
|
|
+ token = NULL;
|
|
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
|
|
+ status = cr_parser_parse_value_core (a_this);
|
|
+ CHECK_PARSING_STATUS (status, FALSE);
|
|
+
|
|
+ return CR_OK;
|
|
+
|
|
+ error:
|
|
+
|
|
+ if (prop) {
|
|
+ cr_string_destroy (prop);
|
|
+ prop = NULL;
|
|
+ }
|
|
+
|
|
+ if (token) {
|
|
+ cr_token_destroy (token);
|
|
+ token = NULL;
|
|
+ }
|
|
+
|
|
+ cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
|
|
+
|
|
+ return status;
|
|
+}
|
|
+
|
|
+/**
|
|
+ *Parses a "value" production as defined by the css core grammar
|
|
+ *in chapter 4.1.
|
|
+ *value ::= [ any | block | ATKEYWORD S* ]+;
|
|
+ *@param a_this the current instance of #CRParser.
|
|
+ *@return CR_OK upon successfull completion, an error code otherwise.
|
|
+ */
|
|
+static enum CRStatus
|
|
+cr_parser_parse_value_core (CRParser * a_this)
|
|
+{
|
|
+ CRToken *token = NULL;
|
|
+ CRInputPos init_pos;
|
|
+ enum CRStatus status = CR_ERROR;
|
|
+ glong ref = 0;
|
|
+
|
|
+ g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
|
|
+ RECORD_INITIAL_POS (a_this, &init_pos);
|
|
+
|
|
+ continue_parsing:
|
|
+
|
|
+ if (token) {
|
|
+ cr_token_destroy (token);
|
|
+ token = NULL;
|
|
+ }
|
|
+
|
|
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
|
|
+ ENSURE_PARSING_COND (status == CR_OK && token);
|
|
+
|
|
+ switch (token->type) {
|
|
+ case CBO_TK:
|
|
+ status = cr_tknzr_unget_token (PRIVATE (a_this)->tknzr,
|
|
+ token);
|
|
+ token = NULL;
|
|
+ status = cr_parser_parse_block_core (a_this);
|
|
+ CHECK_PARSING_STATUS (status, FALSE);
|
|
+ ref++;
|
|
+ goto continue_parsing;
|
|
+
|
|
+ case ATKEYWORD_TK:
|
|
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
|
|
+ ref++;
|
|
+ goto continue_parsing;
|
|
+
|
|
+ default:
|
|
+ status = cr_tknzr_unget_token (PRIVATE (a_this)->tknzr,
|
|
+ token);
|
|
+ token = NULL;
|
|
+ status = cr_parser_parse_any_core (a_this);
|
|
+ if (status == CR_OK) {
|
|
+ ref++;
|
|
+ goto continue_parsing;
|
|
+ } else if (status == CR_PARSING_ERROR) {
|
|
+ status = CR_OK;
|
|
+ goto done;
|
|
+ } else {
|
|
+ goto error;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ done:
|
|
+ if (token) {
|
|
+ cr_token_destroy (token);
|
|
+ token = NULL;
|
|
+ }
|
|
+
|
|
+ if (status == CR_OK && ref)
|
|
+ return CR_OK;
|
|
+ error:
|
|
+ if (token) {
|
|
+ cr_token_destroy (token);
|
|
+ token = NULL;
|
|
+ }
|
|
+
|
|
+ cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
|
|
+
|
|
+ return status;
|
|
+}
|
|
+
|
|
+/**
|
|
+ *Parses an "any" as defined by the css core grammar in the
|
|
+ *css2 spec in chapter 4.1.
|
|
+ *any ::= [ IDENT | NUMBER | PERCENTAGE | DIMENSION | STRING
|
|
+ * | DELIM | URI | HASH | UNICODE-RANGE | INCLUDES
|
|
+ * | FUNCTION | DASHMATCH | '(' any* ')' | '[' any* ']' ] S*;
|
|
+ *
|
|
+ *@param a_this the current instance of #CRParser.
|
|
+ *@return CR_OK upon successfull completion, an error code otherwise.
|
|
+ */
|
|
+static enum CRStatus
|
|
+cr_parser_parse_any_core (CRParser * a_this)
|
|
+{
|
|
+ CRToken *token1 = NULL,
|
|
+ *token2 = NULL;
|
|
+ CRInputPos init_pos;
|
|
+ enum CRStatus status = CR_ERROR;
|
|
+
|
|
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ RECORD_INITIAL_POS (a_this, &init_pos);
|
|
+
|
|
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token1);
|
|
+
|
|
+ ENSURE_PARSING_COND (status == CR_OK && token1);
|
|
+
|
|
+ switch (token1->type) {
|
|
+ case IDENT_TK:
|
|
+ case NUMBER_TK:
|
|
+ case RGB_TK:
|
|
+ case PERCENTAGE_TK:
|
|
+ case DIMEN_TK:
|
|
+ case EMS_TK:
|
|
+ case EXS_TK:
|
|
+ case LENGTH_TK:
|
|
+ case ANGLE_TK:
|
|
+ case FREQ_TK:
|
|
+ case TIME_TK:
|
|
+ case STRING_TK:
|
|
+ case DELIM_TK:
|
|
+ case URI_TK:
|
|
+ case HASH_TK:
|
|
+ case UNICODERANGE_TK:
|
|
+ case INCLUDES_TK:
|
|
+ case DASHMATCH_TK:
|
|
+ case S_TK:
|
|
+ case COMMENT_TK:
|
|
+ case IMPORTANT_SYM_TK:
|
|
+ status = CR_OK;
|
|
+ break;
|
|
+ case FUNCTION_TK:
|
|
+ /*
|
|
+ *this case isn't specified by the spec but it
|
|
+ *does happen. So we have to handle it.
|
|
+ *We must consider function with parameters.
|
|
+ *We consider parameter as being an "any*" production.
|
|
+ */
|
|
+ do {
|
|
+ status = cr_parser_parse_any_core (a_this);
|
|
+ } while (status == CR_OK);
|
|
+
|
|
+ ENSURE_PARSING_COND (status == CR_PARSING_ERROR);
|
|
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr,
|
|
+ &token2);
|
|
+ ENSURE_PARSING_COND (status == CR_OK
|
|
+ && token2 && token2->type == PC_TK);
|
|
+ break;
|
|
+ case PO_TK:
|
|
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr,
|
|
+ &token2);
|
|
+ ENSURE_PARSING_COND (status == CR_OK && token2);
|
|
+
|
|
+ if (token2->type == PC_TK) {
|
|
+ cr_token_destroy (token2);
|
|
+ token2 = NULL;
|
|
+ goto done;
|
|
+ } else {
|
|
+ status = cr_tknzr_unget_token
|
|
+ (PRIVATE (a_this)->tknzr, token2);
|
|
+ token2 = NULL;
|
|
+ }
|
|
+
|
|
+ do {
|
|
+ status = cr_parser_parse_any_core (a_this);
|
|
+ } while (status == CR_OK);
|
|
+
|
|
+ ENSURE_PARSING_COND (status == CR_PARSING_ERROR);
|
|
+
|
|
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr,
|
|
+ &token2);
|
|
+ ENSURE_PARSING_COND (status == CR_OK
|
|
+ && token2 && token2->type == PC_TK);
|
|
+ status = CR_OK;
|
|
+ break;
|
|
+
|
|
+ case BO_TK:
|
|
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr,
|
|
+ &token2);
|
|
+ ENSURE_PARSING_COND (status == CR_OK && token2);
|
|
+
|
|
+ if (token2->type == BC_TK) {
|
|
+ cr_token_destroy (token2);
|
|
+ token2 = NULL;
|
|
+ goto done;
|
|
+ } else {
|
|
+ status = cr_tknzr_unget_token
|
|
+ (PRIVATE (a_this)->tknzr, token2);
|
|
+ token2 = NULL;
|
|
+ }
|
|
+
|
|
+ do {
|
|
+ status = cr_parser_parse_any_core (a_this);
|
|
+ } while (status == CR_OK);
|
|
+
|
|
+ ENSURE_PARSING_COND (status == CR_PARSING_ERROR);
|
|
+
|
|
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr,
|
|
+ &token2);
|
|
+ ENSURE_PARSING_COND (status == CR_OK
|
|
+ && token2 && token2->type == BC_TK);
|
|
+ status = CR_OK;
|
|
+ break;
|
|
+ default:
|
|
+ status = CR_PARSING_ERROR;
|
|
+ goto error;
|
|
+ }
|
|
+
|
|
+ done:
|
|
+ if (token1) {
|
|
+ cr_token_destroy (token1);
|
|
+ token1 = NULL;
|
|
+ }
|
|
+
|
|
+ if (token2) {
|
|
+ cr_token_destroy (token2);
|
|
+ token2 = NULL;
|
|
+ }
|
|
+
|
|
+ return CR_OK;
|
|
+
|
|
+ error:
|
|
+
|
|
+ if (token1) {
|
|
+ cr_token_destroy (token1);
|
|
+ token1 = NULL;
|
|
+ }
|
|
+
|
|
+ if (token2) {
|
|
+ cr_token_destroy (token2);
|
|
+ token2 = NULL;
|
|
+ }
|
|
+
|
|
+ cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
|
|
+ return status;
|
|
+}
|
|
+
|
|
+/**
|
|
+ *Parses an attribute selector as defined in the css2 spec in
|
|
+ *appendix D.1:
|
|
+ *attrib ::= '[' S* IDENT S* [ [ '=' | INCLUDES | DASHMATCH ] S*
|
|
+ * [ IDENT | STRING ] S* ]? ']'
|
|
+ *
|
|
+ *@param a_this the "this pointer" of the current instance of
|
|
+ *#CRParser .
|
|
+ *@param a_sel out parameter. The successfully parsed attribute selector.
|
|
+ *@return CR_OK upon successfull completion, an error code otherwise.
|
|
+ */
|
|
+static enum CRStatus
|
|
+cr_parser_parse_attribute_selector (CRParser * a_this,
|
|
+ CRAttrSel ** a_sel)
|
|
+{
|
|
+ enum CRStatus status = CR_OK;
|
|
+ CRInputPos init_pos;
|
|
+ CRToken *token = NULL;
|
|
+ CRAttrSel *result = NULL;
|
|
+ CRParsingLocation location = {0} ;
|
|
+
|
|
+ g_return_val_if_fail (a_this && a_sel, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ RECORD_INITIAL_POS (a_this, &init_pos);
|
|
+
|
|
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
|
|
+ ENSURE_PARSING_COND (status == CR_OK && token
|
|
+ && token->type == BO_TK);
|
|
+ cr_parsing_location_copy
|
|
+ (&location, &token->location) ;
|
|
+ cr_token_destroy (token);
|
|
+ token = NULL;
|
|
+
|
|
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
|
|
+
|
|
+ result = cr_attr_sel_new ();
|
|
+ if (!result) {
|
|
+ cr_utils_trace_info ("result failed") ;
|
|
+ status = CR_OUT_OF_MEMORY_ERROR ;
|
|
+ goto error ;
|
|
+ }
|
|
+ cr_parsing_location_copy (&result->location,
|
|
+ &location) ;
|
|
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
|
|
+ ENSURE_PARSING_COND (status == CR_OK
|
|
+ && token && token->type == IDENT_TK);
|
|
+
|
|
+ result->name = token->u.str;
|
|
+ token->u.str = NULL;
|
|
+ cr_token_destroy (token);
|
|
+ token = NULL;
|
|
+
|
|
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
|
|
+
|
|
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
|
|
+ ENSURE_PARSING_COND (status == CR_OK && token);
|
|
+
|
|
+ if (token->type == INCLUDES_TK) {
|
|
+ result->match_way = INCLUDES;
|
|
+ goto parse_right_part;
|
|
+ } else if (token->type == DASHMATCH_TK) {
|
|
+ result->match_way = DASHMATCH;
|
|
+ goto parse_right_part;
|
|
+ } else if (token->type == DELIM_TK && token->u.unichar == '=') {
|
|
+ result->match_way = EQUALS;
|
|
+ goto parse_right_part;
|
|
+ } else if (token->type == BC_TK) {
|
|
+ result->match_way = SET;
|
|
+ goto done;
|
|
+ }
|
|
+
|
|
+ parse_right_part:
|
|
+
|
|
+ if (token) {
|
|
+ cr_token_destroy (token);
|
|
+ token = NULL;
|
|
+ }
|
|
+
|
|
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
|
|
+
|
|
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
|
|
+ ENSURE_PARSING_COND (status == CR_OK && token);
|
|
+
|
|
+ if (token->type == IDENT_TK) {
|
|
+ result->value = token->u.str;
|
|
+ token->u.str = NULL;
|
|
+ } else if (token->type == STRING_TK) {
|
|
+ result->value = token->u.str;
|
|
+ token->u.str = NULL;
|
|
+ } else {
|
|
+ status = CR_PARSING_ERROR;
|
|
+ goto error;
|
|
+ }
|
|
+
|
|
+ if (token) {
|
|
+ cr_token_destroy (token);
|
|
+ token = NULL;
|
|
+ }
|
|
+
|
|
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
|
|
+
|
|
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
|
|
+
|
|
+ ENSURE_PARSING_COND (status == CR_OK && token
|
|
+ && token->type == BC_TK);
|
|
+ done:
|
|
+ if (token) {
|
|
+ cr_token_destroy (token);
|
|
+ token = NULL;
|
|
+ }
|
|
+
|
|
+ if (*a_sel) {
|
|
+ status = cr_attr_sel_append_attr_sel (*a_sel, result);
|
|
+ CHECK_PARSING_STATUS (status, FALSE);
|
|
+ } else {
|
|
+ *a_sel = result;
|
|
+ }
|
|
+
|
|
+ cr_parser_clear_errors (a_this);
|
|
+ return CR_OK;
|
|
+
|
|
+ error:
|
|
+
|
|
+ if (result) {
|
|
+ cr_attr_sel_destroy (result);
|
|
+ result = NULL;
|
|
+ }
|
|
+
|
|
+ if (token) {
|
|
+ cr_token_destroy (token);
|
|
+ token = NULL;
|
|
+ }
|
|
+
|
|
+ cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
|
|
+
|
|
+ return status;
|
|
+}
|
|
+
|
|
+/**
|
|
+ *Parses a "property" as specified by the css2 spec at [4.1.1]:
|
|
+ *property : IDENT S*;
|
|
+ *
|
|
+ *@param a_this the "this pointer" of the current instance of #CRParser.
|
|
+ *@param GString a_property out parameter. The parsed property without the
|
|
+ *trailing spaces. If *a_property is NULL, this function allocates a
|
|
+ *new instance of GString and set it content to the parsed property.
|
|
+ *If not, the property is just appended to a_property's previous content.
|
|
+ *In both cases, it is up to the caller to free a_property.
|
|
+ *@return CR_OK upon successfull completion, CR_PARSING_ERROR if the
|
|
+ *next construction was not a "property", or an error code.
|
|
+ */
|
|
+static enum CRStatus
|
|
+cr_parser_parse_property (CRParser * a_this,
|
|
+ CRString ** a_property)
|
|
+{
|
|
+ enum CRStatus status = CR_OK;
|
|
+ CRInputPos init_pos;
|
|
+
|
|
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
|
|
+ && PRIVATE (a_this)->tknzr
|
|
+ && a_property,
|
|
+ CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ RECORD_INITIAL_POS (a_this, &init_pos);
|
|
+
|
|
+ status = cr_parser_parse_ident (a_this, a_property);
|
|
+ CHECK_PARSING_STATUS (status, TRUE);
|
|
+
|
|
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
|
|
+
|
|
+ cr_parser_clear_errors (a_this);
|
|
+ return CR_OK;
|
|
+
|
|
+ error:
|
|
+
|
|
+ cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
|
|
+
|
|
+ return status;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_parser_parse_term:
|
|
+ *@a_term: out parameter. The successfully parsed term.
|
|
+ *
|
|
+ *Parses a "term" as defined in the css2 spec, appendix D.1:
|
|
+ *term ::= unary_operator? [NUMBER S* | PERCENTAGE S* | LENGTH S* |
|
|
+ *EMS S* | EXS S* | ANGLE S* | TIME S* | FREQ S* | function ] |
|
|
+ *STRING S* | IDENT S* | URI S* | RGB S* | UNICODERANGE S* | hexcolor
|
|
+ *
|
|
+ *TODO: handle parsing of 'RGB'
|
|
+ *
|
|
+ *Returns CR_OK upon successfull completion, an error code otherwise.
|
|
+ */
|
|
+enum CRStatus
|
|
+cr_parser_parse_term (CRParser * a_this, CRTerm ** a_term)
|
|
+{
|
|
+ enum CRStatus status = CR_PARSING_ERROR;
|
|
+ CRInputPos init_pos;
|
|
+ CRTerm *result = NULL;
|
|
+ CRTerm *param = NULL;
|
|
+ CRToken *token = NULL;
|
|
+ CRString *func_name = NULL;
|
|
+ CRParsingLocation location = {0} ;
|
|
+
|
|
+ g_return_val_if_fail (a_this && a_term, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ RECORD_INITIAL_POS (a_this, &init_pos);
|
|
+
|
|
+ result = cr_term_new ();
|
|
+
|
|
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr,
|
|
+ &token);
|
|
+ if (status != CR_OK || !token)
|
|
+ goto error;
|
|
+
|
|
+ cr_parsing_location_copy (&location, &token->location) ;
|
|
+ if (token->type == DELIM_TK && token->u.unichar == '+') {
|
|
+ result->unary_op = PLUS_UOP;
|
|
+ cr_token_destroy (token) ;
|
|
+ token = NULL ;
|
|
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
|
|
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr,
|
|
+ &token);
|
|
+ if (status != CR_OK || !token)
|
|
+ goto error;
|
|
+ } else if (token->type == DELIM_TK && token->u.unichar == '-') {
|
|
+ result->unary_op = MINUS_UOP;
|
|
+ cr_token_destroy (token) ;
|
|
+ token = NULL ;
|
|
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
|
|
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr,
|
|
+ &token);
|
|
+ if (status != CR_OK || !token)
|
|
+ goto error;
|
|
+ }
|
|
+
|
|
+ if (token->type == EMS_TK
|
|
+ || token->type == EXS_TK
|
|
+ || token->type == LENGTH_TK
|
|
+ || token->type == ANGLE_TK
|
|
+ || token->type == TIME_TK
|
|
+ || token->type == FREQ_TK
|
|
+ || token->type == PERCENTAGE_TK
|
|
+ || token->type == NUMBER_TK) {
|
|
+ status = cr_term_set_number (result, token->u.num);
|
|
+ CHECK_PARSING_STATUS (status, TRUE);
|
|
+ token->u.num = NULL;
|
|
+ status = CR_OK;
|
|
+ } else if (token && token->type == FUNCTION_TK) {
|
|
+ status = cr_tknzr_unget_token (PRIVATE (a_this)->tknzr,
|
|
+ token);
|
|
+ token = NULL;
|
|
+ status = cr_parser_parse_function (a_this, &func_name,
|
|
+ ¶m);
|
|
+
|
|
+ if (status == CR_OK) {
|
|
+ status = cr_term_set_function (result,
|
|
+ func_name,
|
|
+ param);
|
|
+ CHECK_PARSING_STATUS (status, TRUE);
|
|
+ }
|
|
+ } else if (token && token->type == STRING_TK) {
|
|
+ status = cr_term_set_string (result,
|
|
+ token->u.str);
|
|
+ CHECK_PARSING_STATUS (status, TRUE);
|
|
+ token->u.str = NULL;
|
|
+ } else if (token && token->type == IDENT_TK) {
|
|
+ status = cr_term_set_ident (result, token->u.str);
|
|
+ CHECK_PARSING_STATUS (status, TRUE);
|
|
+ token->u.str = NULL;
|
|
+ } else if (token && token->type == URI_TK) {
|
|
+ status = cr_term_set_uri (result, token->u.str);
|
|
+ CHECK_PARSING_STATUS (status, TRUE);
|
|
+ token->u.str = NULL;
|
|
+ } else if (token && token->type == RGB_TK) {
|
|
+ status = cr_term_set_rgb (result, token->u.rgb);
|
|
+ CHECK_PARSING_STATUS (status, TRUE);
|
|
+ token->u.rgb = NULL;
|
|
+ } else if (token && token->type == UNICODERANGE_TK) {
|
|
+ result->type = TERM_UNICODERANGE;
|
|
+ status = CR_PARSING_ERROR;
|
|
+ } else if (token && token->type == HASH_TK) {
|
|
+ status = cr_term_set_hash (result, token->u.str);
|
|
+ CHECK_PARSING_STATUS (status, TRUE);
|
|
+ token->u.str = NULL;
|
|
+ } else {
|
|
+ status = CR_PARSING_ERROR;
|
|
+ }
|
|
+
|
|
+ if (status != CR_OK) {
|
|
+ goto error;
|
|
+ }
|
|
+ cr_parsing_location_copy (&result->location,
|
|
+ &location) ;
|
|
+ *a_term = cr_term_append_term (*a_term, result);
|
|
+
|
|
+ result = NULL;
|
|
+
|
|
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
|
|
+
|
|
+ if (token) {
|
|
+ cr_token_destroy (token);
|
|
+ token = NULL;
|
|
+ }
|
|
+
|
|
+ cr_parser_clear_errors (a_this);
|
|
+ return CR_OK;
|
|
+
|
|
+ error:
|
|
+
|
|
+ if (result) {
|
|
+ cr_term_destroy (result);
|
|
+ result = NULL;
|
|
+ }
|
|
+
|
|
+ if (token) {
|
|
+ cr_token_destroy (token);
|
|
+ token = NULL;
|
|
+ }
|
|
+
|
|
+ if (param) {
|
|
+ cr_term_destroy (param);
|
|
+ param = NULL;
|
|
+ }
|
|
+
|
|
+ if (func_name) {
|
|
+ cr_string_destroy (func_name);
|
|
+ func_name = NULL;
|
|
+ }
|
|
+
|
|
+ cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
|
|
+
|
|
+ return status;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_parser_parse_simple_selector:
|
|
+ *@a_this: the "this pointer" of the current instance of #CRParser.
|
|
+ *@a_sel: out parameter. Is set to the successfully parsed simple
|
|
+ *selector.
|
|
+ *
|
|
+ *Parses a "simple_selector" as defined by the css2 spec in appendix D.1 :
|
|
+ *element_name? [ HASH | class | attrib | pseudo ]* S*
|
|
+ *and where pseudo is:
|
|
+ *pseudo ::= ':' [ IDENT | FUNCTION S* IDENT S* ')' ]
|
|
+ *
|
|
+ *Returns CR_OK upon successfull completion, an error code otherwise.
|
|
+ */
|
|
+static enum CRStatus
|
|
+cr_parser_parse_simple_selector (CRParser * a_this, CRSimpleSel ** a_sel)
|
|
+{
|
|
+ enum CRStatus status = CR_ERROR;
|
|
+ CRInputPos init_pos;
|
|
+ CRToken *token = NULL;
|
|
+ CRSimpleSel *sel = NULL;
|
|
+ CRAdditionalSel *add_sel_list = NULL;
|
|
+ gboolean found_sel = FALSE;
|
|
+ guint32 cur_char = 0;
|
|
+
|
|
+ g_return_val_if_fail (a_this && a_sel, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ RECORD_INITIAL_POS (a_this, &init_pos);
|
|
+
|
|
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
|
|
+ if (status != CR_OK)
|
|
+ goto error;
|
|
+
|
|
+ sel = cr_simple_sel_new ();
|
|
+ ENSURE_PARSING_COND (sel);
|
|
+
|
|
+ cr_parsing_location_copy
|
|
+ (&sel->location,
|
|
+ &token->location) ;
|
|
+
|
|
+ if (token && token->type == DELIM_TK
|
|
+ && token->u.unichar == '*') {
|
|
+ sel->type_mask |= UNIVERSAL_SELECTOR;
|
|
+ sel->name = cr_string_new_from_string ("*");
|
|
+ found_sel = TRUE;
|
|
+ } else if (token && token->type == IDENT_TK) {
|
|
+ sel->name = token->u.str;
|
|
+ sel->type_mask |= TYPE_SELECTOR;
|
|
+ token->u.str = NULL;
|
|
+ found_sel = TRUE;
|
|
+ } else {
|
|
+ status = cr_tknzr_unget_token
|
|
+ (PRIVATE (a_this)->tknzr,
|
|
+ token);
|
|
+ token = NULL;
|
|
+ }
|
|
+
|
|
+ if (token) {
|
|
+ cr_token_destroy (token);
|
|
+ token = NULL;
|
|
+ }
|
|
+
|
|
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
|
|
+
|
|
+ for (;;) {
|
|
+ if (token) {
|
|
+ cr_token_destroy (token);
|
|
+ token = NULL;
|
|
+ }
|
|
+
|
|
+ status = cr_tknzr_get_next_token
|
|
+ (PRIVATE (a_this)->tknzr,
|
|
+ &token);
|
|
+ if (status != CR_OK)
|
|
+ goto error;
|
|
+
|
|
+ if (token && token->type == HASH_TK) {
|
|
+ /*we parsed an attribute id */
|
|
+ CRAdditionalSel *add_sel = NULL;
|
|
+
|
|
+ add_sel = cr_additional_sel_new_with_type
|
|
+ (ID_ADD_SELECTOR);
|
|
+
|
|
+ add_sel->content.id_name = token->u.str;
|
|
+ token->u.str = NULL;
|
|
+
|
|
+ cr_parsing_location_copy
|
|
+ (&add_sel->location,
|
|
+ &token->location) ;
|
|
+ add_sel_list =
|
|
+ cr_additional_sel_append
|
|
+ (add_sel_list, add_sel);
|
|
+ found_sel = TRUE;
|
|
+ } else if (token && (token->type == DELIM_TK)
|
|
+ && (token->u.unichar == '.')) {
|
|
+ cr_token_destroy (token);
|
|
+ token = NULL;
|
|
+
|
|
+ status = cr_tknzr_get_next_token
|
|
+ (PRIVATE (a_this)->tknzr, &token);
|
|
+ if (status != CR_OK)
|
|
+ goto error;
|
|
+
|
|
+ if (token && token->type == IDENT_TK) {
|
|
+ CRAdditionalSel *add_sel = NULL;
|
|
+
|
|
+ add_sel = cr_additional_sel_new_with_type
|
|
+ (CLASS_ADD_SELECTOR);
|
|
+
|
|
+ add_sel->content.class_name = token->u.str;
|
|
+ token->u.str = NULL;
|
|
+
|
|
+ add_sel_list =
|
|
+ cr_additional_sel_append
|
|
+ (add_sel_list, add_sel);
|
|
+ found_sel = TRUE;
|
|
+
|
|
+ cr_parsing_location_copy
|
|
+ (&add_sel->location,
|
|
+ & token->location) ;
|
|
+ } else {
|
|
+ status = CR_PARSING_ERROR;
|
|
+ goto error;
|
|
+ }
|
|
+ } else if (token && token->type == BO_TK) {
|
|
+ CRAttrSel *attr_sel = NULL;
|
|
+ CRAdditionalSel *add_sel = NULL;
|
|
+
|
|
+ status = cr_tknzr_unget_token
|
|
+ (PRIVATE (a_this)->tknzr, token);
|
|
+ if (status != CR_OK)
|
|
+ goto error;
|
|
+ token = NULL;
|
|
+
|
|
+ status = cr_parser_parse_attribute_selector
|
|
+ (a_this, &attr_sel);
|
|
+ CHECK_PARSING_STATUS (status, FALSE);
|
|
+
|
|
+ add_sel = cr_additional_sel_new_with_type
|
|
+ (ATTRIBUTE_ADD_SELECTOR);
|
|
+
|
|
+ ENSURE_PARSING_COND (add_sel != NULL);
|
|
+
|
|
+ add_sel->content.attr_sel = attr_sel;
|
|
+
|
|
+ add_sel_list =
|
|
+ cr_additional_sel_append
|
|
+ (add_sel_list, add_sel);
|
|
+ found_sel = TRUE;
|
|
+ cr_parsing_location_copy
|
|
+ (&add_sel->location,
|
|
+ &attr_sel->location) ;
|
|
+ } else if (token && (token->type == DELIM_TK)
|
|
+ && (token->u.unichar == ':')) {
|
|
+ CRPseudo *pseudo = NULL;
|
|
+
|
|
+ /*try to parse a pseudo */
|
|
+
|
|
+ if (token) {
|
|
+ cr_token_destroy (token);
|
|
+ token = NULL;
|
|
+ }
|
|
+
|
|
+ pseudo = cr_pseudo_new ();
|
|
+
|
|
+ status = cr_tknzr_get_next_token
|
|
+ (PRIVATE (a_this)->tknzr, &token);
|
|
+ ENSURE_PARSING_COND (status == CR_OK && token);
|
|
+
|
|
+ cr_parsing_location_copy
|
|
+ (&pseudo->location,
|
|
+ &token->location) ;
|
|
+
|
|
+ if (token->type == IDENT_TK) {
|
|
+ pseudo->type = IDENT_PSEUDO;
|
|
+ pseudo->name = token->u.str;
|
|
+ token->u.str = NULL;
|
|
+ found_sel = TRUE;
|
|
+ } else if (token->type == FUNCTION_TK) {
|
|
+ pseudo->name = token->u.str;
|
|
+ token->u.str = NULL;
|
|
+ cr_parser_try_to_skip_spaces_and_comments
|
|
+ (a_this);
|
|
+ status = cr_parser_parse_ident
|
|
+ (a_this, &pseudo->extra);
|
|
+
|
|
+ ENSURE_PARSING_COND (status == CR_OK);
|
|
+ READ_NEXT_CHAR (a_this, &cur_char);
|
|
+ ENSURE_PARSING_COND (cur_char == ')');
|
|
+ pseudo->type = FUNCTION_PSEUDO;
|
|
+ found_sel = TRUE;
|
|
+ } else {
|
|
+ status = CR_PARSING_ERROR;
|
|
+ goto error;
|
|
+ }
|
|
+
|
|
+ if (status == CR_OK) {
|
|
+ CRAdditionalSel *add_sel = NULL;
|
|
+
|
|
+ add_sel = cr_additional_sel_new_with_type
|
|
+ (PSEUDO_CLASS_ADD_SELECTOR);
|
|
+
|
|
+ add_sel->content.pseudo = pseudo;
|
|
+ cr_parsing_location_copy
|
|
+ (&add_sel->location,
|
|
+ &pseudo->location) ;
|
|
+ add_sel_list =
|
|
+ cr_additional_sel_append
|
|
+ (add_sel_list, add_sel);
|
|
+ status = CR_OK;
|
|
+ }
|
|
+ } else {
|
|
+ status = cr_tknzr_unget_token
|
|
+ (PRIVATE (a_this)->tknzr, token);
|
|
+ token = NULL;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (status == CR_OK && found_sel == TRUE) {
|
|
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
|
|
+
|
|
+ sel->add_sel = add_sel_list;
|
|
+ add_sel_list = NULL;
|
|
+
|
|
+ if (*a_sel == NULL) {
|
|
+ *a_sel = sel;
|
|
+ } else {
|
|
+ cr_simple_sel_append_simple_sel (*a_sel, sel);
|
|
+ }
|
|
+
|
|
+ sel = NULL;
|
|
+
|
|
+ if (token) {
|
|
+ cr_token_destroy (token);
|
|
+ token = NULL;
|
|
+ }
|
|
+
|
|
+ cr_parser_clear_errors (a_this);
|
|
+ return CR_OK;
|
|
+ } else {
|
|
+ status = CR_PARSING_ERROR;
|
|
+ }
|
|
+
|
|
+ error:
|
|
+
|
|
+ if (token) {
|
|
+ cr_token_destroy (token);
|
|
+ token = NULL;
|
|
+ }
|
|
+
|
|
+ if (add_sel_list) {
|
|
+ cr_additional_sel_destroy (add_sel_list);
|
|
+ add_sel_list = NULL;
|
|
+ }
|
|
+
|
|
+ if (sel) {
|
|
+ cr_simple_sel_destroy (sel);
|
|
+ sel = NULL;
|
|
+ }
|
|
+
|
|
+ cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
|
|
+
|
|
+ return status;
|
|
+
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_parser_parse_simple_sels:
|
|
+ *@a_this: the this pointer of the current instance of #CRParser.
|
|
+ *@a_start: a pointer to the
|
|
+ *first chararcter of the successfully parsed
|
|
+ *string.
|
|
+ *@a_end: a pointer to the last character of the successfully parsed
|
|
+ *string.
|
|
+ *
|
|
+ *Parses a "selector" as defined by the css2 spec in appendix D.1:
|
|
+ *selector ::= simple_selector [ combinator simple_selector ]*
|
|
+ *
|
|
+ *Returns CR_OK upon successfull completion, an error code otherwise.
|
|
+ */
|
|
+static enum CRStatus
|
|
+cr_parser_parse_simple_sels (CRParser * a_this,
|
|
+ CRSimpleSel ** a_sel)
|
|
+{
|
|
+ enum CRStatus status = CR_ERROR;
|
|
+ CRInputPos init_pos;
|
|
+ CRSimpleSel *sel = NULL;
|
|
+ guint32 cur_char = 0;
|
|
+
|
|
+ g_return_val_if_fail (a_this
|
|
+ && PRIVATE (a_this)
|
|
+ && a_sel,
|
|
+ CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ RECORD_INITIAL_POS (a_this, &init_pos);
|
|
+
|
|
+ status = cr_parser_parse_simple_selector (a_this, &sel);
|
|
+ CHECK_PARSING_STATUS (status, FALSE);
|
|
+
|
|
+ *a_sel = cr_simple_sel_append_simple_sel (*a_sel, sel);
|
|
+
|
|
+ for (;;) {
|
|
+ guint32 next_char = 0;
|
|
+ enum Combinator comb = 0;
|
|
+
|
|
+ sel = NULL;
|
|
+
|
|
+ PEEK_NEXT_CHAR (a_this, &next_char);
|
|
+
|
|
+ if (next_char == '+') {
|
|
+ READ_NEXT_CHAR (a_this, &cur_char);
|
|
+ comb = COMB_PLUS;
|
|
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
|
|
+ } else if (next_char == '>') {
|
|
+ READ_NEXT_CHAR (a_this, &cur_char);
|
|
+ comb = COMB_GT;
|
|
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
|
|
+ } else {
|
|
+ comb = COMB_WS;
|
|
+ }
|
|
+
|
|
+ status = cr_parser_parse_simple_selector (a_this, &sel);
|
|
+ if (status != CR_OK)
|
|
+ break;
|
|
+
|
|
+ if (comb && sel) {
|
|
+ sel->combinator = comb;
|
|
+ comb = 0;
|
|
+ }
|
|
+ if (sel) {
|
|
+ *a_sel = cr_simple_sel_append_simple_sel (*a_sel,
|
|
+ sel) ;
|
|
+ }
|
|
+ }
|
|
+ cr_parser_clear_errors (a_this);
|
|
+ return CR_OK;
|
|
+
|
|
+ error:
|
|
+
|
|
+ cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
|
|
+
|
|
+ return status;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_parser_parse_selector:
|
|
+ *@a_this: the current instance of #CRParser.
|
|
+ *@a_selector: the parsed list of comma separated
|
|
+ *selectors.
|
|
+ *
|
|
+ *Parses a comma separated list of selectors.
|
|
+ *
|
|
+ *Returns CR_OK upon successful completion, an error
|
|
+ *code otherwise.
|
|
+ */
|
|
+static enum CRStatus
|
|
+cr_parser_parse_selector (CRParser * a_this,
|
|
+ CRSelector ** a_selector)
|
|
+{
|
|
+ enum CRStatus status = CR_OK;
|
|
+ CRInputPos init_pos;
|
|
+ guint32 cur_char = 0,
|
|
+ next_char = 0;
|
|
+ CRSimpleSel *simple_sels = NULL;
|
|
+ CRSelector *selector = NULL;
|
|
+
|
|
+ g_return_val_if_fail (a_this && a_selector, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ RECORD_INITIAL_POS (a_this, &init_pos);
|
|
+
|
|
+ status = cr_parser_parse_simple_sels (a_this, &simple_sels);
|
|
+ CHECK_PARSING_STATUS (status, FALSE);
|
|
+
|
|
+ if (simple_sels) {
|
|
+ selector = cr_selector_append_simple_sel
|
|
+ (selector, simple_sels);
|
|
+ if (selector) {
|
|
+ cr_parsing_location_copy
|
|
+ (&selector->location,
|
|
+ &simple_sels->location) ;
|
|
+ }
|
|
+ simple_sels = NULL;
|
|
+ } else {
|
|
+ status = CR_PARSING_ERROR ;
|
|
+ goto error ;
|
|
+ }
|
|
+
|
|
+ status = cr_tknzr_peek_char (PRIVATE (a_this)->tknzr,
|
|
+ &next_char);
|
|
+ if (status != CR_OK) {
|
|
+ if (status == CR_END_OF_INPUT_ERROR) {
|
|
+ status = CR_OK;
|
|
+ goto okay;
|
|
+ } else {
|
|
+ goto error;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (next_char == ',') {
|
|
+ for (;;) {
|
|
+ simple_sels = NULL;
|
|
+
|
|
+ status = cr_tknzr_peek_char (PRIVATE (a_this)->tknzr,
|
|
+ &next_char);
|
|
+ if (status != CR_OK) {
|
|
+ if (status == CR_END_OF_INPUT_ERROR) {
|
|
+ status = CR_OK;
|
|
+ break;
|
|
+ } else {
|
|
+ goto error;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (next_char != ',')
|
|
+ break;
|
|
+
|
|
+ /*consume the ',' char */
|
|
+ READ_NEXT_CHAR (a_this, &cur_char);
|
|
+
|
|
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
|
|
+
|
|
+ status = cr_parser_parse_simple_sels
|
|
+ (a_this, &simple_sels);
|
|
+
|
|
+ CHECK_PARSING_STATUS (status, FALSE);
|
|
+
|
|
+ if (simple_sels) {
|
|
+ selector =
|
|
+ cr_selector_append_simple_sel
|
|
+ (selector, simple_sels);
|
|
+
|
|
+ simple_sels = NULL;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ okay:
|
|
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
|
|
+
|
|
+ if (!*a_selector) {
|
|
+ *a_selector = selector;
|
|
+ } else {
|
|
+ *a_selector = cr_selector_append (*a_selector, selector);
|
|
+ }
|
|
+
|
|
+ selector = NULL;
|
|
+ return CR_OK;
|
|
+
|
|
+ error:
|
|
+
|
|
+ if (simple_sels) {
|
|
+ cr_simple_sel_destroy (simple_sels);
|
|
+ simple_sels = NULL;
|
|
+ }
|
|
+
|
|
+ if (selector) {
|
|
+ cr_selector_unref (selector);
|
|
+ selector = NULL;
|
|
+ }
|
|
+
|
|
+ cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
|
|
+
|
|
+ return status;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_parser_parse_function:
|
|
+ *@a_this: the "this pointer" of the current instance of #CRParser.
|
|
+ *
|
|
+ *@a_func_name: out parameter. The parsed function name
|
|
+ *@a_expr: out parameter. The successfully parsed term.
|
|
+ *
|
|
+ *Parses a "function" as defined in css spec at appendix D.1:
|
|
+ *function ::= FUNCTION S* expr ')' S*
|
|
+ *FUNCTION ::= ident'('
|
|
+ *
|
|
+ *Returns CR_OK upon successfull completion, an error code otherwise.
|
|
+ */
|
|
+static enum CRStatus
|
|
+cr_parser_parse_function (CRParser * a_this,
|
|
+ CRString ** a_func_name,
|
|
+ CRTerm ** a_expr)
|
|
+{
|
|
+ CRInputPos init_pos;
|
|
+ enum CRStatus status = CR_OK;
|
|
+ CRToken *token = NULL;
|
|
+ CRTerm *expr = NULL;
|
|
+
|
|
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
|
|
+ && a_func_name,
|
|
+ CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ RECORD_INITIAL_POS (a_this, &init_pos);
|
|
+
|
|
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
|
|
+ if (status != CR_OK)
|
|
+ goto error;
|
|
+
|
|
+ if (token && token->type == FUNCTION_TK) {
|
|
+ *a_func_name = token->u.str;
|
|
+ token->u.str = NULL;
|
|
+ } else {
|
|
+ status = CR_PARSING_ERROR;
|
|
+ goto error;
|
|
+ }
|
|
+ cr_token_destroy (token);
|
|
+ token = NULL;
|
|
+
|
|
+ cr_parser_try_to_skip_spaces_and_comments (a_this) ;
|
|
+
|
|
+ status = cr_parser_parse_expr (a_this, &expr);
|
|
+
|
|
+ CHECK_PARSING_STATUS (status, FALSE);
|
|
+
|
|
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
|
|
+ if (status != CR_OK)
|
|
+ goto error;
|
|
+
|
|
+ ENSURE_PARSING_COND (token && token->type == PC_TK);
|
|
+
|
|
+ cr_token_destroy (token);
|
|
+ token = NULL;
|
|
+
|
|
+ if (expr) {
|
|
+ *a_expr = cr_term_append_term (*a_expr, expr);
|
|
+ expr = NULL;
|
|
+ }
|
|
+
|
|
+ cr_parser_clear_errors (a_this);
|
|
+ return CR_OK;
|
|
+
|
|
+ error:
|
|
+
|
|
+ if (*a_func_name) {
|
|
+ cr_string_destroy (*a_func_name);
|
|
+ *a_func_name = NULL;
|
|
+ }
|
|
+
|
|
+ if (expr) {
|
|
+ cr_term_destroy (expr);
|
|
+ expr = NULL;
|
|
+ }
|
|
+
|
|
+ if (token) {
|
|
+ cr_token_destroy (token);
|
|
+
|
|
+ }
|
|
+
|
|
+ cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
|
|
+
|
|
+ return status;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_parser_parse_uri:
|
|
+ *@a_this: the current instance of #CRParser.
|
|
+ *@a_str: the successfully parsed url.
|
|
+ *
|
|
+ *Parses an uri as defined by the css spec [4.1.1]:
|
|
+ * URI ::= url\({w}{string}{w}\)
|
|
+ * |url\({w}([!#$%&*-~]|{nonascii}|{escape})*{w}\)
|
|
+ *
|
|
+ *Returns CR_OK upon successfull completion, an error code otherwise.
|
|
+ */
|
|
+static enum CRStatus
|
|
+cr_parser_parse_uri (CRParser * a_this, CRString ** a_str)
|
|
+{
|
|
+
|
|
+ enum CRStatus status = CR_PARSING_ERROR;
|
|
+
|
|
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
|
|
+ && PRIVATE (a_this)->tknzr, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ status = cr_tknzr_parse_token (PRIVATE (a_this)->tknzr,
|
|
+ URI_TK, NO_ET, a_str, NULL);
|
|
+ return status;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_parser_parse_string:
|
|
+ *@a_this: the current instance of #CRParser.
|
|
+ *@a_start: out parameter. Upon successfull completion,
|
|
+ *points to the beginning of the string, points to an undefined value
|
|
+ *otherwise.
|
|
+ *@a_end: out parameter. Upon successfull completion, points to
|
|
+ *the beginning of the string, points to an undefined value otherwise.
|
|
+ *
|
|
+ *Parses a string type as defined in css spec [4.1.1]:
|
|
+ *
|
|
+ *string ::= {string1}|{string2}
|
|
+ *string1 ::= \"([\t !#$%&(-~]|\\{nl}|\'|{nonascii}|{escape})*\"
|
|
+ *string2 ::= \'([\t !#$%&(-~]|\\{nl}|\"|{nonascii}|{escape})*\'
|
|
+ *
|
|
+ *Returns CR_OK upon successfull completion, an error code otherwise.
|
|
+ */
|
|
+static enum CRStatus
|
|
+cr_parser_parse_string (CRParser * a_this, CRString ** a_str)
|
|
+{
|
|
+ enum CRStatus status = CR_OK;
|
|
+
|
|
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
|
|
+ && PRIVATE (a_this)->tknzr
|
|
+ && a_str, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ status = cr_tknzr_parse_token (PRIVATE (a_this)->tknzr,
|
|
+ STRING_TK, NO_ET, a_str, NULL);
|
|
+ return status;
|
|
+}
|
|
+
|
|
+/**
|
|
+ *Parses an "ident" as defined in css spec [4.1.1]:
|
|
+ *ident ::= {nmstart}{nmchar}*
|
|
+ *
|
|
+ *@param a_this the currens instance of #CRParser.
|
|
+ *
|
|
+ *@param a_str a pointer to parsed ident. If *a_str is NULL,
|
|
+ *this function allocates a new instance of #CRString. If not,
|
|
+ *the function just appends the parsed string to the one passed.
|
|
+ *In both cases it is up to the caller to free *a_str.
|
|
+ *
|
|
+ *@return CR_OK upon successfull completion, an error code
|
|
+ *otherwise.
|
|
+ */
|
|
+static enum CRStatus
|
|
+cr_parser_parse_ident (CRParser * a_this, CRString ** a_str)
|
|
+{
|
|
+ enum CRStatus status = CR_OK;
|
|
+
|
|
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
|
|
+ && PRIVATE (a_this)->tknzr
|
|
+ && a_str, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ status = cr_tknzr_parse_token (PRIVATE (a_this)->tknzr,
|
|
+ IDENT_TK, NO_ET, a_str, NULL);
|
|
+ return status;
|
|
+}
|
|
+
|
|
+/**
|
|
+ *the next rule is ignored as well. This seems to be a bug
|
|
+ *Parses a stylesheet as defined in the css2 spec in appendix D.1:
|
|
+ *stylesheet ::= [ CHARSET_SYM S* STRING S* ';' ]?
|
|
+ * [S|CDO|CDC]* [ import [S|CDO|CDC]* ]*
|
|
+ * [ [ ruleset | media | page | font_face ] [S|CDO|CDC]* ]*
|
|
+ *
|
|
+ *TODO: Finish the code of this function. Think about splitting it into
|
|
+ *smaller functions.
|
|
+ *
|
|
+ *@param a_this the "this pointer" of the current instance of #CRParser.
|
|
+ *@param a_start out parameter. A pointer to the first character of
|
|
+ *the successfully parsed string.
|
|
+ *@param a_end out parameter. A pointer to the first character of
|
|
+ *the successfully parsed string.
|
|
+ *
|
|
+ *@return CR_OK upon successfull completion, an error code otherwise.
|
|
+ */
|
|
+static enum CRStatus
|
|
+cr_parser_parse_stylesheet (CRParser * a_this)
|
|
+{
|
|
+ enum CRStatus status = CR_OK;
|
|
+ CRInputPos init_pos;
|
|
+ CRToken *token = NULL;
|
|
+ CRString *charset = NULL;
|
|
+
|
|
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
|
|
+ && PRIVATE (a_this)->tknzr, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ RECORD_INITIAL_POS (a_this, &init_pos);
|
|
+
|
|
+ PRIVATE (a_this)->state = READY_STATE;
|
|
+
|
|
+ if (PRIVATE (a_this)->sac_handler
|
|
+ && PRIVATE (a_this)->sac_handler->start_document) {
|
|
+ PRIVATE (a_this)->sac_handler->start_document
|
|
+ (PRIVATE (a_this)->sac_handler);
|
|
+ }
|
|
+
|
|
+ parse_charset:
|
|
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
|
|
+
|
|
+ if (status == CR_END_OF_INPUT_ERROR)
|
|
+ goto done;
|
|
+ CHECK_PARSING_STATUS (status, TRUE);
|
|
+
|
|
+ if (token && token->type == CHARSET_SYM_TK) {
|
|
+ CRParsingLocation location = {0} ;
|
|
+ status = cr_tknzr_unget_token (PRIVATE (a_this)->tknzr,
|
|
+ token);
|
|
+ CHECK_PARSING_STATUS (status, TRUE);
|
|
+ token = NULL;
|
|
+
|
|
+ status = cr_parser_parse_charset (a_this,
|
|
+ &charset,
|
|
+ &location);
|
|
+
|
|
+ if (status == CR_OK && charset) {
|
|
+ if (PRIVATE (a_this)->sac_handler
|
|
+ && PRIVATE (a_this)->sac_handler->charset) {
|
|
+ PRIVATE (a_this)->sac_handler->charset
|
|
+ (PRIVATE (a_this)->sac_handler,
|
|
+ charset, &location);
|
|
+ }
|
|
+ } else if (status != CR_END_OF_INPUT_ERROR) {
|
|
+ status = cr_parser_parse_atrule_core (a_this);
|
|
+ CHECK_PARSING_STATUS (status, FALSE);
|
|
+ }
|
|
+
|
|
+ if (charset) {
|
|
+ cr_string_destroy (charset);
|
|
+ charset = NULL;
|
|
+ }
|
|
+ } else if (token
|
|
+ && (token->type == S_TK
|
|
+ || token->type == COMMENT_TK)) {
|
|
+ status = cr_tknzr_unget_token (PRIVATE (a_this)->tknzr,
|
|
+ token);
|
|
+ token = NULL;
|
|
+ CHECK_PARSING_STATUS (status, TRUE);
|
|
+
|
|
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
|
|
+ goto parse_charset ;
|
|
+ } else if (token) {
|
|
+ status = cr_tknzr_unget_token (PRIVATE (a_this)->tknzr,
|
|
+ token);
|
|
+ token = NULL;
|
|
+ CHECK_PARSING_STATUS (status, TRUE);
|
|
+ }
|
|
+
|
|
+/* parse_imports:*/
|
|
+ do {
|
|
+ if (token) {
|
|
+ cr_token_destroy (token);
|
|
+ token = NULL;
|
|
+ }
|
|
+ cr_parser_try_to_skip_spaces_and_comments (a_this) ;
|
|
+ status = cr_tknzr_get_next_token
|
|
+ (PRIVATE (a_this)->tknzr, &token);
|
|
+
|
|
+ if (status == CR_END_OF_INPUT_ERROR)
|
|
+ goto done;
|
|
+ CHECK_PARSING_STATUS (status, TRUE);
|
|
+ } while (token
|
|
+ && (token->type == S_TK
|
|
+ || token->type == CDO_TK || token->type == CDC_TK));
|
|
+
|
|
+ if (token) {
|
|
+ status = cr_tknzr_unget_token (PRIVATE (a_this)->tknzr,
|
|
+ token);
|
|
+ token = NULL;
|
|
+ }
|
|
+
|
|
+ for (;;) {
|
|
+ status = cr_tknzr_get_next_token
|
|
+ (PRIVATE (a_this)->tknzr, &token);
|
|
+ if (status == CR_END_OF_INPUT_ERROR)
|
|
+ goto done;
|
|
+ CHECK_PARSING_STATUS (status, TRUE);
|
|
+
|
|
+ if (token && token->type == IMPORT_SYM_TK) {
|
|
+ GList *media_list = NULL;
|
|
+ CRString *import_string = NULL;
|
|
+ CRParsingLocation location = {0} ;
|
|
+
|
|
+ status = cr_tknzr_unget_token
|
|
+ (PRIVATE (a_this)->tknzr, token);
|
|
+ token = NULL;
|
|
+ CHECK_PARSING_STATUS (status, TRUE);
|
|
+
|
|
+ status = cr_parser_parse_import (a_this,
|
|
+ &media_list,
|
|
+ &import_string,
|
|
+ &location);
|
|
+ if (status == CR_OK) {
|
|
+ if (import_string
|
|
+ && PRIVATE (a_this)->sac_handler
|
|
+ && PRIVATE (a_this)->sac_handler->import_style) {
|
|
+ PRIVATE (a_this)->sac_handler->import_style
|
|
+ (PRIVATE(a_this)->sac_handler,
|
|
+ media_list,
|
|
+ import_string,
|
|
+ NULL, &location) ;
|
|
+
|
|
+ if ((PRIVATE (a_this)->sac_handler->resolve_import == TRUE)) {
|
|
+ /*
|
|
+ *TODO: resolve the
|
|
+ *import rule.
|
|
+ */
|
|
+ }
|
|
+
|
|
+ if ((PRIVATE (a_this)->sac_handler->import_style_result)) {
|
|
+ PRIVATE (a_this)->sac_handler->import_style_result
|
|
+ (PRIVATE (a_this)->sac_handler,
|
|
+ media_list, import_string,
|
|
+ NULL, NULL);
|
|
+ }
|
|
+ }
|
|
+ } else if (status != CR_END_OF_INPUT_ERROR) {
|
|
+ if (PRIVATE (a_this)->sac_handler
|
|
+ && PRIVATE (a_this)->sac_handler->error) {
|
|
+ PRIVATE (a_this)->sac_handler->error
|
|
+ (PRIVATE (a_this)->sac_handler);
|
|
+ }
|
|
+ status = cr_parser_parse_atrule_core (a_this);
|
|
+ CHECK_PARSING_STATUS (status, TRUE) ;
|
|
+ } else {
|
|
+ goto error ;
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ *then, after calling the appropriate
|
|
+ *SAC handler, free
|
|
+ *the media_list and import_string.
|
|
+ */
|
|
+ if (media_list) {
|
|
+ GList *cur = NULL;
|
|
+
|
|
+ /*free the medium list */
|
|
+ for (cur = media_list; cur; cur = cur->next) {
|
|
+ if (cur->data) {
|
|
+ cr_string_destroy (cur->data);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ g_list_free (media_list);
|
|
+ media_list = NULL;
|
|
+ }
|
|
+
|
|
+ if (import_string) {
|
|
+ cr_string_destroy (import_string);
|
|
+ import_string = NULL;
|
|
+ }
|
|
+
|
|
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
|
|
+ } else if (token
|
|
+ && (token->type == S_TK
|
|
+ || token->type == CDO_TK
|
|
+ || token->type == CDC_TK)) {
|
|
+ status = cr_tknzr_unget_token
|
|
+ (PRIVATE (a_this)->tknzr, token);
|
|
+ token = NULL;
|
|
+
|
|
+ do {
|
|
+ if (token) {
|
|
+ cr_token_destroy (token);
|
|
+ token = NULL;
|
|
+ }
|
|
+
|
|
+ status = cr_tknzr_get_next_token
|
|
+ (PRIVATE (a_this)->tknzr, &token);
|
|
+
|
|
+ if (status == CR_END_OF_INPUT_ERROR)
|
|
+ goto done;
|
|
+ CHECK_PARSING_STATUS (status, TRUE);
|
|
+ } while (token
|
|
+ && (token->type == S_TK
|
|
+ || token->type == CDO_TK
|
|
+ || token->type == CDC_TK));
|
|
+ } else {
|
|
+ if (token) {
|
|
+ status = cr_tknzr_unget_token
|
|
+ (PRIVATE (a_this)->tknzr, token);
|
|
+ token = NULL;
|
|
+ }
|
|
+ goto parse_ruleset_and_others;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ parse_ruleset_and_others:
|
|
+
|
|
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
|
|
+
|
|
+ for (;;) {
|
|
+ status = cr_tknzr_get_next_token
|
|
+ (PRIVATE (a_this)->tknzr, &token);
|
|
+ if (status == CR_END_OF_INPUT_ERROR)
|
|
+ goto done;
|
|
+ CHECK_PARSING_STATUS (status, TRUE);
|
|
+
|
|
+ if (token
|
|
+ && (token->type == S_TK
|
|
+ || token->type == CDO_TK || token->type == CDC_TK)) {
|
|
+ status = cr_tknzr_unget_token
|
|
+ (PRIVATE (a_this)->tknzr, token);
|
|
+ token = NULL;
|
|
+
|
|
+ do {
|
|
+ if (token) {
|
|
+ cr_token_destroy (token);
|
|
+ token = NULL;
|
|
+ }
|
|
+
|
|
+ cr_parser_try_to_skip_spaces_and_comments
|
|
+ (a_this);
|
|
+ status = cr_tknzr_get_next_token
|
|
+ (PRIVATE (a_this)->tknzr, &token);
|
|
+ } while (token
|
|
+ && (token->type == S_TK
|
|
+ || token->type == COMMENT_TK
|
|
+ || token->type == CDO_TK
|
|
+ || token->type == CDC_TK));
|
|
+ if (token) {
|
|
+ cr_tknzr_unget_token
|
|
+ (PRIVATE (a_this)->tknzr, token);
|
|
+ token = NULL;
|
|
+ }
|
|
+ } else if (token
|
|
+ && (token->type == HASH_TK
|
|
+ || (token->type == DELIM_TK
|
|
+ && token->u.unichar == '.')
|
|
+ || (token->type == DELIM_TK
|
|
+ && token->u.unichar == ':')
|
|
+ || (token->type == DELIM_TK
|
|
+ && token->u.unichar == '*')
|
|
+ || (token->type == BO_TK)
|
|
+ || token->type == IDENT_TK)) {
|
|
+ /*
|
|
+ *Try to parse a CSS2 ruleset.
|
|
+ *if the parsing fails, try to parse
|
|
+ *a css core ruleset.
|
|
+ */
|
|
+ status = cr_tknzr_unget_token
|
|
+ (PRIVATE (a_this)->tknzr, token);
|
|
+ CHECK_PARSING_STATUS (status, TRUE);
|
|
+ token = NULL;
|
|
+
|
|
+ status = cr_parser_parse_ruleset (a_this);
|
|
+
|
|
+ if (status == CR_OK) {
|
|
+ continue;
|
|
+ } else {
|
|
+ if (PRIVATE (a_this)->sac_handler
|
|
+ && PRIVATE (a_this)->sac_handler->error) {
|
|
+ PRIVATE (a_this)->sac_handler->
|
|
+ error
|
|
+ (PRIVATE (a_this)->
|
|
+ sac_handler);
|
|
+ }
|
|
+
|
|
+ status = cr_parser_parse_ruleset_core
|
|
+ (a_this);
|
|
+
|
|
+ if (status == CR_OK) {
|
|
+ continue;
|
|
+ } else {
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ } else if (token && token->type == MEDIA_SYM_TK) {
|
|
+ status = cr_tknzr_unget_token
|
|
+ (PRIVATE (a_this)->tknzr, token);
|
|
+ CHECK_PARSING_STATUS (status, TRUE);
|
|
+ token = NULL;
|
|
+
|
|
+ status = cr_parser_parse_media (a_this);
|
|
+ if (status == CR_OK) {
|
|
+ continue;
|
|
+ } else {
|
|
+ if (PRIVATE (a_this)->sac_handler
|
|
+ && PRIVATE (a_this)->sac_handler->error) {
|
|
+ PRIVATE (a_this)->sac_handler->
|
|
+ error
|
|
+ (PRIVATE (a_this)->
|
|
+ sac_handler);
|
|
+ }
|
|
+
|
|
+ status = cr_parser_parse_atrule_core (a_this);
|
|
+
|
|
+ if (status == CR_OK) {
|
|
+ continue;
|
|
+ } else {
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ } else if (token && token->type == PAGE_SYM_TK) {
|
|
+ status = cr_tknzr_unget_token
|
|
+ (PRIVATE (a_this)->tknzr, token);
|
|
+ CHECK_PARSING_STATUS (status, TRUE);
|
|
+ token = NULL;
|
|
+ status = cr_parser_parse_page (a_this);
|
|
+
|
|
+ if (status == CR_OK) {
|
|
+ continue;
|
|
+ } else {
|
|
+ if (PRIVATE (a_this)->sac_handler
|
|
+ && PRIVATE (a_this)->sac_handler->error) {
|
|
+ PRIVATE (a_this)->sac_handler->
|
|
+ error
|
|
+ (PRIVATE (a_this)->
|
|
+ sac_handler);
|
|
+ }
|
|
+
|
|
+ status = cr_parser_parse_atrule_core (a_this);
|
|
+
|
|
+ if (status == CR_OK) {
|
|
+ continue;
|
|
+ } else {
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ } else if (token && token->type == FONT_FACE_SYM_TK) {
|
|
+ status = cr_tknzr_unget_token
|
|
+ (PRIVATE (a_this)->tknzr, token);
|
|
+ CHECK_PARSING_STATUS (status, TRUE);
|
|
+ token = NULL;
|
|
+ status = cr_parser_parse_font_face (a_this);
|
|
+
|
|
+ if (status == CR_OK) {
|
|
+ continue;
|
|
+ } else {
|
|
+ if (PRIVATE (a_this)->sac_handler
|
|
+ && PRIVATE (a_this)->sac_handler->error) {
|
|
+ PRIVATE (a_this)->sac_handler->
|
|
+ error
|
|
+ (PRIVATE (a_this)->
|
|
+ sac_handler);
|
|
+ }
|
|
+
|
|
+ status = cr_parser_parse_atrule_core (a_this);
|
|
+
|
|
+ if (status == CR_OK) {
|
|
+ continue;
|
|
+ } else {
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ } else {
|
|
+ status = cr_tknzr_unget_token
|
|
+ (PRIVATE (a_this)->tknzr, token);
|
|
+ CHECK_PARSING_STATUS (status, TRUE);
|
|
+ token = NULL;
|
|
+ status = cr_parser_parse_statement_core (a_this);
|
|
+
|
|
+ if (status == CR_OK) {
|
|
+ continue;
|
|
+ } else {
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ done:
|
|
+ if (token) {
|
|
+ cr_token_destroy (token);
|
|
+ token = NULL;
|
|
+ }
|
|
+
|
|
+ if (status == CR_END_OF_INPUT_ERROR || status == CR_OK) {
|
|
+
|
|
+ if (PRIVATE (a_this)->sac_handler
|
|
+ && PRIVATE (a_this)->sac_handler->end_document) {
|
|
+ PRIVATE (a_this)->sac_handler->end_document
|
|
+ (PRIVATE (a_this)->sac_handler);
|
|
+ }
|
|
+
|
|
+ return CR_OK;
|
|
+ }
|
|
+
|
|
+ cr_parser_push_error
|
|
+ (a_this, (const guchar *) "could not recognize next production", CR_ERROR);
|
|
+
|
|
+ if (PRIVATE (a_this)->sac_handler
|
|
+ && PRIVATE (a_this)->sac_handler->unrecoverable_error) {
|
|
+ PRIVATE (a_this)->sac_handler->
|
|
+ unrecoverable_error (PRIVATE (a_this)->sac_handler);
|
|
+ }
|
|
+
|
|
+ cr_parser_dump_err_stack (a_this, TRUE);
|
|
+
|
|
+ return status;
|
|
+
|
|
+ error:
|
|
+
|
|
+ if (token) {
|
|
+ cr_token_destroy (token);
|
|
+ token = NULL;
|
|
+ }
|
|
+
|
|
+ if (PRIVATE (a_this)->sac_handler
|
|
+ && PRIVATE (a_this)->sac_handler->unrecoverable_error) {
|
|
+ PRIVATE (a_this)->sac_handler->
|
|
+ unrecoverable_error (PRIVATE (a_this)->sac_handler);
|
|
+ }
|
|
+
|
|
+ cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
|
|
+
|
|
+ return status;
|
|
+}
|
|
+
|
|
+/****************************************
|
|
+ *Public CRParser Methods
|
|
+ ****************************************/
|
|
+
|
|
+/**
|
|
+ * cr_parser_new:
|
|
+ * @a_tknzr: the tokenizer to use for the parsing.
|
|
+ *
|
|
+ *Creates a new parser to parse data
|
|
+ *coming the input stream given in parameter.
|
|
+ *
|
|
+ *Returns the newly created instance of #CRParser,
|
|
+ *or NULL if an error occurred.
|
|
+ */
|
|
+CRParser *
|
|
+cr_parser_new (CRTknzr * a_tknzr)
|
|
+{
|
|
+ CRParser *result = NULL;
|
|
+ enum CRStatus status = CR_OK;
|
|
+
|
|
+ result = g_malloc0 (sizeof (CRParser));
|
|
+
|
|
+ PRIVATE (result) = g_malloc0 (sizeof (CRParserPriv));
|
|
+
|
|
+ if (a_tknzr) {
|
|
+ status = cr_parser_set_tknzr (result, a_tknzr);
|
|
+ }
|
|
+
|
|
+ g_return_val_if_fail (status == CR_OK, NULL);
|
|
+
|
|
+ return result;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_parser_new_from_buf:
|
|
+ *@a_buf: the buffer to parse.
|
|
+ *@a_len: the length of the data in the buffer.
|
|
+ *@a_enc: the encoding of the input buffer a_buf.
|
|
+ *@a_free_buf: if set to TRUE, a_buf will be freed
|
|
+ *during the destruction of the newly built instance
|
|
+ *of #CRParser. If set to FALSE, it is up to the caller to
|
|
+ *eventually free it.
|
|
+ *
|
|
+ *Instanciates a new parser from a memory buffer.
|
|
+ *
|
|
+ *Returns the newly built parser, or NULL if an error arises.
|
|
+ */
|
|
+CRParser *
|
|
+cr_parser_new_from_buf (guchar * a_buf,
|
|
+ gulong a_len,
|
|
+ enum CREncoding a_enc,
|
|
+ gboolean a_free_buf)
|
|
+{
|
|
+ CRParser *result = NULL;
|
|
+ CRInput *input = NULL;
|
|
+
|
|
+ g_return_val_if_fail (a_buf && a_len, NULL);
|
|
+
|
|
+ input = cr_input_new_from_buf (a_buf, a_len, a_enc, a_free_buf);
|
|
+ g_return_val_if_fail (input, NULL);
|
|
+
|
|
+ result = cr_parser_new_from_input (input);
|
|
+ if (!result) {
|
|
+ cr_input_destroy (input);
|
|
+ input = NULL;
|
|
+ return NULL;
|
|
+ }
|
|
+ return result;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_parser_new_from_input:
|
|
+ * @a_input: the parser input stream to use.
|
|
+ *
|
|
+ * Returns a newly built parser input.
|
|
+ */
|
|
+CRParser *
|
|
+cr_parser_new_from_input (CRInput * a_input)
|
|
+{
|
|
+ CRParser *result = NULL;
|
|
+ CRTknzr *tokenizer = NULL;
|
|
+
|
|
+ if (a_input) {
|
|
+ tokenizer = cr_tknzr_new (a_input);
|
|
+ g_return_val_if_fail (tokenizer, NULL);
|
|
+ }
|
|
+
|
|
+ result = cr_parser_new (tokenizer);
|
|
+ g_return_val_if_fail (result, NULL);
|
|
+
|
|
+ return result;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_parser_new_from_file:
|
|
+ * @a_file_uri: the uri of the file to parse.
|
|
+ * @a_enc: the file encoding to use.
|
|
+ *
|
|
+ * Returns the newly built parser.
|
|
+ */
|
|
+CRParser *
|
|
+cr_parser_new_from_file (const guchar * a_file_uri, enum CREncoding a_enc)
|
|
+{
|
|
+ CRParser *result = NULL;
|
|
+ CRTknzr *tokenizer = NULL;
|
|
+
|
|
+ tokenizer = cr_tknzr_new_from_uri (a_file_uri, a_enc);
|
|
+ if (!tokenizer) {
|
|
+ cr_utils_trace_info ("Could not open input file");
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
+ result = cr_parser_new (tokenizer);
|
|
+ g_return_val_if_fail (result, NULL);
|
|
+ return result;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_parser_set_sac_handler:
|
|
+ *@a_this: the "this pointer" of the current instance of #CRParser.
|
|
+ *@a_handler: the handler to set.
|
|
+ *
|
|
+ *Sets a SAC document handler to the parser.
|
|
+ *
|
|
+ *Returns CR_OK upon successfull completion, an error code otherwise.
|
|
+ */
|
|
+enum CRStatus
|
|
+cr_parser_set_sac_handler (CRParser * a_this, CRDocHandler * a_handler)
|
|
+{
|
|
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ if (PRIVATE (a_this)->sac_handler) {
|
|
+ cr_doc_handler_unref (PRIVATE (a_this)->sac_handler);
|
|
+ }
|
|
+
|
|
+ PRIVATE (a_this)->sac_handler = a_handler;
|
|
+ cr_doc_handler_ref (a_handler);
|
|
+
|
|
+ return CR_OK;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_parser_get_sac_handler:
|
|
+ *@a_this: the "this pointer" of the current instance of
|
|
+ *#CRParser.
|
|
+ *@a_handler: out parameter. The returned handler.
|
|
+ *
|
|
+ *Gets the SAC document handler.
|
|
+ *
|
|
+ *Returns CR_OK upon successfull completion, an error code
|
|
+ *otherwise.
|
|
+ */
|
|
+enum CRStatus
|
|
+cr_parser_get_sac_handler (CRParser * a_this, CRDocHandler ** a_handler)
|
|
+{
|
|
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ *a_handler = PRIVATE (a_this)->sac_handler;
|
|
+
|
|
+ return CR_OK;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_parser_set_default_sac_handler:
|
|
+ *@a_this: a pointer to the current instance of #CRParser.
|
|
+ *
|
|
+ *Sets the SAC handler associated to the current instance
|
|
+ *of #CRParser to the default SAC handler.
|
|
+ *
|
|
+ *Returns CR_OK upon successfull completion, an error code otherwise.
|
|
+ */
|
|
+enum CRStatus
|
|
+cr_parser_set_default_sac_handler (CRParser * a_this)
|
|
+{
|
|
+ CRDocHandler *default_sac_handler = NULL;
|
|
+ enum CRStatus status = CR_ERROR;
|
|
+
|
|
+ g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ default_sac_handler = cr_doc_handler_new ();
|
|
+
|
|
+ cr_doc_handler_set_default_sac_handler (default_sac_handler);
|
|
+
|
|
+ status = cr_parser_set_sac_handler (a_this, default_sac_handler);
|
|
+
|
|
+ if (status != CR_OK) {
|
|
+ cr_doc_handler_destroy (default_sac_handler);
|
|
+ default_sac_handler = NULL;
|
|
+ }
|
|
+
|
|
+ return status;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_parser_set_use_core_grammar:
|
|
+ * @a_this: the current instance of #CRParser.
|
|
+ * @a_use_core_grammar: where to parse against the css core grammar.
|
|
+ *
|
|
+ * Returns CR_OK upon succesful completion, an error code otherwise.
|
|
+ */
|
|
+enum CRStatus
|
|
+cr_parser_set_use_core_grammar (CRParser * a_this,
|
|
+ gboolean a_use_core_grammar)
|
|
+{
|
|
+ g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ PRIVATE (a_this)->use_core_grammar = a_use_core_grammar;
|
|
+
|
|
+ return CR_OK;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_parser_get_use_core_grammar:
|
|
+ * @a_this: the current instance of #CRParser.
|
|
+ * @a_use_core_grammar: wether to use the core grammar or not.
|
|
+ *
|
|
+ * Returns CR_OK upon succesful completion, an error code otherwise.
|
|
+ */
|
|
+enum CRStatus
|
|
+cr_parser_get_use_core_grammar (CRParser const * a_this,
|
|
+ gboolean * a_use_core_grammar)
|
|
+{
|
|
+ g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ *a_use_core_grammar = PRIVATE (a_this)->use_core_grammar;
|
|
+
|
|
+ return CR_OK;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_parser_parse_file:
|
|
+ *@a_this: a pointer to the current instance of #CRParser.
|
|
+ *@a_file_uri: the uri to the file to load. For the time being,
|
|
+ *@a_enc: the encoding of the file to parse.
|
|
+ *only local files are supported.
|
|
+ *
|
|
+ *Parses a the given in parameter.
|
|
+ *
|
|
+ *Returns CR_OK upon successfull completion, an error code otherwise.
|
|
+ */
|
|
+enum CRStatus
|
|
+cr_parser_parse_file (CRParser * a_this,
|
|
+ const guchar * a_file_uri, enum CREncoding a_enc)
|
|
+{
|
|
+ enum CRStatus status = CR_ERROR;
|
|
+ CRTknzr *tknzr = NULL;
|
|
+
|
|
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
|
|
+ && a_file_uri, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ tknzr = cr_tknzr_new_from_uri (a_file_uri, a_enc);
|
|
+
|
|
+ g_return_val_if_fail (tknzr != NULL, CR_ERROR);
|
|
+
|
|
+ status = cr_parser_set_tknzr (a_this, tknzr);
|
|
+ g_return_val_if_fail (status == CR_OK, CR_ERROR);
|
|
+
|
|
+ status = cr_parser_parse (a_this);
|
|
+
|
|
+ return status;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_parser_parse_expr:
|
|
+ * @a_this: the current instance of #CRParser.
|
|
+ * @a_expr: out parameter. the parsed expression.
|
|
+ *
|
|
+ *Parses an expression as defined by the css2 spec in appendix
|
|
+ *D.1:
|
|
+ *expr: term [ operator term ]*
|
|
+ *
|
|
+ *
|
|
+ * Returns CR_OK upon successful completion, an error code otherwise.
|
|
+ */
|
|
+enum CRStatus
|
|
+cr_parser_parse_expr (CRParser * a_this, CRTerm ** a_expr)
|
|
+{
|
|
+ enum CRStatus status = CR_ERROR;
|
|
+ CRInputPos init_pos;
|
|
+ CRTerm *expr = NULL,
|
|
+ *expr2 = NULL;
|
|
+ guchar next_byte = 0;
|
|
+ gulong nb_terms = 0;
|
|
+
|
|
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
|
|
+ && a_expr, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ RECORD_INITIAL_POS (a_this, &init_pos);
|
|
+
|
|
+ status = cr_parser_parse_term (a_this, &expr);
|
|
+
|
|
+ CHECK_PARSING_STATUS (status, FALSE);
|
|
+
|
|
+ for (;;) {
|
|
+ guchar operator = 0;
|
|
+
|
|
+ status = cr_tknzr_peek_byte (PRIVATE (a_this)->tknzr,
|
|
+ 1, &next_byte);
|
|
+ if (status != CR_OK) {
|
|
+ if (status == CR_END_OF_INPUT_ERROR) {
|
|
+ /*
|
|
+ if (!nb_terms)
|
|
+ {
|
|
+ goto error ;
|
|
+ }
|
|
+ */
|
|
+ status = CR_OK;
|
|
+ break;
|
|
+ } else {
|
|
+ goto error;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (next_byte == '/' || next_byte == ',') {
|
|
+ READ_NEXT_BYTE (a_this, &operator);
|
|
+ }
|
|
+
|
|
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
|
|
+
|
|
+ status = cr_parser_parse_term (a_this, &expr2);
|
|
+
|
|
+ if (status != CR_OK || expr2 == NULL) {
|
|
+ status = CR_OK;
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ switch (operator) {
|
|
+ case '/':
|
|
+ expr2->the_operator = DIVIDE;
|
|
+ break;
|
|
+ case ',':
|
|
+ expr2->the_operator = COMMA;
|
|
+
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ expr = cr_term_append_term (expr, expr2);
|
|
+ expr2 = NULL;
|
|
+ operator = 0;
|
|
+ nb_terms++;
|
|
+ }
|
|
+
|
|
+ if (status == CR_OK) {
|
|
+ *a_expr = cr_term_append_term (*a_expr, expr);
|
|
+ expr = NULL;
|
|
+
|
|
+ cr_parser_clear_errors (a_this);
|
|
+ return CR_OK;
|
|
+ }
|
|
+
|
|
+ error:
|
|
+
|
|
+ if (expr) {
|
|
+ cr_term_destroy (expr);
|
|
+ expr = NULL;
|
|
+ }
|
|
+
|
|
+ if (expr2) {
|
|
+ cr_term_destroy (expr2);
|
|
+ expr2 = NULL;
|
|
+ }
|
|
+
|
|
+ cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
|
|
+
|
|
+ return status;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_parser_parse_prio:
|
|
+ *@a_this: the current instance of #CRParser.
|
|
+ *@a_prio: a string representing the priority.
|
|
+ *Today, only "!important" is returned as only this
|
|
+ *priority is defined by css2.
|
|
+ *
|
|
+ *Parses a declaration priority as defined by
|
|
+ *the css2 grammar in appendix C:
|
|
+ *prio: IMPORTANT_SYM S*
|
|
+ *
|
|
+ * Returns CR_OK upon successful completion, an error code otherwise.
|
|
+ */
|
|
+enum CRStatus
|
|
+cr_parser_parse_prio (CRParser * a_this, CRString ** a_prio)
|
|
+{
|
|
+ enum CRStatus status = CR_ERROR;
|
|
+ CRInputPos init_pos;
|
|
+ CRToken *token = NULL;
|
|
+
|
|
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
|
|
+ && a_prio
|
|
+ && *a_prio == NULL, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ RECORD_INITIAL_POS (a_this, &init_pos);
|
|
+
|
|
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
|
|
+ if (status == CR_END_OF_INPUT_ERROR) {
|
|
+ goto error;
|
|
+ }
|
|
+ ENSURE_PARSING_COND (status == CR_OK
|
|
+ && token && token->type == IMPORTANT_SYM_TK);
|
|
+
|
|
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
|
|
+ *a_prio = cr_string_new_from_string ("!important");
|
|
+ cr_token_destroy (token);
|
|
+ token = NULL;
|
|
+ return CR_OK;
|
|
+
|
|
+ error:
|
|
+ if (token) {
|
|
+ cr_token_destroy (token);
|
|
+ token = NULL;
|
|
+ }
|
|
+ cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
|
|
+
|
|
+ return status;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_parser_parse_declaration:
|
|
+ *@a_this: the "this pointer" of the current instance of #CRParser.
|
|
+ *@a_property: the successfully parsed property. The caller
|
|
+ * *must* free the returned pointer.
|
|
+ *@a_expr: the expression that represents the attribute value.
|
|
+ *The caller *must* free the returned pointer.
|
|
+ *
|
|
+ *TODO: return the parsed priority, so that
|
|
+ *upper layers can take benefit from it.
|
|
+ *Parses a "declaration" as defined by the css2 spec in appendix D.1:
|
|
+ *declaration ::= [property ':' S* expr prio?]?
|
|
+ *
|
|
+ *Returns CR_OK upon successfull completion, an error code otherwise.
|
|
+ */
|
|
+enum CRStatus
|
|
+cr_parser_parse_declaration (CRParser * a_this,
|
|
+ CRString ** a_property,
|
|
+ CRTerm ** a_expr, gboolean * a_important)
|
|
+{
|
|
+ enum CRStatus status = CR_ERROR;
|
|
+ CRInputPos init_pos;
|
|
+ guint32 cur_char = 0;
|
|
+ CRTerm *expr = NULL;
|
|
+ CRString *prio = NULL;
|
|
+
|
|
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
|
|
+ && a_property && a_expr
|
|
+ && a_important, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ RECORD_INITIAL_POS (a_this, &init_pos);
|
|
+
|
|
+ status = cr_parser_parse_property (a_this, a_property);
|
|
+
|
|
+ if (status == CR_END_OF_INPUT_ERROR)
|
|
+ goto error;
|
|
+
|
|
+ CHECK_PARSING_STATUS_ERR
|
|
+ (a_this, status, FALSE,
|
|
+ (const guchar *) "while parsing declaration: next property is malformed",
|
|
+ CR_SYNTAX_ERROR);
|
|
+
|
|
+ READ_NEXT_CHAR (a_this, &cur_char);
|
|
+
|
|
+ if (cur_char != ':') {
|
|
+ status = CR_PARSING_ERROR;
|
|
+ cr_parser_push_error
|
|
+ (a_this,
|
|
+ (const guchar *) "while parsing declaration: this char must be ':'",
|
|
+ CR_SYNTAX_ERROR);
|
|
+ goto error;
|
|
+ }
|
|
+
|
|
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
|
|
+
|
|
+ status = cr_parser_parse_expr (a_this, &expr);
|
|
+
|
|
+ CHECK_PARSING_STATUS_ERR
|
|
+ (a_this, status, FALSE,
|
|
+ (const guchar *) "while parsing declaration: next expression is malformed",
|
|
+ CR_SYNTAX_ERROR);
|
|
+
|
|
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
|
|
+ status = cr_parser_parse_prio (a_this, &prio);
|
|
+ if (prio) {
|
|
+ cr_string_destroy (prio);
|
|
+ prio = NULL;
|
|
+ *a_important = TRUE;
|
|
+ } else {
|
|
+ *a_important = FALSE;
|
|
+ }
|
|
+ if (*a_expr) {
|
|
+ cr_term_append_term (*a_expr, expr);
|
|
+ expr = NULL;
|
|
+ } else {
|
|
+ *a_expr = expr;
|
|
+ expr = NULL;
|
|
+ }
|
|
+
|
|
+ cr_parser_clear_errors (a_this);
|
|
+ return CR_OK;
|
|
+
|
|
+ error:
|
|
+
|
|
+ if (expr) {
|
|
+ cr_term_destroy (expr);
|
|
+ expr = NULL;
|
|
+ }
|
|
+
|
|
+ if (*a_property) {
|
|
+ cr_string_destroy (*a_property);
|
|
+ *a_property = NULL;
|
|
+ }
|
|
+
|
|
+ cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
|
|
+
|
|
+ return status;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_parser_parse_statement_core:
|
|
+ *@a_this: the current instance of #CRParser.
|
|
+ *
|
|
+ *Parses a statement as defined by the css core grammar in
|
|
+ *chapter 4.1 of the css2 spec.
|
|
+ *statement : ruleset | at-rule;
|
|
+ *
|
|
+ *Returns CR_OK upon successfull completion, an error code otherwise.
|
|
+ */
|
|
+enum CRStatus
|
|
+cr_parser_parse_statement_core (CRParser * a_this)
|
|
+{
|
|
+ CRToken *token = NULL;
|
|
+ CRInputPos init_pos;
|
|
+ enum CRStatus status = CR_ERROR;
|
|
+
|
|
+ g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ RECORD_INITIAL_POS (a_this, &init_pos);
|
|
+
|
|
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
|
|
+
|
|
+ ENSURE_PARSING_COND (status == CR_OK && token);
|
|
+
|
|
+ switch (token->type) {
|
|
+ case ATKEYWORD_TK:
|
|
+ case IMPORT_SYM_TK:
|
|
+ case PAGE_SYM_TK:
|
|
+ case MEDIA_SYM_TK:
|
|
+ case FONT_FACE_SYM_TK:
|
|
+ case CHARSET_SYM_TK:
|
|
+ cr_tknzr_unget_token (PRIVATE (a_this)->tknzr, token);
|
|
+ token = NULL;
|
|
+ status = cr_parser_parse_atrule_core (a_this);
|
|
+ CHECK_PARSING_STATUS (status, TRUE);
|
|
+ break;
|
|
+
|
|
+ default:
|
|
+ cr_tknzr_unget_token (PRIVATE (a_this)->tknzr, token);
|
|
+ token = NULL;
|
|
+ status = cr_parser_parse_ruleset_core (a_this);
|
|
+ cr_parser_clear_errors (a_this);
|
|
+ CHECK_PARSING_STATUS (status, TRUE);
|
|
+ }
|
|
+
|
|
+ return CR_OK;
|
|
+
|
|
+ error:
|
|
+ if (token) {
|
|
+ cr_token_destroy (token);
|
|
+ token = NULL;
|
|
+ }
|
|
+
|
|
+ cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
|
|
+
|
|
+ return status;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_parser_parse_ruleset:
|
|
+ *@a_this: the "this pointer" of the current instance of #CRParser.
|
|
+ *
|
|
+ *Parses a "ruleset" as defined in the css2 spec at appendix D.1.
|
|
+ *ruleset ::= selector [ ',' S* selector ]*
|
|
+ *'{' S* declaration? [ ';' S* declaration? ]* '}' S*;
|
|
+ *
|
|
+ *This methods calls the the SAC handler on the relevant SAC handler
|
|
+ *callbacks whenever it encounters some specific constructions.
|
|
+ *See the documentation of #CRDocHandler (the SAC handler) to know
|
|
+ *when which SAC handler is called.
|
|
+ *
|
|
+ *Returns CR_OK upon successfull completion, an error code otherwise.
|
|
+ */
|
|
+enum CRStatus
|
|
+cr_parser_parse_ruleset (CRParser * a_this)
|
|
+{
|
|
+ enum CRStatus status = CR_OK;
|
|
+ CRInputPos init_pos;
|
|
+ guint32 cur_char = 0,
|
|
+ next_char = 0;
|
|
+ CRString *property = NULL;
|
|
+ CRTerm *expr = NULL;
|
|
+ CRSimpleSel *simple_sels = NULL;
|
|
+ CRSelector *selector = NULL;
|
|
+ gboolean start_selector = FALSE,
|
|
+ is_important = FALSE;
|
|
+ CRParsingLocation end_parsing_location;
|
|
+
|
|
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ RECORD_INITIAL_POS (a_this, &init_pos);
|
|
+
|
|
+ status = cr_parser_parse_selector (a_this, &selector);
|
|
+ CHECK_PARSING_STATUS (status, FALSE);
|
|
+
|
|
+ READ_NEXT_CHAR (a_this, &cur_char);
|
|
+
|
|
+ ENSURE_PARSING_COND_ERR
|
|
+ (a_this, cur_char == '{',
|
|
+ (const guchar *) "while parsing rulset: current char should be '{'",
|
|
+ CR_SYNTAX_ERROR);
|
|
+
|
|
+ if (PRIVATE (a_this)->sac_handler
|
|
+ && PRIVATE (a_this)->sac_handler->start_selector) {
|
|
+ /*
|
|
+ *the selector is ref counted so that the parser's user
|
|
+ *can choose to keep it.
|
|
+ */
|
|
+ if (selector) {
|
|
+ cr_selector_ref (selector);
|
|
+ }
|
|
+
|
|
+ PRIVATE (a_this)->sac_handler->start_selector
|
|
+ (PRIVATE (a_this)->sac_handler, selector);
|
|
+ start_selector = TRUE;
|
|
+ }
|
|
+
|
|
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
|
|
+
|
|
+ PRIVATE (a_this)->state = TRY_PARSE_RULESET_STATE;
|
|
+
|
|
+ status = cr_parser_parse_declaration (a_this, &property,
|
|
+ &expr,
|
|
+ &is_important);
|
|
+ if (expr) {
|
|
+ cr_term_ref (expr);
|
|
+ }
|
|
+ if (status == CR_OK
|
|
+ && PRIVATE (a_this)->sac_handler
|
|
+ && PRIVATE (a_this)->sac_handler->property) {
|
|
+ PRIVATE (a_this)->sac_handler->property
|
|
+ (PRIVATE (a_this)->sac_handler, property, expr,
|
|
+ is_important);
|
|
+ }
|
|
+ if (status == CR_OK) {
|
|
+ /*
|
|
+ *free the allocated
|
|
+ *'property' and 'term' before parsing
|
|
+ *next declarations.
|
|
+ */
|
|
+ if (property) {
|
|
+ cr_string_destroy (property);
|
|
+ property = NULL;
|
|
+ }
|
|
+ if (expr) {
|
|
+ cr_term_unref (expr);
|
|
+ expr = NULL;
|
|
+ }
|
|
+ } else {/*status != CR_OK*/
|
|
+ guint32 c = 0 ;
|
|
+ /*
|
|
+ *test if we have reached '}', which
|
|
+ *would mean that we are parsing an empty ruleset (eg. x{ })
|
|
+ *In that case, goto end_of_ruleset.
|
|
+ */
|
|
+ status = cr_tknzr_peek_char (PRIVATE (a_this)->tknzr, &c) ;
|
|
+ if (status == CR_OK && c == '}') {
|
|
+ status = CR_OK ;
|
|
+ goto end_of_ruleset ;
|
|
+ }
|
|
+ }
|
|
+ CHECK_PARSING_STATUS_ERR
|
|
+ (a_this, status, FALSE,
|
|
+ (const guchar *) "while parsing ruleset: next construction should be a declaration",
|
|
+ CR_SYNTAX_ERROR);
|
|
+
|
|
+ for (;;) {
|
|
+ PEEK_NEXT_CHAR (a_this, &next_char);
|
|
+ if (next_char != ';')
|
|
+ break;
|
|
+
|
|
+ /*consume the ';' char */
|
|
+ READ_NEXT_CHAR (a_this, &cur_char);
|
|
+
|
|
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
|
|
+
|
|
+ status = cr_parser_parse_declaration (a_this, &property,
|
|
+ &expr, &is_important);
|
|
+
|
|
+ if (expr) {
|
|
+ cr_term_ref (expr);
|
|
+ }
|
|
+ if (status == CR_OK
|
|
+ && PRIVATE (a_this)->sac_handler
|
|
+ && PRIVATE (a_this)->sac_handler->property) {
|
|
+ PRIVATE (a_this)->sac_handler->property
|
|
+ (PRIVATE (a_this)->sac_handler,
|
|
+ property, expr, is_important);
|
|
+ }
|
|
+ if (property) {
|
|
+ cr_string_destroy (property);
|
|
+ property = NULL;
|
|
+ }
|
|
+ if (expr) {
|
|
+ cr_term_unref (expr);
|
|
+ expr = NULL;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ end_of_ruleset:
|
|
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
|
|
+ cr_parser_get_parsing_location (a_this, &end_parsing_location);
|
|
+ READ_NEXT_CHAR (a_this, &cur_char);
|
|
+ ENSURE_PARSING_COND_ERR
|
|
+ (a_this, cur_char == '}',
|
|
+ (const guchar *) "while parsing rulset: current char must be a '}'",
|
|
+ CR_SYNTAX_ERROR);
|
|
+
|
|
+ selector->location = end_parsing_location;
|
|
+ if (PRIVATE (a_this)->sac_handler
|
|
+ && PRIVATE (a_this)->sac_handler->end_selector) {
|
|
+ PRIVATE (a_this)->sac_handler->end_selector
|
|
+ (PRIVATE (a_this)->sac_handler, selector);
|
|
+ start_selector = FALSE;
|
|
+ }
|
|
+
|
|
+ if (expr) {
|
|
+ cr_term_unref (expr);
|
|
+ expr = NULL;
|
|
+ }
|
|
+
|
|
+ if (simple_sels) {
|
|
+ cr_simple_sel_destroy (simple_sels);
|
|
+ simple_sels = NULL;
|
|
+ }
|
|
+
|
|
+ if (selector) {
|
|
+ cr_selector_unref (selector);
|
|
+ selector = NULL;
|
|
+ }
|
|
+
|
|
+ cr_parser_clear_errors (a_this);
|
|
+ PRIVATE (a_this)->state = RULESET_PARSED_STATE;
|
|
+
|
|
+ return CR_OK;
|
|
+
|
|
+ error:
|
|
+ if (start_selector == TRUE
|
|
+ && PRIVATE (a_this)->sac_handler
|
|
+ && PRIVATE (a_this)->sac_handler->error) {
|
|
+ PRIVATE (a_this)->sac_handler->error
|
|
+ (PRIVATE (a_this)->sac_handler);
|
|
+ }
|
|
+ if (expr) {
|
|
+ cr_term_unref (expr);
|
|
+ expr = NULL;
|
|
+ }
|
|
+ if (simple_sels) {
|
|
+ cr_simple_sel_destroy (simple_sels);
|
|
+ simple_sels = NULL;
|
|
+ }
|
|
+ if (property) {
|
|
+ cr_string_destroy (property);
|
|
+ }
|
|
+ if (selector) {
|
|
+ cr_selector_unref (selector);
|
|
+ selector = NULL;
|
|
+ }
|
|
+
|
|
+ cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
|
|
+
|
|
+ return status;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_parser_parse_import:
|
|
+ *@a_this: the "this pointer" of the current instance
|
|
+ *of #CRParser.
|
|
+ *@a_media_list: out parameter. A linked list of
|
|
+ *#CRString
|
|
+ *Each CRString is a string that contains
|
|
+ *a 'medium' declaration part of the successfully
|
|
+ *parsed 'import' declaration.
|
|
+ *@a_import_string: out parameter.
|
|
+ *A string that contains the 'import
|
|
+ *string". The import string can be either an uri (if it starts with
|
|
+ *the substring "uri(") or a any other css2 string. Note that
|
|
+ * *a_import_string must be initially set to NULL or else, this function
|
|
+ *will return CR_BAD_PARAM_ERROR.
|
|
+ *@a_location: the location (line, column) where the import has been parsed
|
|
+ *
|
|
+ *Parses an 'import' declaration as defined in the css2 spec
|
|
+ *in appendix D.1:
|
|
+ *
|
|
+ *import ::=
|
|
+ *\@import [STRING|URI] S* [ medium [ ',' S* medium]* ]? ';' S*
|
|
+ *
|
|
+ *Returns CR_OK upon sucessfull completion, an error code otherwise.
|
|
+ */
|
|
+enum CRStatus
|
|
+cr_parser_parse_import (CRParser * a_this,
|
|
+ GList ** a_media_list,
|
|
+ CRString ** a_import_string,
|
|
+ CRParsingLocation *a_location)
|
|
+{
|
|
+ enum CRStatus status = CR_OK;
|
|
+ CRInputPos init_pos;
|
|
+ guint32 cur_char = 0,
|
|
+ next_char = 0;
|
|
+ CRString *medium = NULL;
|
|
+
|
|
+ g_return_val_if_fail (a_this
|
|
+ && a_import_string
|
|
+ && (*a_import_string == NULL),
|
|
+ CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ RECORD_INITIAL_POS (a_this, &init_pos);
|
|
+
|
|
+ if (BYTE (a_this, 1, NULL) == '@'
|
|
+ && BYTE (a_this, 2, NULL) == 'i'
|
|
+ && BYTE (a_this, 3, NULL) == 'm'
|
|
+ && BYTE (a_this, 4, NULL) == 'p'
|
|
+ && BYTE (a_this, 5, NULL) == 'o'
|
|
+ && BYTE (a_this, 6, NULL) == 'r'
|
|
+ && BYTE (a_this, 7, NULL) == 't') {
|
|
+ SKIP_CHARS (a_this, 1);
|
|
+ if (a_location) {
|
|
+ cr_parser_get_parsing_location
|
|
+ (a_this, a_location) ;
|
|
+ }
|
|
+ SKIP_CHARS (a_this, 6);
|
|
+ status = CR_OK;
|
|
+ } else {
|
|
+ status = CR_PARSING_ERROR;
|
|
+ goto error;
|
|
+ }
|
|
+
|
|
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
|
|
+
|
|
+ PRIVATE (a_this)->state = TRY_PARSE_IMPORT_STATE;
|
|
+
|
|
+ PEEK_NEXT_CHAR (a_this, &next_char);
|
|
+
|
|
+ if (next_char == '"' || next_char == '\'') {
|
|
+ status = cr_parser_parse_string (a_this, a_import_string);
|
|
+
|
|
+ CHECK_PARSING_STATUS (status, FALSE);
|
|
+ } else {
|
|
+ status = cr_parser_parse_uri (a_this, a_import_string);
|
|
+
|
|
+ CHECK_PARSING_STATUS (status, FALSE);
|
|
+ }
|
|
+
|
|
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
|
|
+
|
|
+ status = cr_parser_parse_ident (a_this, &medium);
|
|
+
|
|
+ if (status == CR_OK && medium) {
|
|
+ *a_media_list = g_list_append (*a_media_list, medium);
|
|
+ medium = NULL;
|
|
+ }
|
|
+
|
|
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
|
|
+
|
|
+ for (; status == CR_OK;) {
|
|
+ if ((status = cr_tknzr_peek_char (PRIVATE (a_this)->tknzr,
|
|
+ &next_char)) != CR_OK) {
|
|
+ if (status == CR_END_OF_INPUT_ERROR) {
|
|
+ status = CR_OK;
|
|
+ goto okay;
|
|
+ }
|
|
+ goto error;
|
|
+ }
|
|
+
|
|
+ if (next_char == ',') {
|
|
+ READ_NEXT_CHAR (a_this, &cur_char);
|
|
+ } else {
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
|
|
+
|
|
+ status = cr_parser_parse_ident (a_this, &medium);
|
|
+
|
|
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
|
|
+
|
|
+ if ((status == CR_OK) && medium) {
|
|
+ *a_media_list = g_list_append (*a_media_list, medium);
|
|
+
|
|
+ medium = NULL;
|
|
+ }
|
|
+
|
|
+ CHECK_PARSING_STATUS (status, FALSE);
|
|
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
|
|
+ }
|
|
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
|
|
+ READ_NEXT_CHAR (a_this, &cur_char);
|
|
+ ENSURE_PARSING_COND (cur_char == ';');
|
|
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
|
|
+ okay:
|
|
+ cr_parser_clear_errors (a_this);
|
|
+ PRIVATE (a_this)->state = IMPORT_PARSED_STATE;
|
|
+
|
|
+ return CR_OK;
|
|
+
|
|
+ error:
|
|
+
|
|
+ if (*a_media_list) {
|
|
+ GList *cur = NULL;
|
|
+
|
|
+ /*
|
|
+ *free each element of *a_media_list.
|
|
+ *Note that each element of *a_medium list *must*
|
|
+ *be a GString* or else, the code that is coming next
|
|
+ *will corrupt the memory and lead to hard to debug
|
|
+ *random crashes.
|
|
+ *This is where C++ and its compile time
|
|
+ *type checking mecanism (through STL containers) would
|
|
+ *have prevented us to go through this hassle.
|
|
+ */
|
|
+ for (cur = *a_media_list; cur; cur = cur->next) {
|
|
+ if (cur->data) {
|
|
+ cr_string_destroy (cur->data);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ g_list_free (*a_media_list);
|
|
+ *a_media_list = NULL;
|
|
+ }
|
|
+
|
|
+ if (*a_import_string) {
|
|
+ cr_string_destroy (*a_import_string);
|
|
+ *a_import_string = NULL;
|
|
+ }
|
|
+
|
|
+ if (medium) {
|
|
+ cr_string_destroy (medium);
|
|
+ medium = NULL;
|
|
+ }
|
|
+
|
|
+ cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
|
|
+
|
|
+ return status;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_parser_parse_media:
|
|
+ *@a_this: the "this pointer" of the current instance of #CRParser.
|
|
+ *
|
|
+ *Parses a 'media' declaration as specified in the css2 spec at
|
|
+ *appendix D.1:
|
|
+ *
|
|
+ *media ::= \@media S* medium [ ',' S* medium ]* '{' S* ruleset* '}' S*
|
|
+ *
|
|
+ *Note that this function calls the required sac handlers during the parsing
|
|
+ *to notify media productions. See #CRDocHandler to know the callback called
|
|
+ *during \@media parsing.
|
|
+ *
|
|
+ *Returns CR_OK upon successfull completion, an error code otherwise.
|
|
+ */
|
|
+enum CRStatus
|
|
+cr_parser_parse_media (CRParser * a_this)
|
|
+{
|
|
+ enum CRStatus status = CR_OK;
|
|
+ CRInputPos init_pos;
|
|
+ CRToken *token = NULL;
|
|
+ guint32 next_char = 0,
|
|
+ cur_char = 0;
|
|
+ CRString *medium = NULL;
|
|
+ GList *media_list = NULL;
|
|
+ CRParsingLocation location = {0} ;
|
|
+
|
|
+ g_return_val_if_fail (a_this
|
|
+ && PRIVATE (a_this),
|
|
+ CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ RECORD_INITIAL_POS (a_this, &init_pos);
|
|
+
|
|
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr,
|
|
+ &token);
|
|
+ ENSURE_PARSING_COND (status == CR_OK
|
|
+ && token
|
|
+ && token->type == MEDIA_SYM_TK);
|
|
+ cr_parsing_location_copy (&location, &token->location) ;
|
|
+ cr_token_destroy (token);
|
|
+ token = NULL;
|
|
+
|
|
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
|
|
+
|
|
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
|
|
+ ENSURE_PARSING_COND (status == CR_OK
|
|
+ && token && token->type == IDENT_TK);
|
|
+
|
|
+ medium = token->u.str;
|
|
+ token->u.str = NULL;
|
|
+ cr_token_destroy (token);
|
|
+ token = NULL;
|
|
+
|
|
+ if (medium) {
|
|
+ media_list = g_list_append (media_list, medium);
|
|
+ medium = NULL;
|
|
+ }
|
|
+
|
|
+ for (; status == CR_OK;) {
|
|
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
|
|
+ PEEK_NEXT_CHAR (a_this, &next_char);
|
|
+
|
|
+ if (next_char == ',') {
|
|
+ READ_NEXT_CHAR (a_this, &cur_char);
|
|
+ } else {
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
|
|
+
|
|
+ status = cr_parser_parse_ident (a_this, &medium);
|
|
+
|
|
+ CHECK_PARSING_STATUS (status, FALSE);
|
|
+
|
|
+ if (medium) {
|
|
+ media_list = g_list_append (media_list, medium);
|
|
+ medium = NULL;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ READ_NEXT_CHAR (a_this, &cur_char);
|
|
+
|
|
+ ENSURE_PARSING_COND (cur_char == '{');
|
|
+
|
|
+ /*
|
|
+ *call the SAC handler api here.
|
|
+ */
|
|
+ if (PRIVATE (a_this)->sac_handler
|
|
+ && PRIVATE (a_this)->sac_handler->start_media) {
|
|
+ PRIVATE (a_this)->sac_handler->start_media
|
|
+ (PRIVATE (a_this)->sac_handler, media_list,
|
|
+ &location);
|
|
+ }
|
|
+
|
|
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
|
|
+
|
|
+ PRIVATE (a_this)->state = TRY_PARSE_MEDIA_STATE;
|
|
+
|
|
+ for (; status == CR_OK;) {
|
|
+ status = cr_parser_parse_ruleset (a_this);
|
|
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
|
|
+ }
|
|
+
|
|
+ READ_NEXT_CHAR (a_this, &cur_char);
|
|
+
|
|
+ ENSURE_PARSING_COND (cur_char == '}');
|
|
+
|
|
+ /*
|
|
+ *call the right SAC handler api here.
|
|
+ */
|
|
+ if (PRIVATE (a_this)->sac_handler
|
|
+ && PRIVATE (a_this)->sac_handler->end_media) {
|
|
+ PRIVATE (a_this)->sac_handler->end_media
|
|
+ (PRIVATE (a_this)->sac_handler, media_list);
|
|
+ }
|
|
+
|
|
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
|
|
+
|
|
+ /*
|
|
+ *Then, free the data structures passed to
|
|
+ *the last call to the SAC handler.
|
|
+ */
|
|
+ if (medium) {
|
|
+ cr_string_destroy (medium);
|
|
+ medium = NULL;
|
|
+ }
|
|
+
|
|
+ if (media_list) {
|
|
+ GList *cur = NULL;
|
|
+
|
|
+ for (cur = media_list; cur; cur = cur->next) {
|
|
+ cr_string_destroy (cur->data);
|
|
+ }
|
|
+
|
|
+ g_list_free (media_list);
|
|
+ media_list = NULL;
|
|
+ }
|
|
+
|
|
+ cr_parser_clear_errors (a_this);
|
|
+ PRIVATE (a_this)->state = MEDIA_PARSED_STATE;
|
|
+
|
|
+ return CR_OK;
|
|
+
|
|
+ error:
|
|
+
|
|
+ if (token) {
|
|
+ cr_token_destroy (token);
|
|
+ token = NULL;
|
|
+ }
|
|
+
|
|
+ if (medium) {
|
|
+ cr_string_destroy (medium);
|
|
+ medium = NULL;
|
|
+ }
|
|
+
|
|
+ if (media_list) {
|
|
+ GList *cur = NULL;
|
|
+
|
|
+ for (cur = media_list; cur; cur = cur->next) {
|
|
+ cr_string_destroy (cur->data);
|
|
+ }
|
|
+
|
|
+ g_list_free (media_list);
|
|
+ media_list = NULL;
|
|
+ }
|
|
+
|
|
+ cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
|
|
+
|
|
+ return status;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_parser_parse_page:
|
|
+ *@a_this: the "this pointer" of the current instance of #CRParser.
|
|
+ *
|
|
+ *Parses '\@page' rule as specified in the css2 spec in appendix D.1:
|
|
+ *page ::= PAGE_SYM S* IDENT? pseudo_page? S*
|
|
+ *'{' S* declaration [ ';' S* declaration ]* '}' S*
|
|
+ *
|
|
+ *This function also calls the relevant SAC handlers whenever it
|
|
+ *encounters a construction that must
|
|
+ *be reported to the calling application.
|
|
+ *
|
|
+ *Returns CR_OK upon successfull completion, an error code otherwise.
|
|
+ */
|
|
+enum CRStatus
|
|
+cr_parser_parse_page (CRParser * a_this)
|
|
+{
|
|
+ enum CRStatus status = CR_OK;
|
|
+ CRInputPos init_pos;
|
|
+ CRToken *token = NULL;
|
|
+ CRTerm *css_expression = NULL;
|
|
+ CRString *page_selector = NULL,
|
|
+ *page_pseudo_class = NULL,
|
|
+ *property = NULL;
|
|
+ gboolean important = TRUE;
|
|
+ CRParsingLocation location = {0} ;
|
|
+
|
|
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ RECORD_INITIAL_POS (a_this, &init_pos);
|
|
+
|
|
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr,
|
|
+ &token) ;
|
|
+ ENSURE_PARSING_COND (status == CR_OK
|
|
+ && token
|
|
+ && token->type == PAGE_SYM_TK);
|
|
+
|
|
+ cr_parsing_location_copy (&location, &token->location) ;
|
|
+ cr_token_destroy (token);
|
|
+ token = NULL;
|
|
+
|
|
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
|
|
+
|
|
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
|
|
+ ENSURE_PARSING_COND (status == CR_OK && token);
|
|
+
|
|
+ if (token->type == IDENT_TK) {
|
|
+ page_selector = token->u.str;
|
|
+ token->u.str = NULL;
|
|
+ cr_token_destroy (token);
|
|
+ token = NULL;
|
|
+ } else {
|
|
+ cr_tknzr_unget_token (PRIVATE (a_this)->tknzr, token);
|
|
+ token = NULL;
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ *try to parse pseudo_page
|
|
+ */
|
|
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
|
|
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
|
|
+ ENSURE_PARSING_COND (status == CR_OK && token);
|
|
+
|
|
+ if (token->type == DELIM_TK && token->u.unichar == ':') {
|
|
+ cr_token_destroy (token);
|
|
+ token = NULL;
|
|
+ status = cr_parser_parse_ident (a_this, &page_pseudo_class);
|
|
+ CHECK_PARSING_STATUS (status, FALSE);
|
|
+ } else {
|
|
+ cr_tknzr_unget_token (PRIVATE (a_this)->tknzr, token);
|
|
+ token = NULL;
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ *parse_block
|
|
+ *
|
|
+ */
|
|
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
|
|
+
|
|
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
|
|
+
|
|
+ ENSURE_PARSING_COND (status == CR_OK && token
|
|
+ && token->type == CBO_TK);
|
|
+
|
|
+ cr_token_destroy (token);
|
|
+ token = NULL;
|
|
+
|
|
+ /*
|
|
+ *Call the appropriate SAC handler here.
|
|
+ */
|
|
+ if (PRIVATE (a_this)->sac_handler
|
|
+ && PRIVATE (a_this)->sac_handler->start_page) {
|
|
+ PRIVATE (a_this)->sac_handler->start_page
|
|
+ (PRIVATE (a_this)->sac_handler,
|
|
+ page_selector, page_pseudo_class,
|
|
+ &location);
|
|
+ }
|
|
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
|
|
+
|
|
+ PRIVATE (a_this)->state = TRY_PARSE_PAGE_STATE;
|
|
+
|
|
+ status = cr_parser_parse_declaration (a_this, &property,
|
|
+ &css_expression,
|
|
+ &important);
|
|
+ ENSURE_PARSING_COND (status == CR_OK);
|
|
+
|
|
+ /*
|
|
+ *call the relevant SAC handler here...
|
|
+ */
|
|
+ if (PRIVATE (a_this)->sac_handler
|
|
+ && PRIVATE (a_this)->sac_handler->property) {
|
|
+ if (css_expression)
|
|
+ cr_term_ref (css_expression);
|
|
+
|
|
+ PRIVATE (a_this)->sac_handler->property
|
|
+ (PRIVATE (a_this)->sac_handler,
|
|
+ property, css_expression, important);
|
|
+ }
|
|
+ /*
|
|
+ *... and free the data structure passed to that last
|
|
+ *SAC handler.
|
|
+ */
|
|
+ if (property) {
|
|
+ cr_string_destroy (property);
|
|
+ property = NULL;
|
|
+ }
|
|
+ if (css_expression) {
|
|
+ cr_term_unref (css_expression);
|
|
+ css_expression = NULL;
|
|
+ }
|
|
+
|
|
+ for (;;) {
|
|
+ /*parse the other ';' separated declarations */
|
|
+ if (token) {
|
|
+ cr_token_destroy (token);
|
|
+ token = NULL;
|
|
+ }
|
|
+ status = cr_tknzr_get_next_token
|
|
+ (PRIVATE (a_this)->tknzr, &token);
|
|
+
|
|
+ ENSURE_PARSING_COND (status == CR_OK && token);
|
|
+
|
|
+ if (token->type != SEMICOLON_TK) {
|
|
+ cr_tknzr_unget_token
|
|
+ (PRIVATE (a_this)->tknzr,
|
|
+ token);
|
|
+ token = NULL ;
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ cr_token_destroy (token);
|
|
+ token = NULL;
|
|
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
|
|
+
|
|
+ status = cr_parser_parse_declaration (a_this, &property,
|
|
+ &css_expression,
|
|
+ &important);
|
|
+ if (status != CR_OK)
|
|
+ break ;
|
|
+
|
|
+ /*
|
|
+ *call the relevant SAC handler here...
|
|
+ */
|
|
+ if (PRIVATE (a_this)->sac_handler
|
|
+ && PRIVATE (a_this)->sac_handler->property) {
|
|
+ cr_term_ref (css_expression);
|
|
+ PRIVATE (a_this)->sac_handler->property
|
|
+ (PRIVATE (a_this)->sac_handler,
|
|
+ property, css_expression, important);
|
|
+ }
|
|
+ /*
|
|
+ *... and free the data structure passed to that last
|
|
+ *SAC handler.
|
|
+ */
|
|
+ if (property) {
|
|
+ cr_string_destroy (property);
|
|
+ property = NULL;
|
|
+ }
|
|
+ if (css_expression) {
|
|
+ cr_term_unref (css_expression);
|
|
+ css_expression = NULL;
|
|
+ }
|
|
+ }
|
|
+ cr_parser_try_to_skip_spaces_and_comments
|
|
+ (a_this) ;
|
|
+ if (token) {
|
|
+ cr_token_destroy (token) ;
|
|
+ token = NULL ;
|
|
+ }
|
|
+
|
|
+ status = cr_tknzr_get_next_token
|
|
+ (PRIVATE (a_this)->tknzr, &token);
|
|
+ ENSURE_PARSING_COND (status == CR_OK
|
|
+ && token
|
|
+ && token->type == CBC_TK) ;
|
|
+ cr_token_destroy (token) ;
|
|
+ token = NULL ;
|
|
+ /*
|
|
+ *call the relevant SAC handler here.
|
|
+ */
|
|
+ if (PRIVATE (a_this)->sac_handler
|
|
+ && PRIVATE (a_this)->sac_handler->end_page) {
|
|
+ PRIVATE (a_this)->sac_handler->end_page
|
|
+ (PRIVATE (a_this)->sac_handler,
|
|
+ page_selector, page_pseudo_class);
|
|
+ }
|
|
+
|
|
+ if (page_selector) {
|
|
+ cr_string_destroy (page_selector);
|
|
+ page_selector = NULL;
|
|
+ }
|
|
+
|
|
+ if (page_pseudo_class) {
|
|
+ cr_string_destroy (page_pseudo_class);
|
|
+ page_pseudo_class = NULL;
|
|
+ }
|
|
+
|
|
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
|
|
+
|
|
+ /*here goes the former implem of this function ... */
|
|
+
|
|
+ cr_parser_clear_errors (a_this);
|
|
+ PRIVATE (a_this)->state = PAGE_PARSED_STATE;
|
|
+
|
|
+ return CR_OK;
|
|
+
|
|
+ error:
|
|
+ if (token) {
|
|
+ cr_token_destroy (token);
|
|
+ token = NULL;
|
|
+ }
|
|
+ if (page_selector) {
|
|
+ cr_string_destroy (page_selector);
|
|
+ page_selector = NULL;
|
|
+ }
|
|
+ if (page_pseudo_class) {
|
|
+ cr_string_destroy (page_pseudo_class);
|
|
+ page_pseudo_class = NULL;
|
|
+ }
|
|
+ if (property) {
|
|
+ cr_string_destroy (property);
|
|
+ property = NULL;
|
|
+ }
|
|
+ if (css_expression) {
|
|
+ cr_term_destroy (css_expression);
|
|
+ css_expression = NULL;
|
|
+ }
|
|
+ cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
|
|
+ return status;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_parser_parse_charset:
|
|
+ *@a_this: the "this pointer" of the current instance of #CRParser.
|
|
+ *@a_value: out parameter. The actual parsed value of the charset
|
|
+ *declararation. Note that for safety check reasons, *a_value must be
|
|
+ *set to NULL.
|
|
+ *@a_charset_sym_location: the parsing location of the charset rule
|
|
+ *
|
|
+ *Parses a charset declaration as defined implictly by the css2 spec in
|
|
+ *appendix D.1:
|
|
+ *charset ::= CHARSET_SYM S* STRING S* ';'
|
|
+ *
|
|
+ *Returns CR_OK upon successfull completion, an error code otherwise.
|
|
+ */
|
|
+enum CRStatus
|
|
+cr_parser_parse_charset (CRParser * a_this, CRString ** a_value,
|
|
+ CRParsingLocation *a_charset_sym_location)
|
|
+{
|
|
+ enum CRStatus status = CR_OK;
|
|
+ CRInputPos init_pos;
|
|
+ CRToken *token = NULL;
|
|
+ CRString *charset_str = NULL;
|
|
+
|
|
+ g_return_val_if_fail (a_this && a_value
|
|
+ && (*a_value == NULL),
|
|
+ CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ RECORD_INITIAL_POS (a_this, &init_pos);
|
|
+
|
|
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
|
|
+
|
|
+ ENSURE_PARSING_COND (status == CR_OK
|
|
+ && token && token->type == CHARSET_SYM_TK);
|
|
+ if (a_charset_sym_location) {
|
|
+ cr_parsing_location_copy (a_charset_sym_location,
|
|
+ &token->location) ;
|
|
+ }
|
|
+ cr_token_destroy (token);
|
|
+ token = NULL;
|
|
+
|
|
+ PRIVATE (a_this)->state = TRY_PARSE_CHARSET_STATE;
|
|
+
|
|
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
|
|
+
|
|
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
|
|
+ ENSURE_PARSING_COND (status == CR_OK
|
|
+ && token && token->type == STRING_TK);
|
|
+ charset_str = token->u.str;
|
|
+ token->u.str = NULL;
|
|
+ cr_token_destroy (token);
|
|
+ token = NULL;
|
|
+
|
|
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
|
|
+
|
|
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
|
|
+
|
|
+ ENSURE_PARSING_COND (status == CR_OK
|
|
+ && token && token->type == SEMICOLON_TK);
|
|
+ cr_token_destroy (token);
|
|
+ token = NULL;
|
|
+
|
|
+ if (charset_str) {
|
|
+ *a_value = charset_str;
|
|
+ charset_str = NULL;
|
|
+ }
|
|
+
|
|
+ PRIVATE (a_this)->state = CHARSET_PARSED_STATE;
|
|
+ return CR_OK;
|
|
+
|
|
+ error:
|
|
+
|
|
+ if (token) {
|
|
+ cr_token_destroy (token);
|
|
+ token = NULL;
|
|
+ }
|
|
+
|
|
+ if (*a_value) {
|
|
+ cr_string_destroy (*a_value);
|
|
+ *a_value = NULL;
|
|
+ }
|
|
+
|
|
+ if (charset_str) {
|
|
+ cr_string_destroy (charset_str);
|
|
+ charset_str = NULL;
|
|
+ }
|
|
+
|
|
+ cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
|
|
+
|
|
+ return status;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_parser_parse_font_face:
|
|
+ *@a_this: the current instance of #CRParser.
|
|
+ *
|
|
+ *Parses the "\@font-face" rule specified in the css1 spec in
|
|
+ *appendix D.1:
|
|
+ *
|
|
+ *font_face ::= FONT_FACE_SYM S*
|
|
+ *'{' S* declaration [ ';' S* declaration ]* '}' S*
|
|
+ *
|
|
+ *This function will call SAC handlers whenever it is necessary.
|
|
+ *
|
|
+ *Returns CR_OK upon successfull completion, an error code otherwise.
|
|
+ */
|
|
+enum CRStatus
|
|
+cr_parser_parse_font_face (CRParser * a_this)
|
|
+{
|
|
+ enum CRStatus status = CR_ERROR;
|
|
+ CRInputPos init_pos;
|
|
+ CRString *property = NULL;
|
|
+ CRTerm *css_expression = NULL;
|
|
+ CRToken *token = NULL;
|
|
+ gboolean important = FALSE;
|
|
+ guint32 next_char = 0,
|
|
+ cur_char = 0;
|
|
+ CRParsingLocation location = {0} ;
|
|
+
|
|
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ RECORD_INITIAL_POS (a_this, &init_pos);
|
|
+
|
|
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
|
|
+ ENSURE_PARSING_COND (status == CR_OK
|
|
+ && token
|
|
+ && token->type == FONT_FACE_SYM_TK);
|
|
+
|
|
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
|
|
+ if (token) {
|
|
+ cr_parsing_location_copy (&location,
|
|
+ &token->location) ;
|
|
+ cr_token_destroy (token);
|
|
+ token = NULL;
|
|
+ }
|
|
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr,
|
|
+ &token);
|
|
+ ENSURE_PARSING_COND (status == CR_OK && token
|
|
+ && token->type == CBO_TK);
|
|
+ if (token) {
|
|
+ cr_token_destroy (token);
|
|
+ token = NULL;
|
|
+ }
|
|
+ /*
|
|
+ *here, call the relevant SAC handler.
|
|
+ */
|
|
+ if (PRIVATE (a_this)->sac_handler
|
|
+ && PRIVATE (a_this)->sac_handler->start_font_face) {
|
|
+ PRIVATE (a_this)->sac_handler->start_font_face
|
|
+ (PRIVATE (a_this)->sac_handler, &location);
|
|
+ }
|
|
+ PRIVATE (a_this)->state = TRY_PARSE_FONT_FACE_STATE;
|
|
+ /*
|
|
+ *and resume the parsing.
|
|
+ */
|
|
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
|
|
+ status = cr_parser_parse_declaration (a_this, &property,
|
|
+ &css_expression, &important);
|
|
+ if (status == CR_OK) {
|
|
+ /*
|
|
+ *here, call the relevant SAC handler.
|
|
+ */
|
|
+ cr_term_ref (css_expression);
|
|
+ if (PRIVATE (a_this)->sac_handler &&
|
|
+ PRIVATE (a_this)->sac_handler->property) {
|
|
+ PRIVATE (a_this)->sac_handler->property
|
|
+ (PRIVATE (a_this)->sac_handler,
|
|
+ property, css_expression, important);
|
|
+ }
|
|
+ ENSURE_PARSING_COND (css_expression && property);
|
|
+ }
|
|
+ /*free the data structures allocated during last parsing. */
|
|
+ if (property) {
|
|
+ cr_string_destroy (property);
|
|
+ property = NULL;
|
|
+ }
|
|
+ if (css_expression) {
|
|
+ cr_term_unref (css_expression);
|
|
+ css_expression = NULL;
|
|
+ }
|
|
+ for (;;) {
|
|
+ PEEK_NEXT_CHAR (a_this, &next_char);
|
|
+ if (next_char == ';') {
|
|
+ READ_NEXT_CHAR (a_this, &cur_char);
|
|
+ } else {
|
|
+ break;
|
|
+ }
|
|
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
|
|
+ status = cr_parser_parse_declaration (a_this,
|
|
+ &property,
|
|
+ &css_expression,
|
|
+ &important);
|
|
+ if (status != CR_OK)
|
|
+ break;
|
|
+ /*
|
|
+ *here, call the relevant SAC handler.
|
|
+ */
|
|
+ cr_term_ref (css_expression);
|
|
+ if (PRIVATE (a_this)->sac_handler->property) {
|
|
+ PRIVATE (a_this)->sac_handler->property
|
|
+ (PRIVATE (a_this)->sac_handler,
|
|
+ property, css_expression, important);
|
|
+ }
|
|
+ /*
|
|
+ *Then, free the data structures allocated during
|
|
+ *last parsing.
|
|
+ */
|
|
+ if (property) {
|
|
+ cr_string_destroy (property);
|
|
+ property = NULL;
|
|
+ }
|
|
+ if (css_expression) {
|
|
+ cr_term_unref (css_expression);
|
|
+ css_expression = NULL;
|
|
+ }
|
|
+ }
|
|
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
|
|
+ READ_NEXT_CHAR (a_this, &cur_char);
|
|
+ ENSURE_PARSING_COND (cur_char == '}');
|
|
+ /*
|
|
+ *here, call the relevant SAC handler.
|
|
+ */
|
|
+ if (PRIVATE (a_this)->sac_handler->end_font_face) {
|
|
+ PRIVATE (a_this)->sac_handler->end_font_face
|
|
+ (PRIVATE (a_this)->sac_handler);
|
|
+ }
|
|
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
|
|
+
|
|
+ if (token) {
|
|
+ cr_token_destroy (token);
|
|
+ token = NULL;
|
|
+ }
|
|
+ cr_parser_clear_errors (a_this);
|
|
+ PRIVATE (a_this)->state = FONT_FACE_PARSED_STATE;
|
|
+ return CR_OK;
|
|
+
|
|
+ error:
|
|
+ if (token) {
|
|
+ cr_token_destroy (token);
|
|
+ token = NULL;
|
|
+ }
|
|
+ if (property) {
|
|
+ cr_string_destroy (property);
|
|
+ property = NULL;
|
|
+ }
|
|
+ if (css_expression) {
|
|
+ cr_term_destroy (css_expression);
|
|
+ css_expression = NULL;
|
|
+ }
|
|
+ cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
|
|
+ return status;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_parser_parse:
|
|
+ *@a_this: the current instance of #CRParser.
|
|
+ *
|
|
+ *Parses the data that comes from the
|
|
+ *input previously associated to the current instance of
|
|
+ *#CRParser.
|
|
+ *
|
|
+ *Returns CR_OK upon succesful completion, an error code otherwise.
|
|
+ */
|
|
+enum CRStatus
|
|
+cr_parser_parse (CRParser * a_this)
|
|
+{
|
|
+ enum CRStatus status = CR_ERROR;
|
|
+
|
|
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
|
|
+ && PRIVATE (a_this)->tknzr, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ if (PRIVATE (a_this)->use_core_grammar == FALSE) {
|
|
+ status = cr_parser_parse_stylesheet (a_this);
|
|
+ } else {
|
|
+ status = cr_parser_parse_stylesheet_core (a_this);
|
|
+ }
|
|
+
|
|
+ return status;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_parser_set_tknzr:
|
|
+ * @a_this: the current instance of #CRParser;
|
|
+ * @a_tknzr: the new tokenizer.
|
|
+ *
|
|
+ * Returns CR_OK upon successful completion, an error code otherwise.
|
|
+ */
|
|
+enum CRStatus
|
|
+cr_parser_set_tknzr (CRParser * a_this, CRTknzr * a_tknzr)
|
|
+{
|
|
+ g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ if (PRIVATE (a_this)->tknzr) {
|
|
+ cr_tknzr_unref (PRIVATE (a_this)->tknzr);
|
|
+ }
|
|
+
|
|
+ PRIVATE (a_this)->tknzr = a_tknzr;
|
|
+
|
|
+ if (a_tknzr)
|
|
+ cr_tknzr_ref (a_tknzr);
|
|
+
|
|
+ return CR_OK;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_parser_get_tknzr:
|
|
+ *@a_this: the current instance of #CRParser
|
|
+ *@a_tknzr: out parameter. The returned tokenizer
|
|
+ *
|
|
+ *Getter of the parser's underlying tokenizer
|
|
+ *
|
|
+ *Returns CR_OK upon succesful completion, an error code
|
|
+ *otherwise
|
|
+ */
|
|
+enum CRStatus
|
|
+cr_parser_get_tknzr (CRParser * a_this, CRTknzr ** a_tknzr)
|
|
+{
|
|
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
|
|
+ && a_tknzr, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ *a_tknzr = PRIVATE (a_this)->tknzr;
|
|
+ return CR_OK;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_parser_get_parsing_location:
|
|
+ *@a_this: the current instance of #CRParser
|
|
+ *@a_loc: the parsing location to get.
|
|
+ *
|
|
+ *Gets the current parsing location.
|
|
+ *
|
|
+ *Returns CR_OK upon succesful completion, an error code
|
|
+ *otherwise.
|
|
+ */
|
|
+enum CRStatus
|
|
+cr_parser_get_parsing_location (CRParser const *a_this,
|
|
+ CRParsingLocation *a_loc)
|
|
+{
|
|
+ g_return_val_if_fail (a_this
|
|
+ && PRIVATE (a_this)
|
|
+ && a_loc, CR_BAD_PARAM_ERROR) ;
|
|
+
|
|
+ return cr_tknzr_get_parsing_location
|
|
+ (PRIVATE (a_this)->tknzr, a_loc) ;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_parser_parse_buf:
|
|
+ *@a_this: the current instance of #CRparser
|
|
+ *@a_buf: the input buffer
|
|
+ *@a_len: the length of the input buffer
|
|
+ *@a_enc: the encoding of the buffer
|
|
+ *
|
|
+ *Parses a stylesheet from a buffer
|
|
+ *
|
|
+ *Returns CR_OK upon successful completion, an error code otherwise.
|
|
+ */
|
|
+enum CRStatus
|
|
+cr_parser_parse_buf (CRParser * a_this,
|
|
+ const guchar * a_buf,
|
|
+ gulong a_len, enum CREncoding a_enc)
|
|
+{
|
|
+ enum CRStatus status = CR_ERROR;
|
|
+ CRTknzr *tknzr = NULL;
|
|
+
|
|
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
|
|
+ && a_buf, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ tknzr = cr_tknzr_new_from_buf ((guchar*)a_buf, a_len, a_enc, FALSE);
|
|
+
|
|
+ g_return_val_if_fail (tknzr != NULL, CR_ERROR);
|
|
+
|
|
+ status = cr_parser_set_tknzr (a_this, tknzr);
|
|
+ g_return_val_if_fail (status == CR_OK, CR_ERROR);
|
|
+
|
|
+ status = cr_parser_parse (a_this);
|
|
+
|
|
+ return status;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_parser_destroy:
|
|
+ *@a_this: the current instance of #CRParser to
|
|
+ *destroy.
|
|
+ *
|
|
+ *Destroys the current instance
|
|
+ *of #CRParser.
|
|
+ */
|
|
+void
|
|
+cr_parser_destroy (CRParser * a_this)
|
|
+{
|
|
+ g_return_if_fail (a_this && PRIVATE (a_this));
|
|
+
|
|
+ if (PRIVATE (a_this)->tknzr) {
|
|
+ if (cr_tknzr_unref (PRIVATE (a_this)->tknzr) == TRUE)
|
|
+ PRIVATE (a_this)->tknzr = NULL;
|
|
+ }
|
|
+
|
|
+ if (PRIVATE (a_this)->sac_handler) {
|
|
+ cr_doc_handler_unref (PRIVATE (a_this)->sac_handler);
|
|
+ PRIVATE (a_this)->sac_handler = NULL;
|
|
+ }
|
|
+
|
|
+ if (PRIVATE (a_this)->err_stack) {
|
|
+ cr_parser_clear_errors (a_this);
|
|
+ PRIVATE (a_this)->err_stack = NULL;
|
|
+ }
|
|
+
|
|
+ if (PRIVATE (a_this)) {
|
|
+ g_free (PRIVATE (a_this));
|
|
+ PRIVATE (a_this) = NULL;
|
|
+ }
|
|
+
|
|
+ if (a_this) {
|
|
+ g_free (a_this);
|
|
+ a_this = NULL; /*useless. Just for the sake of coherence */
|
|
+ }
|
|
+}
|
|
diff --git a/src/st/croco/cr-parser.h b/src/st/croco/cr-parser.h
|
|
new file mode 100644
|
|
index 000000000..6dce9439e
|
|
--- /dev/null
|
|
+++ b/src/st/croco/cr-parser.h
|
|
@@ -0,0 +1,128 @@
|
|
+/* -*- 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 copyrights information.
|
|
+ */
|
|
+
|
|
+#ifndef __CR_PARSER_H__
|
|
+#define __CR_PARSER_H__
|
|
+
|
|
+#include <glib.h>
|
|
+#include "cr-input.h"
|
|
+#include "cr-tknzr.h"
|
|
+#include "cr-utils.h"
|
|
+#include "cr-doc-handler.h"
|
|
+
|
|
+G_BEGIN_DECLS
|
|
+
|
|
+/**
|
|
+ *@file
|
|
+ *The declaration file
|
|
+ *of the #CRParser class.
|
|
+ */
|
|
+typedef struct _CRParser CRParser ;
|
|
+typedef struct _CRParserPriv CRParserPriv ;
|
|
+
|
|
+
|
|
+/**
|
|
+ *The implementation of
|
|
+ *the SAC parser.
|
|
+ *The Class is opaque
|
|
+ *and must be manipulated through
|
|
+ *the provided methods.
|
|
+ */
|
|
+struct _CRParser {
|
|
+ CRParserPriv *priv ;
|
|
+} ;
|
|
+
|
|
+
|
|
+CRParser * cr_parser_new (CRTknzr *a_tknzr) ;
|
|
+
|
|
+CRParser * cr_parser_new_from_buf (guchar *a_buf, gulong a_len,
|
|
+ enum CREncoding a_enc,
|
|
+ gboolean a_free_buf) ;
|
|
+
|
|
+CRParser * cr_parser_new_from_file (const guchar *a_file_uri,
|
|
+ enum CREncoding a_enc) ;
|
|
+
|
|
+CRParser * cr_parser_new_from_input (CRInput *a_input) ;
|
|
+
|
|
+enum CRStatus cr_parser_set_tknzr (CRParser *a_this, CRTknzr *a_tknzr) ;
|
|
+
|
|
+enum CRStatus cr_parser_get_tknzr (CRParser *a_this, CRTknzr **a_tknzr) ;
|
|
+
|
|
+enum CRStatus cr_parser_get_parsing_location (CRParser const *a_this, CRParsingLocation *a_loc) ;
|
|
+
|
|
+enum CRStatus cr_parser_try_to_skip_spaces_and_comments (CRParser *a_this) ;
|
|
+
|
|
+
|
|
+enum CRStatus cr_parser_set_sac_handler (CRParser *a_this,
|
|
+ CRDocHandler *a_handler) ;
|
|
+
|
|
+enum CRStatus cr_parser_get_sac_handler (CRParser *a_this,
|
|
+ CRDocHandler **a_handler) ;
|
|
+
|
|
+enum CRStatus cr_parser_set_use_core_grammar (CRParser *a_this,
|
|
+ gboolean a_use_core_grammar) ;
|
|
+enum CRStatus cr_parser_get_use_core_grammar (CRParser const *a_this,
|
|
+ gboolean *a_use_core_grammar) ;
|
|
+
|
|
+enum CRStatus cr_parser_parse (CRParser *a_this) ;
|
|
+
|
|
+enum CRStatus cr_parser_parse_file (CRParser *a_this,
|
|
+ const guchar *a_file_uri,
|
|
+ enum CREncoding a_enc) ;
|
|
+
|
|
+enum CRStatus cr_parser_parse_buf (CRParser *a_this, const guchar *a_buf,
|
|
+ gulong a_len, enum CREncoding a_enc) ;
|
|
+
|
|
+enum CRStatus cr_parser_set_default_sac_handler (CRParser *a_this) ;
|
|
+
|
|
+enum CRStatus cr_parser_parse_term (CRParser *a_this, CRTerm **a_term) ;
|
|
+
|
|
+enum CRStatus cr_parser_parse_expr (CRParser *a_this, CRTerm **a_expr) ;
|
|
+
|
|
+enum CRStatus cr_parser_parse_prio (CRParser *a_this, CRString **a_prio) ;
|
|
+
|
|
+enum CRStatus cr_parser_parse_declaration (CRParser *a_this, CRString **a_property,
|
|
+ CRTerm **a_expr, gboolean *a_important) ;
|
|
+
|
|
+enum CRStatus cr_parser_parse_statement_core (CRParser *a_this) ;
|
|
+
|
|
+enum CRStatus cr_parser_parse_ruleset (CRParser *a_this) ;
|
|
+
|
|
+enum CRStatus cr_parser_parse_import (CRParser *a_this, GList ** a_media_list,
|
|
+ CRString **a_import_string,
|
|
+ CRParsingLocation *a_location) ;
|
|
+
|
|
+enum CRStatus cr_parser_parse_media (CRParser *a_this) ;
|
|
+
|
|
+enum CRStatus cr_parser_parse_page (CRParser *a_this) ;
|
|
+
|
|
+enum CRStatus cr_parser_parse_charset (CRParser *a_this, CRString **a_value,
|
|
+ CRParsingLocation *a_charset_sym_location) ;
|
|
+
|
|
+enum CRStatus cr_parser_parse_font_face (CRParser *a_this) ;
|
|
+
|
|
+void cr_parser_destroy (CRParser *a_this) ;
|
|
+
|
|
+G_END_DECLS
|
|
+
|
|
+#endif /*__CR_PARSER_H__*/
|
|
diff --git a/src/st/croco/cr-parsing-location.c b/src/st/croco/cr-parsing-location.c
|
|
new file mode 100644
|
|
index 000000000..4fe4acc30
|
|
--- /dev/null
|
|
+++ b/src/st/croco/cr-parsing-location.c
|
|
@@ -0,0 +1,172 @@
|
|
+/* -*- 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 the COPYRIGHTS file for copyright information.
|
|
+ */
|
|
+
|
|
+#include <string.h>
|
|
+#include "cr-parsing-location.h"
|
|
+
|
|
+/**
|
|
+ *@CRParsingLocation:
|
|
+ *
|
|
+ *Definition of the #CRparsingLocation class.
|
|
+ */
|
|
+
|
|
+
|
|
+/**
|
|
+ * cr_parsing_location_new:
|
|
+ *Instanciates a new parsing location.
|
|
+ *
|
|
+ *Returns the newly instanciated #CRParsingLocation.
|
|
+ *Must be freed by cr_parsing_location_destroy()
|
|
+ */
|
|
+CRParsingLocation *
|
|
+cr_parsing_location_new (void)
|
|
+{
|
|
+ CRParsingLocation * result = NULL ;
|
|
+
|
|
+ result = g_try_malloc (sizeof (CRParsingLocation)) ;
|
|
+ if (!result) {
|
|
+ cr_utils_trace_info ("Out of memory error") ;
|
|
+ return NULL ;
|
|
+ }
|
|
+ cr_parsing_location_init (result) ;
|
|
+ return result ;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_parsing_location_init:
|
|
+ *@a_this: the current instance of #CRParsingLocation.
|
|
+ *
|
|
+ *Initializes the an instance of #CRparsingLocation.
|
|
+ *
|
|
+ *Returns CR_OK upon succesful completion, an error code otherwise.
|
|
+ */
|
|
+enum CRStatus
|
|
+cr_parsing_location_init (CRParsingLocation *a_this)
|
|
+{
|
|
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR) ;
|
|
+
|
|
+ memset (a_this, 0, sizeof (CRParsingLocation)) ;
|
|
+ return CR_OK ;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_parsing_location_copy:
|
|
+ *@a_to: the destination of the copy.
|
|
+ *Must be allocated by the caller.
|
|
+ *@a_from: the source of the copy.
|
|
+ *
|
|
+ *Copies an instance of CRParsingLocation into another one.
|
|
+ *
|
|
+ *Returns CR_OK upon succesful completion, an error code
|
|
+ *otherwise.
|
|
+ */
|
|
+enum CRStatus
|
|
+cr_parsing_location_copy (CRParsingLocation *a_to,
|
|
+ CRParsingLocation const *a_from)
|
|
+{
|
|
+ g_return_val_if_fail (a_to && a_from, CR_BAD_PARAM_ERROR) ;
|
|
+
|
|
+ memcpy (a_to, a_from, sizeof (CRParsingLocation)) ;
|
|
+ return CR_OK ;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_parsing_location_to_string:
|
|
+ *@a_this: the current instance of #CRParsingLocation.
|
|
+ *@a_mask: a bitmap that defines which parts of the
|
|
+ *parsing location are to be serialized (line, column or byte offset)
|
|
+ *
|
|
+ *Returns the serialized string or NULL in case of an error.
|
|
+ */
|
|
+gchar *
|
|
+cr_parsing_location_to_string (CRParsingLocation const *a_this,
|
|
+ enum CRParsingLocationSerialisationMask a_mask)
|
|
+{
|
|
+ GString *result = NULL ;
|
|
+ gchar *str = NULL ;
|
|
+
|
|
+ g_return_val_if_fail (a_this, NULL) ;
|
|
+
|
|
+ if (!a_mask) {
|
|
+ a_mask = DUMP_LINE | DUMP_COLUMN | DUMP_BYTE_OFFSET ;
|
|
+ }
|
|
+ result =g_string_new (NULL) ;
|
|
+ if (!result)
|
|
+ return NULL ;
|
|
+ if (a_mask & DUMP_LINE) {
|
|
+ g_string_append_printf (result, "line:%d ",
|
|
+ a_this->line) ;
|
|
+ }
|
|
+ if (a_mask & DUMP_COLUMN) {
|
|
+ g_string_append_printf (result, "column:%d ",
|
|
+ a_this->column) ;
|
|
+ }
|
|
+ if (a_mask & DUMP_BYTE_OFFSET) {
|
|
+ g_string_append_printf (result, "byte offset:%d ",
|
|
+ a_this->byte_offset) ;
|
|
+ }
|
|
+ if (result->len) {
|
|
+ str = result->str ;
|
|
+ g_string_free (result, FALSE) ;
|
|
+ } else {
|
|
+ g_string_free (result, TRUE) ;
|
|
+ }
|
|
+ return str ;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_parsing_location_dump:
|
|
+ * @a_this: current instance of #CRParsingLocation
|
|
+ * @a_mask: the serialization mask.
|
|
+ * @a_fp: the file pointer to dump the parsing location to.
|
|
+ */
|
|
+void
|
|
+cr_parsing_location_dump (CRParsingLocation const *a_this,
|
|
+ enum CRParsingLocationSerialisationMask a_mask,
|
|
+ FILE *a_fp)
|
|
+{
|
|
+ gchar *str = NULL ;
|
|
+
|
|
+ g_return_if_fail (a_this && a_fp) ;
|
|
+ str = cr_parsing_location_to_string (a_this, a_mask) ;
|
|
+ if (str) {
|
|
+ fprintf (a_fp, "%s", str) ;
|
|
+ g_free (str) ;
|
|
+ str = NULL ;
|
|
+ }
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_parsing_location_destroy:
|
|
+ *@a_this: the current instance of #CRParsingLocation. Must
|
|
+ *have been allocated with cr_parsing_location_new().
|
|
+ *
|
|
+ *Destroys the current instance of #CRParsingLocation
|
|
+ */
|
|
+void
|
|
+cr_parsing_location_destroy (CRParsingLocation *a_this)
|
|
+{
|
|
+ g_return_if_fail (a_this) ;
|
|
+ g_free (a_this) ;
|
|
+}
|
|
+
|
|
diff --git a/src/st/croco/cr-parsing-location.h b/src/st/croco/cr-parsing-location.h
|
|
new file mode 100644
|
|
index 000000000..b8064a560
|
|
--- /dev/null
|
|
+++ b/src/st/croco/cr-parsing-location.h
|
|
@@ -0,0 +1,70 @@
|
|
+/* -*- 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 the COPYRIGHTS file for copyright information.
|
|
+ */
|
|
+
|
|
+#ifndef __CR_PARSING_LOCATION_H__
|
|
+#define __CR_PARSING_LOCATION_H__
|
|
+
|
|
+#include "cr-utils.h"
|
|
+
|
|
+G_BEGIN_DECLS
|
|
+
|
|
+/**
|
|
+ *@file
|
|
+ *The declaration of the CRParsingLocation
|
|
+ *object. This object keeps track of line/column/byte offset/
|
|
+ *at which the parsing of a given CSS construction appears.
|
|
+ */
|
|
+
|
|
+typedef struct _CRParsingLocation CRParsingLocation;
|
|
+struct _CRParsingLocation {
|
|
+ guint line ;
|
|
+ guint column ;
|
|
+ guint byte_offset ;
|
|
+} ;
|
|
+
|
|
+
|
|
+enum CRParsingLocationSerialisationMask {
|
|
+ DUMP_LINE = 1,
|
|
+ DUMP_COLUMN = 1 << 1,
|
|
+ DUMP_BYTE_OFFSET = 1 << 2
|
|
+} ;
|
|
+
|
|
+CRParsingLocation * cr_parsing_location_new (void) ;
|
|
+
|
|
+enum CRStatus cr_parsing_location_init (CRParsingLocation *a_this) ;
|
|
+
|
|
+enum CRStatus cr_parsing_location_copy (CRParsingLocation *a_to,
|
|
+ CRParsingLocation const *a_from) ;
|
|
+
|
|
+gchar * cr_parsing_location_to_string (CRParsingLocation const *a_this,
|
|
+ enum CRParsingLocationSerialisationMask a_mask) ;
|
|
+void cr_parsing_location_dump (CRParsingLocation const *a_this,
|
|
+ enum CRParsingLocationSerialisationMask a_mask,
|
|
+ FILE *a_fp) ;
|
|
+
|
|
+void cr_parsing_location_destroy (CRParsingLocation *a_this) ;
|
|
+
|
|
+
|
|
+
|
|
+G_END_DECLS
|
|
+#endif
|
|
diff --git a/src/st/croco/cr-prop-list.c b/src/st/croco/cr-prop-list.c
|
|
new file mode 100644
|
|
index 000000000..70a04f337
|
|
--- /dev/null
|
|
+++ b/src/st/croco/cr-prop-list.c
|
|
@@ -0,0 +1,404 @@
|
|
+/*
|
|
+ * 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 copyrights information.
|
|
+ */
|
|
+
|
|
+#include <string.h>
|
|
+#include "cr-prop-list.h"
|
|
+
|
|
+#define PRIVATE(a_obj) (a_obj)->priv
|
|
+
|
|
+struct _CRPropListPriv {
|
|
+ CRString *prop;
|
|
+ CRDeclaration *decl;
|
|
+ CRPropList *next;
|
|
+ CRPropList *prev;
|
|
+};
|
|
+
|
|
+static CRPropList *cr_prop_list_allocate (void);
|
|
+
|
|
+/**
|
|
+ *Default allocator of CRPropList
|
|
+ *@return the newly allocated CRPropList or NULL
|
|
+ *if an error arises.
|
|
+ */
|
|
+static CRPropList *
|
|
+cr_prop_list_allocate (void)
|
|
+{
|
|
+ CRPropList *result = NULL;
|
|
+
|
|
+ result = g_try_malloc (sizeof (CRPropList));
|
|
+ if (!result) {
|
|
+ cr_utils_trace_info ("could not allocate CRPropList");
|
|
+ return NULL;
|
|
+ }
|
|
+ memset (result, 0, sizeof (CRPropList));
|
|
+ PRIVATE (result) = g_try_malloc (sizeof (CRPropListPriv));
|
|
+ if (!result) {
|
|
+ cr_utils_trace_info ("could not allocate CRPropListPriv");
|
|
+ g_free (result);
|
|
+ return NULL;
|
|
+ }
|
|
+ memset (PRIVATE (result), 0, sizeof (CRPropListPriv));
|
|
+ return result;
|
|
+}
|
|
+
|
|
+/****************
|
|
+ *public methods
|
|
+ ***************/
|
|
+
|
|
+/**
|
|
+ * cr_prop_list_append:
|
|
+ *@a_this: the current instance of #CRPropList
|
|
+ *@a_to_append: the property list to append
|
|
+ *
|
|
+ *Appends a property list to the current one.
|
|
+ *
|
|
+ *Returns the resulting prop list, or NULL if an error
|
|
+ *occurred
|
|
+ */
|
|
+CRPropList *
|
|
+cr_prop_list_append (CRPropList * a_this, CRPropList * a_to_append)
|
|
+{
|
|
+ CRPropList *cur = NULL;
|
|
+
|
|
+ g_return_val_if_fail (a_to_append, NULL);
|
|
+
|
|
+ if (!a_this)
|
|
+ return a_to_append;
|
|
+
|
|
+ /*go fetch the last element of the list */
|
|
+ for (cur = a_this;
|
|
+ cur && PRIVATE (cur) && PRIVATE (cur)->next;
|
|
+ cur = PRIVATE (cur)->next) ;
|
|
+ g_return_val_if_fail (cur, NULL);
|
|
+ PRIVATE (cur)->next = a_to_append;
|
|
+ PRIVATE (a_to_append)->prev = cur;
|
|
+ return a_this;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_prop_list_append2:
|
|
+ *Appends a pair of prop/declaration to
|
|
+ *the current prop list.
|
|
+ *@a_this: the current instance of #CRPropList
|
|
+ *@a_prop: the property to consider
|
|
+ *@a_decl: the declaration to consider
|
|
+ *
|
|
+ *Returns the resulting property list, or NULL in case
|
|
+ *of an error.
|
|
+ */
|
|
+CRPropList *
|
|
+cr_prop_list_append2 (CRPropList * a_this,
|
|
+ CRString * a_prop,
|
|
+ CRDeclaration * a_decl)
|
|
+{
|
|
+ CRPropList *list = NULL,
|
|
+ *result = NULL;
|
|
+
|
|
+ g_return_val_if_fail (a_prop && a_decl, NULL);
|
|
+
|
|
+ list = cr_prop_list_allocate ();
|
|
+ g_return_val_if_fail (list && PRIVATE (list), NULL);
|
|
+
|
|
+ PRIVATE (list)->prop = a_prop;
|
|
+ PRIVATE (list)->decl = a_decl;
|
|
+
|
|
+ result = cr_prop_list_append (a_this, list);
|
|
+ return result;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_prop_list_prepend:
|
|
+ *@a_this: the current instance of #CRPropList
|
|
+ *@a_to_prepend: the new list to prepend.
|
|
+ *
|
|
+ *Prepends a list to the current list
|
|
+ *Returns the new properties list.
|
|
+ */
|
|
+CRPropList *
|
|
+cr_prop_list_prepend (CRPropList * a_this, CRPropList * a_to_prepend)
|
|
+{
|
|
+ CRPropList *cur = NULL;
|
|
+
|
|
+ g_return_val_if_fail (a_to_prepend, NULL);
|
|
+
|
|
+ if (!a_this)
|
|
+ return a_to_prepend;
|
|
+
|
|
+ for (cur = a_to_prepend; cur && PRIVATE (cur)->next;
|
|
+ cur = PRIVATE (cur)->next) ;
|
|
+ g_return_val_if_fail (cur, NULL);
|
|
+ PRIVATE (cur)->next = a_this;
|
|
+ PRIVATE (a_this)->prev = cur;
|
|
+ return a_to_prepend;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_prop_list_prepend2:
|
|
+ *@a_this: the current instance of #CRPropList
|
|
+ *@a_prop_name: property name to append
|
|
+ *@a_decl: the property value to append.
|
|
+ *
|
|
+ *Prepends a propertie to a list of properties
|
|
+ *
|
|
+ *Returns the new property list.
|
|
+ */
|
|
+CRPropList *
|
|
+cr_prop_list_prepend2 (CRPropList * a_this,
|
|
+ CRString * a_prop_name, CRDeclaration * a_decl)
|
|
+{
|
|
+ CRPropList *list = NULL,
|
|
+ *result = NULL;
|
|
+
|
|
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
|
|
+ && a_prop_name && a_decl, NULL);
|
|
+
|
|
+ list = cr_prop_list_allocate ();
|
|
+ g_return_val_if_fail (list, NULL);
|
|
+ PRIVATE (list)->prop = a_prop_name;
|
|
+ PRIVATE (list)->decl = a_decl;
|
|
+ result = cr_prop_list_prepend (a_this, list);
|
|
+ return result;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_prop_list_set_prop:
|
|
+ *@a_this: the current instance of #CRPropList
|
|
+ *@a_prop: the property to set
|
|
+ *
|
|
+ *Sets the property of a CRPropList
|
|
+ */
|
|
+enum CRStatus
|
|
+cr_prop_list_set_prop (CRPropList * a_this, CRString * a_prop)
|
|
+{
|
|
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
|
|
+ && a_prop, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ PRIVATE (a_this)->prop = a_prop;
|
|
+ return CR_OK;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_prop_list_get_prop:
|
|
+ *@a_this: the current instance of #CRPropList
|
|
+ *@a_prop: out parameter. The returned property
|
|
+ *
|
|
+ *Getter of the property associated to the current instance
|
|
+ *of #CRPropList
|
|
+ *
|
|
+ *Returns CR_OK upon successful completion, an error code
|
|
+ *otherwise.
|
|
+ */
|
|
+enum CRStatus
|
|
+cr_prop_list_get_prop (CRPropList const * a_this, CRString ** a_prop)
|
|
+{
|
|
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
|
|
+ && a_prop, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ *a_prop = PRIVATE (a_this)->prop;
|
|
+ return CR_OK;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_prop_list_set_decl:
|
|
+ * @a_this: the current instance of #CRPropList
|
|
+ * @a_decl: the new property value.
|
|
+ *
|
|
+ * Returns CR_OK upon successful completion, an error code otherwise.
|
|
+ */
|
|
+enum CRStatus
|
|
+cr_prop_list_set_decl (CRPropList * a_this, CRDeclaration * a_decl)
|
|
+{
|
|
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
|
|
+ && a_decl, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ PRIVATE (a_this)->decl = a_decl;
|
|
+ return CR_OK;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_prop_list_get_decl:
|
|
+ * @a_this: the current instance of #CRPropList
|
|
+ * @a_decl: out parameter. The property value
|
|
+ *
|
|
+ * Returns CR_OK upon successful completion.
|
|
+ */
|
|
+enum CRStatus
|
|
+cr_prop_list_get_decl (CRPropList const * a_this, CRDeclaration ** a_decl)
|
|
+{
|
|
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
|
|
+ && a_decl, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ *a_decl = PRIVATE (a_this)->decl;
|
|
+ return CR_OK;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_prop_list_lookup_prop:
|
|
+ *@a_this: the current instance of #CRPropList
|
|
+ *@a_prop: the property to lookup
|
|
+ *@a_prop_list: out parameter. The property/declaration
|
|
+ *pair found (if and only if the function returned code if CR_OK)
|
|
+ *
|
|
+ *Lookup a given property/declaration pair
|
|
+ *
|
|
+ *Returns CR_OK if a prop/decl pair has been found,
|
|
+ *CR_VALUE_NOT_FOUND_ERROR if not, or an error code if something
|
|
+ *bad happens.
|
|
+ */
|
|
+enum CRStatus
|
|
+cr_prop_list_lookup_prop (CRPropList * a_this,
|
|
+ CRString * a_prop, CRPropList ** a_pair)
|
|
+{
|
|
+ CRPropList *cur = NULL;
|
|
+
|
|
+ g_return_val_if_fail (a_prop && a_pair, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ if (!a_this)
|
|
+ return CR_VALUE_NOT_FOUND_ERROR;
|
|
+
|
|
+ g_return_val_if_fail (PRIVATE (a_this), CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ for (cur = a_this; cur; cur = PRIVATE (cur)->next) {
|
|
+ if (PRIVATE (cur)->prop
|
|
+ && PRIVATE (cur)->prop->stryng
|
|
+ && PRIVATE (cur)->prop->stryng->str
|
|
+ && a_prop->stryng
|
|
+ && a_prop->stryng->str
|
|
+ && !strcmp (PRIVATE (cur)->prop->stryng->str,
|
|
+ a_prop->stryng->str))
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ if (cur) {
|
|
+ *a_pair = cur;
|
|
+ return CR_OK;
|
|
+ }
|
|
+
|
|
+ return CR_VALUE_NOT_FOUND_ERROR;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_prop_list_get_next:
|
|
+ *@a_this: the current instance of CRPropList
|
|
+ *
|
|
+ *Gets the next prop/decl pair in the list
|
|
+ *
|
|
+ *Returns the next prop/declaration pair of the list,
|
|
+ *or NULL if we reached end of list (or if an error occurs)
|
|
+ */
|
|
+CRPropList *
|
|
+cr_prop_list_get_next (CRPropList * a_this)
|
|
+{
|
|
+ g_return_val_if_fail (a_this && PRIVATE (a_this), NULL);
|
|
+
|
|
+ return PRIVATE (a_this)->next;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_prop_list_get_prev:
|
|
+ *@a_this: the current instance of CRPropList
|
|
+ *
|
|
+ *Gets the previous prop/decl pair in the list
|
|
+ *
|
|
+ *Returns the previous prop/declaration pair of the list,
|
|
+ *or NULL if we reached end of list (or if an error occurs)
|
|
+ */
|
|
+CRPropList *
|
|
+cr_prop_list_get_prev (CRPropList * a_this)
|
|
+{
|
|
+ g_return_val_if_fail (a_this && PRIVATE (a_this), NULL);
|
|
+
|
|
+ return PRIVATE (a_this)->prev;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_prop_list_unlink:
|
|
+ *@a_this: the current list of prop/decl pairs
|
|
+ *@a_pair: the prop/decl pair to unlink.
|
|
+ *
|
|
+ *Unlinks a prop/decl pair from the list
|
|
+ *
|
|
+ *Returns the new list or NULL in case of an error.
|
|
+ */
|
|
+CRPropList *
|
|
+cr_prop_list_unlink (CRPropList * a_this, CRPropList * a_pair)
|
|
+{
|
|
+ CRPropList *prev = NULL,
|
|
+ *next = NULL;
|
|
+
|
|
+ g_return_val_if_fail (a_this && PRIVATE (a_this) && a_pair, NULL);
|
|
+
|
|
+ /*some sanity checks */
|
|
+ if (PRIVATE (a_pair)->next) {
|
|
+ next = PRIVATE (a_pair)->next;
|
|
+ g_return_val_if_fail (PRIVATE (next), NULL);
|
|
+ g_return_val_if_fail (PRIVATE (next)->prev == a_pair, NULL);
|
|
+ }
|
|
+ if (PRIVATE (a_pair)->prev) {
|
|
+ prev = PRIVATE (a_pair)->prev;
|
|
+ g_return_val_if_fail (PRIVATE (prev), NULL);
|
|
+ g_return_val_if_fail (PRIVATE (prev)->next == a_pair, NULL);
|
|
+ }
|
|
+ if (prev) {
|
|
+ PRIVATE (prev)->next = next;
|
|
+ }
|
|
+ if (next) {
|
|
+ PRIVATE (next)->prev = prev;
|
|
+ }
|
|
+ PRIVATE (a_pair)->prev = PRIVATE (a_pair)->next = NULL;
|
|
+ if (a_this == a_pair) {
|
|
+ if (next)
|
|
+ return next;
|
|
+ return NULL;
|
|
+ }
|
|
+ return a_this;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_prop_list_destroy:
|
|
+ * @a_this: the current instance of #CRPropList
|
|
+ */
|
|
+void
|
|
+cr_prop_list_destroy (CRPropList * a_this)
|
|
+{
|
|
+ CRPropList *tail = NULL,
|
|
+ *cur = NULL;
|
|
+
|
|
+ g_return_if_fail (a_this && PRIVATE (a_this));
|
|
+
|
|
+ for (tail = a_this;
|
|
+ tail && PRIVATE (tail) && PRIVATE (tail)->next;
|
|
+ tail = cr_prop_list_get_next (tail)) ;
|
|
+ g_return_if_fail (tail);
|
|
+
|
|
+ cur = tail;
|
|
+
|
|
+ while (cur) {
|
|
+ tail = PRIVATE (cur)->prev;
|
|
+ if (tail && PRIVATE (tail))
|
|
+ PRIVATE (tail)->next = NULL;
|
|
+ PRIVATE (cur)->prev = NULL;
|
|
+ g_free (PRIVATE (cur));
|
|
+ PRIVATE (cur) = NULL;
|
|
+ g_free (cur);
|
|
+ cur = tail;
|
|
+ }
|
|
+}
|
|
diff --git a/src/st/croco/cr-prop-list.h b/src/st/croco/cr-prop-list.h
|
|
new file mode 100644
|
|
index 000000000..797ba43ea
|
|
--- /dev/null
|
|
+++ b/src/st/croco/cr-prop-list.h
|
|
@@ -0,0 +1,80 @@
|
|
+/*
|
|
+ * 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 copyrights information.
|
|
+ */
|
|
+
|
|
+#ifndef __CR_PROP_LIST_H__
|
|
+#define __CR_PROP_LIST_H__
|
|
+
|
|
+#include "cr-utils.h"
|
|
+#include "cr-declaration.h"
|
|
+#include "cr-string.h"
|
|
+
|
|
+G_BEGIN_DECLS
|
|
+
|
|
+typedef struct _CRPropList CRPropList ;
|
|
+typedef struct _CRPropListPriv CRPropListPriv ;
|
|
+
|
|
+struct _CRPropList
|
|
+{
|
|
+ CRPropListPriv * priv;
|
|
+} ;
|
|
+
|
|
+CRPropList * cr_prop_list_append (CRPropList *a_this,
|
|
+ CRPropList *a_to_append) ;
|
|
+
|
|
+CRPropList * cr_prop_list_append2 (CRPropList *a_this,
|
|
+ CRString *a_prop,
|
|
+ CRDeclaration *a_decl) ;
|
|
+
|
|
+CRPropList * cr_prop_list_prepend (CRPropList *a_this,
|
|
+ CRPropList *a_to_append) ;
|
|
+
|
|
+CRPropList * cr_prop_list_prepend2 (CRPropList *a_this,
|
|
+ CRString *a_prop,
|
|
+ CRDeclaration *a_decl) ;
|
|
+
|
|
+enum CRStatus cr_prop_list_set_prop (CRPropList *a_this,
|
|
+ CRString *a_prop) ;
|
|
+
|
|
+enum CRStatus cr_prop_list_get_prop (CRPropList const *a_this,
|
|
+ CRString **a_prop) ;
|
|
+
|
|
+enum CRStatus cr_prop_list_lookup_prop (CRPropList *a_this,
|
|
+ CRString *a_prop,
|
|
+ CRPropList**a_pair) ;
|
|
+
|
|
+CRPropList * cr_prop_list_get_next (CRPropList *a_this) ;
|
|
+
|
|
+CRPropList * cr_prop_list_get_prev (CRPropList *a_this) ;
|
|
+
|
|
+enum CRStatus cr_prop_list_set_decl (CRPropList *a_this,
|
|
+ CRDeclaration *a_decl);
|
|
+
|
|
+enum CRStatus cr_prop_list_get_decl (CRPropList const *a_this,
|
|
+ CRDeclaration **a_decl) ;
|
|
+
|
|
+CRPropList * cr_prop_list_unlink (CRPropList *a_this,
|
|
+ CRPropList *a_pair) ;
|
|
+
|
|
+void cr_prop_list_destroy (CRPropList *a_this) ;
|
|
+
|
|
+G_END_DECLS
|
|
+
|
|
+#endif /*__CR_PROP_LIST_H__*/
|
|
diff --git a/src/st/croco/cr-pseudo.c b/src/st/croco/cr-pseudo.c
|
|
new file mode 100644
|
|
index 000000000..cee3fc869
|
|
--- /dev/null
|
|
+++ b/src/st/croco/cr-pseudo.c
|
|
@@ -0,0 +1,167 @@
|
|
+/* -*- 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 "cr-pseudo.h"
|
|
+
|
|
+/**
|
|
+ *@CRPseudo:
|
|
+ *The definition of the #CRPseudo class.
|
|
+ */
|
|
+
|
|
+/**
|
|
+ * cr_pseudo_new:
|
|
+ *Constructor of the #CRPseudo class.
|
|
+ *
|
|
+ *Returns the newly build instance.
|
|
+ */
|
|
+CRPseudo *
|
|
+cr_pseudo_new (void)
|
|
+{
|
|
+ CRPseudo *result = NULL;
|
|
+
|
|
+ result = g_malloc0 (sizeof (CRPseudo));
|
|
+
|
|
+ return result;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_pseudo_to_string:
|
|
+ * @a_this: the current instance of #CRPseud.
|
|
+ *
|
|
+ * Returns the serialized pseudo. Caller must free the returned
|
|
+ * string using g_free().
|
|
+ */
|
|
+guchar *
|
|
+cr_pseudo_to_string (CRPseudo const * a_this)
|
|
+{
|
|
+ guchar *result = NULL;
|
|
+ GString *str_buf = NULL;
|
|
+
|
|
+ g_return_val_if_fail (a_this, NULL);
|
|
+
|
|
+ str_buf = g_string_new (NULL);
|
|
+
|
|
+ if (a_this->type == IDENT_PSEUDO) {
|
|
+ guchar *name = NULL;
|
|
+
|
|
+ if (a_this->name == NULL) {
|
|
+ goto error;
|
|
+ }
|
|
+
|
|
+ name = (guchar *) g_strndup (a_this->name->stryng->str,
|
|
+ a_this->name->stryng->len);
|
|
+
|
|
+ if (name) {
|
|
+ g_string_append (str_buf, (const gchar *) name);
|
|
+ g_free (name);
|
|
+ name = NULL;
|
|
+ }
|
|
+ } else if (a_this->type == FUNCTION_PSEUDO) {
|
|
+ guchar *name = NULL,
|
|
+ *arg = NULL;
|
|
+
|
|
+ if (a_this->name == NULL)
|
|
+ goto error;
|
|
+
|
|
+ name = (guchar *) g_strndup (a_this->name->stryng->str,
|
|
+ a_this->name->stryng->len);
|
|
+
|
|
+ if (a_this->extra) {
|
|
+ arg = (guchar *) g_strndup (a_this->extra->stryng->str,
|
|
+ a_this->extra->stryng->len);
|
|
+ }
|
|
+
|
|
+ if (name) {
|
|
+ g_string_append_printf (str_buf, "%s(", name);
|
|
+ g_free (name);
|
|
+ name = NULL;
|
|
+
|
|
+ if (arg) {
|
|
+ g_string_append (str_buf, (const gchar *) arg);
|
|
+ g_free (arg);
|
|
+ arg = NULL;
|
|
+ }
|
|
+
|
|
+ g_string_append_c (str_buf, ')');
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (str_buf) {
|
|
+ result = (guchar *) str_buf->str;
|
|
+ g_string_free (str_buf, FALSE);
|
|
+ str_buf = NULL;
|
|
+ }
|
|
+
|
|
+ return result;
|
|
+
|
|
+ error:
|
|
+ g_string_free (str_buf, TRUE);
|
|
+ return NULL;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_pseudo_dump:
|
|
+ *@a_this: the current instance of pseudo
|
|
+ *@a_fp: the destination file pointer.
|
|
+ *
|
|
+ *Dumps the pseudo to a file.
|
|
+ *
|
|
+ */
|
|
+void
|
|
+cr_pseudo_dump (CRPseudo const * a_this, FILE * a_fp)
|
|
+{
|
|
+ guchar *tmp_str = NULL;
|
|
+
|
|
+ if (a_this) {
|
|
+ tmp_str = cr_pseudo_to_string (a_this);
|
|
+ if (tmp_str) {
|
|
+ fprintf (a_fp, "%s", tmp_str);
|
|
+ g_free (tmp_str);
|
|
+ tmp_str = NULL;
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_pseudo_destroy:
|
|
+ *@a_this: the current instance to destroy.
|
|
+ *
|
|
+ *destructor of the #CRPseudo class.
|
|
+ */
|
|
+void
|
|
+cr_pseudo_destroy (CRPseudo * a_this)
|
|
+{
|
|
+ g_return_if_fail (a_this);
|
|
+
|
|
+ if (a_this->name) {
|
|
+ cr_string_destroy (a_this->name);
|
|
+ a_this->name = NULL;
|
|
+ }
|
|
+
|
|
+ if (a_this->extra) {
|
|
+ cr_string_destroy (a_this->extra);
|
|
+ a_this->extra = NULL;
|
|
+ }
|
|
+
|
|
+ g_free (a_this);
|
|
+}
|
|
diff --git a/src/st/croco/cr-pseudo.h b/src/st/croco/cr-pseudo.h
|
|
new file mode 100644
|
|
index 000000000..8917da45e
|
|
--- /dev/null
|
|
+++ b/src/st/croco/cr-pseudo.h
|
|
@@ -0,0 +1,64 @@
|
|
+/* -*- 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
|
|
+ *
|
|
+ * See COPYRIGHTS file for copyright information
|
|
+ */
|
|
+
|
|
+#ifndef __CR_PSEUDO_H__
|
|
+#define __CR_PSEUDO_H__
|
|
+
|
|
+#include <stdio.h>
|
|
+#include <glib.h>
|
|
+#include "cr-attr-sel.h"
|
|
+#include "cr-parsing-location.h"
|
|
+
|
|
+G_BEGIN_DECLS
|
|
+
|
|
+enum CRPseudoType
|
|
+{
|
|
+ IDENT_PSEUDO = 0,
|
|
+ FUNCTION_PSEUDO
|
|
+} ;
|
|
+
|
|
+typedef struct _CRPseudo CRPseudo ;
|
|
+
|
|
+/**
|
|
+ *The CRPseudo Class.
|
|
+ *Abstract a "pseudo" as defined by the css2 spec
|
|
+ *in appendix D.1 .
|
|
+ */
|
|
+struct _CRPseudo
|
|
+{
|
|
+ enum CRPseudoType type ;
|
|
+ CRString *name ;
|
|
+ CRString *extra ;
|
|
+ CRParsingLocation location ;
|
|
+} ;
|
|
+
|
|
+CRPseudo * cr_pseudo_new (void) ;
|
|
+
|
|
+guchar * cr_pseudo_to_string (CRPseudo const *a_this) ;
|
|
+
|
|
+void cr_pseudo_dump (CRPseudo const *a_this, FILE *a_fp) ;
|
|
+
|
|
+void cr_pseudo_destroy (CRPseudo *a_this) ;
|
|
+
|
|
+G_END_DECLS
|
|
+
|
|
+#endif /*__CR_PSEUDO_H__*/
|
|
diff --git a/src/st/croco/cr-rgb.c b/src/st/croco/cr-rgb.c
|
|
new file mode 100644
|
|
index 000000000..1b8b66256
|
|
--- /dev/null
|
|
+++ b/src/st/croco/cr-rgb.c
|
|
@@ -0,0 +1,687 @@
|
|
+/* -*- 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 copyrights information.
|
|
+ */
|
|
+
|
|
+#include "config.h"
|
|
+
|
|
+#include <stdio.h>
|
|
+#include <string.h>
|
|
+#include <stdlib.h>
|
|
+#include "cr-rgb.h"
|
|
+#include "cr-term.h"
|
|
+#include "cr-parser.h"
|
|
+
|
|
+static const CRRgb gv_standard_colors[] = {
|
|
+ {(const guchar*)"aliceblue", 240, 248, 255, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"antiquewhite", 250, 235, 215, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"aqua", 0, 255, 255, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"aquamarine", 127, 255, 212, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"azure", 240, 255, 255, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"beige", 245, 245, 220, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"bisque", 255, 228, 196, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"black", 0, 0, 0, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"blanchedalmond", 255, 235, 205, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"blue", 0, 0, 255, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"blueviolet", 138, 43, 226, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"brown", 165, 42, 42, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"burlywood", 222, 184, 135, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"cadetblue", 95, 158, 160, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"chartreuse", 127, 255, 0, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"chocolate", 210, 105, 30, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"coral", 255, 127, 80, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"cornflowerblue", 100, 149, 237, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"cornsilk", 255, 248, 220, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"crimson", 220, 20, 60, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"cyan", 0, 255, 255, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"darkblue", 0, 0, 139, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"darkcyan", 0, 139, 139, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"darkgoldenrod", 184, 134, 11, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"darkgray", 169, 169, 169, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"darkgreen", 0, 100, 0, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"darkgrey", 169, 169, 169, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"darkkhaki", 189, 183, 107, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"darkmagenta", 139, 0, 139, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"darkolivegreen", 85, 107, 47, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"darkorange", 255, 140, 0, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"darkorchid", 153, 50, 204, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"darkred", 139, 0, 0, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"darksalmon", 233, 150, 122, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"darkseagreen", 143, 188, 143, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"darkslateblue", 72, 61, 139, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"darkslategray", 47, 79, 79, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"darkslategrey", 47, 79, 79, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"darkturquoise", 0, 206, 209, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"darkviolet", 148, 0, 211, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"deeppink", 255, 20, 147, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"deepskyblue", 0, 191, 255, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"dimgray", 105, 105, 105, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"dimgrey", 105, 105, 105, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"dodgerblue", 30, 144, 255, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"firebrick", 178, 34, 34, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"floralwhite", 255, 250, 240, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"forestgreen", 34, 139, 34, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"fuchsia", 255, 0, 255, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"gainsboro", 220, 220, 220, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"ghostwhite", 248, 248, 255, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"gold", 255, 215, 0, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"goldenrod", 218, 165, 32, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"gray", 128, 128, 128, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"green", 0, 128, 0, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"greenyellow", 173, 255, 47, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"grey", 128, 128, 128, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"honeydew", 240, 255, 240, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"hotpink", 255, 105, 180, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"indianred", 205, 92, 92, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"indigo", 75, 0, 130, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"ivory", 255, 255, 240, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"khaki", 240, 230, 140, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"lavender", 230, 230, 250, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"lavenderblush", 255, 240, 245, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"lawngreen", 124, 252, 0, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"lemonchiffon", 255, 250, 205, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"lightblue", 173, 216, 230, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"lightcoral", 240, 128, 128, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"lightcyan", 224, 255, 255, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"lightgoldenrodyellow", 250, 250, 210, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"lightgray", 211, 211, 211, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"lightgreen", 144, 238, 144, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"lightgrey", 211, 211, 211, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"lightpink", 255, 182, 193, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"lightsalmon", 255, 160, 122, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"lightseagreen", 32, 178, 170, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"lightskyblue", 135, 206, 250, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"lightslategray", 119, 136, 153, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"lightslategrey", 119, 136, 153, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"lightsteelblue", 176, 196, 222, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"lightyellow", 255, 255, 224, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"lime", 0, 255, 0, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"limegreen", 50, 205, 50, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"linen", 250, 240, 230, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"magenta", 255, 0, 255, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"maroon", 128, 0, 0, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"mediumaquamarine", 102, 205, 170, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"mediumblue", 0, 0, 205, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"mediumorchid", 186, 85, 211, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"mediumpurple", 147, 112, 219, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"mediumseagreen", 60, 179, 113, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"mediumslateblue", 123, 104, 238, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"mediumspringgreen", 0, 250, 154, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"mediumturquoise", 72, 209, 204, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"mediumvioletred", 199, 21, 133, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"midnightblue", 25, 25, 112, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"mintcream", 245, 255, 250, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"mistyrose", 255, 228, 225, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"moccasin", 255, 228, 181, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"navajowhite", 255, 222, 173, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"navy", 0, 0, 128, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"oldlace", 253, 245, 230, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"olive", 128, 128, 0, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"olivedrab", 107, 142, 35, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"orange", 255, 165, 0, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"orangered", 255, 69, 0, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"orchid", 218, 112, 214, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"palegoldenrod", 238, 232, 170, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"palegreen", 152, 251, 152, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"paleturquoise", 175, 238, 238, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"palevioletred", 219, 112, 147, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"papayawhip", 255, 239, 213, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"peachpuff", 255, 218, 185, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"peru", 205, 133, 63, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"pink", 255, 192, 203, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"plum", 221, 160, 221, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"powderblue", 176, 224, 230, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"purple", 128, 0, 128, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"red", 255, 0, 0, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"rosybrown", 188, 143, 143, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"royalblue", 65, 105, 225, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"saddlebrown", 139, 69, 19, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"salmon", 250, 128, 114, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"sandybrown", 244, 164, 96, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"seagreen", 46, 139, 87, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"seashell", 255, 245, 238, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"sienna", 160, 82, 45, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"silver", 192, 192, 192, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"skyblue", 135, 206, 235, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"slateblue", 106, 90, 205, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"slategray", 112, 128, 144, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"slategrey", 112, 128, 144, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"snow", 255, 250, 250, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"springgreen", 0, 255, 127, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"steelblue", 70, 130, 180, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"tan", 210, 180, 140, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"teal", 0, 128, 128, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"thistle", 216, 191, 216, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"tomato", 255, 99, 71, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"transparent", 255, 255, 255, FALSE, FALSE, TRUE, {0,0,0}},
|
|
+ {(const guchar*)"turquoise", 64, 224, 208, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"violet", 238, 130, 238, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"wheat", 245, 222, 179, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"white", 255, 255, 255, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"whitesmoke", 245, 245, 245, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"yellow", 255, 255, 0, FALSE, FALSE, FALSE, {0,0,0}},
|
|
+ {(const guchar*)"yellowgreen", 154, 205, 50, FALSE, FALSE, FALSE, {0,0,0}}
|
|
+};
|
|
+
|
|
+/**
|
|
+ * cr_rgb_new:
|
|
+ *
|
|
+ *The default constructor of #CRRgb.
|
|
+ *
|
|
+ *Returns the newly built instance of #CRRgb
|
|
+ */
|
|
+CRRgb *
|
|
+cr_rgb_new (void)
|
|
+{
|
|
+ CRRgb *result = NULL;
|
|
+
|
|
+ result = g_try_malloc (sizeof (CRRgb));
|
|
+
|
|
+ if (result == NULL) {
|
|
+ cr_utils_trace_info ("No more memory");
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
+ memset (result, 0, sizeof (CRRgb));
|
|
+
|
|
+ return result;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_rgb_new_with_vals:
|
|
+ *@a_red: the red component of the color.
|
|
+ *@a_green: the green component of the color.
|
|
+ *@a_blue: the blue component of the color.
|
|
+ *@a_unit: the unit of the rgb values.
|
|
+ *(either percentage or integer values)
|
|
+ *
|
|
+ *A constructor of #CRRgb.
|
|
+ *
|
|
+ *Returns the newly built instance of #CRRgb.
|
|
+ */
|
|
+CRRgb *
|
|
+cr_rgb_new_with_vals (gulong a_red, gulong a_green,
|
|
+ gulong a_blue, gboolean a_is_percentage)
|
|
+{
|
|
+ CRRgb *result = NULL;
|
|
+
|
|
+ result = cr_rgb_new ();
|
|
+
|
|
+ g_return_val_if_fail (result, NULL);
|
|
+
|
|
+ result->red = a_red;
|
|
+ result->green = a_green;
|
|
+ result->blue = a_blue;
|
|
+ result->is_percentage = a_is_percentage;
|
|
+
|
|
+ return result;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_rgb_to_string:
|
|
+ *@a_this: the instance of #CRRgb to serialize.
|
|
+ *
|
|
+ *Serializes the rgb into a zero terminated string.
|
|
+ *
|
|
+ *Returns the zero terminated string containing the serialized
|
|
+ *rgb. MUST BE FREED by the caller using g_free().
|
|
+ */
|
|
+guchar *
|
|
+cr_rgb_to_string (CRRgb const * a_this)
|
|
+{
|
|
+ guchar *result = NULL;
|
|
+ GString *str_buf = NULL;
|
|
+
|
|
+ str_buf = g_string_new (NULL);
|
|
+ g_return_val_if_fail (str_buf, NULL);
|
|
+
|
|
+ if (a_this->is_percentage == 1) {
|
|
+ g_string_append_printf (str_buf, "%ld", a_this->red);
|
|
+
|
|
+ g_string_append (str_buf, "%, ");
|
|
+
|
|
+ g_string_append_printf (str_buf, "%ld", a_this->green);
|
|
+ g_string_append (str_buf, "%, ");
|
|
+
|
|
+ g_string_append_printf (str_buf, "%ld", a_this->blue);
|
|
+ g_string_append_c (str_buf, '%');
|
|
+ } else {
|
|
+ g_string_append_printf (str_buf, "%ld", a_this->red);
|
|
+ g_string_append (str_buf, ", ");
|
|
+
|
|
+ g_string_append_printf (str_buf, "%ld", a_this->green);
|
|
+ g_string_append (str_buf, ", ");
|
|
+
|
|
+ g_string_append_printf (str_buf, "%ld", a_this->blue);
|
|
+ }
|
|
+
|
|
+ if (str_buf) {
|
|
+ result = (guchar *) str_buf->str;
|
|
+ g_string_free (str_buf, FALSE);
|
|
+ }
|
|
+
|
|
+ return result;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_rgb_dump:
|
|
+ *@a_this: the "this pointer" of
|
|
+ *the current instance of #CRRgb.
|
|
+ *@a_fp: the destination file pointer.
|
|
+ *
|
|
+ *Dumps the current instance of #CRRgb
|
|
+ *to a file.
|
|
+ */
|
|
+void
|
|
+cr_rgb_dump (CRRgb const * a_this, FILE * a_fp)
|
|
+{
|
|
+ guchar *str = NULL;
|
|
+
|
|
+ g_return_if_fail (a_this);
|
|
+
|
|
+ str = cr_rgb_to_string (a_this);
|
|
+
|
|
+ if (str) {
|
|
+ fprintf (a_fp, "%s", str);
|
|
+ g_free (str);
|
|
+ str = NULL;
|
|
+ }
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_rgb_compute_from_percentage:
|
|
+ *@a_this: the current instance of #CRRgb
|
|
+ *
|
|
+ *If the rgb values are expressed in percentage,
|
|
+ *compute their real value.
|
|
+ *
|
|
+ *Returns CR_OK upon successful completion, an error code otherwise.
|
|
+ */
|
|
+enum CRStatus
|
|
+cr_rgb_compute_from_percentage (CRRgb * a_this)
|
|
+{
|
|
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ if (a_this->is_percentage == FALSE)
|
|
+ return CR_OK;
|
|
+ a_this->red = a_this->red * 255 / 100;
|
|
+ a_this->green = a_this->green * 255 / 100;
|
|
+ a_this->blue = a_this->blue * 255 / 100;
|
|
+ a_this->is_percentage = FALSE;
|
|
+ return CR_OK;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_rgb_set:
|
|
+ *@a_this: the current instance of #CRRgb.
|
|
+ *@a_red: the red value.
|
|
+ *@a_green: the green value.
|
|
+ *@a_blue: the blue value.
|
|
+ *
|
|
+ *Sets rgb values to the RGB.
|
|
+ *
|
|
+ *Returns CR_OK upon successful completion, an error code
|
|
+ *otherwise.
|
|
+ */
|
|
+enum CRStatus
|
|
+cr_rgb_set (CRRgb * a_this, gulong a_red,
|
|
+ gulong a_green, gulong a_blue, gboolean a_is_percentage)
|
|
+{
|
|
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
|
|
+ if (a_is_percentage != FALSE) {
|
|
+ g_return_val_if_fail (a_red <= 100
|
|
+ && a_green <= 100
|
|
+ && a_blue <= 100, CR_BAD_PARAM_ERROR);
|
|
+ }
|
|
+
|
|
+ a_this->is_percentage = a_is_percentage;
|
|
+
|
|
+ a_this->red = a_red;
|
|
+ a_this->green = a_green;
|
|
+ a_this->blue = a_blue;
|
|
+ a_this->inherit = FALSE ;
|
|
+ a_this->is_transparent = FALSE ;
|
|
+ return CR_OK;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_rgb_set_to_inherit:
|
|
+ *@a_this: the current instance of #CRRgb
|
|
+ *
|
|
+ *sets the value of the rgb to inherit.
|
|
+ *Look at the css spec from chapter 6.1 to 6.2 to understand
|
|
+ *the meaning of "inherit".
|
|
+ *
|
|
+ * Returns CR_OK upon succesful completion, an error code otherwise.
|
|
+ */
|
|
+enum CRStatus
|
|
+cr_rgb_set_to_inherit (CRRgb *a_this, gboolean a_inherit)
|
|
+{
|
|
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR) ;
|
|
+
|
|
+ a_this->inherit = a_inherit ;
|
|
+
|
|
+ return CR_OK ;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_rgb_is_set_to_inherit:
|
|
+ *
|
|
+ * @a_this: the current instance of #CRRgb.
|
|
+ *
|
|
+ * Returns TRUE if the rgb is set to the value "inherit", FALSE otherwise.
|
|
+ */
|
|
+gboolean
|
|
+cr_rgb_is_set_to_inherit (CRRgb const *a_this)
|
|
+{
|
|
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR) ;
|
|
+
|
|
+ return a_this->inherit ;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_rgb_is_set_to_transparent:
|
|
+ *@a_this: the current instance of
|
|
+ *#CRRgb
|
|
+ *
|
|
+ *Tests if the the rgb is set to the
|
|
+ *value "transparent" or not.
|
|
+ *
|
|
+ *Returns TRUE if the rgb has been set to
|
|
+ *transparent, FALSE otherwise.
|
|
+ */
|
|
+gboolean
|
|
+cr_rgb_is_set_to_transparent (CRRgb const *a_this)
|
|
+{
|
|
+ g_return_val_if_fail (a_this, FALSE) ;
|
|
+ return a_this->is_transparent ;
|
|
+}
|
|
+
|
|
+
|
|
+/**
|
|
+ * cr_rgb_set_to_transparent:
|
|
+ *@a_this: the current instance of #CRRgb
|
|
+ *@a_is_transparent: set to transparent or not.
|
|
+ *
|
|
+ *Sets the rgb to the "transparent" value (or not)
|
|
+ *Returns CR_OK upon successfull completion, an error code otherwise.
|
|
+ */
|
|
+enum CRStatus
|
|
+cr_rgb_set_to_transparent (CRRgb *a_this,
|
|
+ gboolean a_is_transparent)
|
|
+{
|
|
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR) ;
|
|
+ a_this->is_transparent = a_is_transparent ;
|
|
+ return CR_OK ;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_rgb_set_from_rgb:
|
|
+ *@a_this: the current instance of #CRRgb.
|
|
+ *@a_rgb: the rgb to "copy"
|
|
+ *
|
|
+ *Sets the rgb from an other one.
|
|
+ *
|
|
+ *Returns CR_OK upon successful completion, an error code otherwise.
|
|
+ */
|
|
+enum CRStatus
|
|
+cr_rgb_set_from_rgb (CRRgb * a_this, CRRgb const * a_rgb)
|
|
+{
|
|
+ g_return_val_if_fail (a_this && a_rgb, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ cr_rgb_copy (a_this, a_rgb) ;
|
|
+
|
|
+ return CR_OK;
|
|
+}
|
|
+
|
|
+static int
|
|
+cr_rgb_color_name_compare (const void *a,
|
|
+ const void *b)
|
|
+{
|
|
+ const char *a_color_name = a;
|
|
+ const CRRgb *rgb = b;
|
|
+
|
|
+ return g_ascii_strcasecmp (a_color_name, (const char *) rgb->name);
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_rgb_set_from_name:
|
|
+ * @a_this: the current instance of #CRRgb
|
|
+ * @a_color_name: the color name
|
|
+ *
|
|
+ * Returns CR_OK upon successful completion, an error code otherwise.
|
|
+ */
|
|
+enum CRStatus
|
|
+cr_rgb_set_from_name (CRRgb * a_this, const guchar * a_color_name)
|
|
+{
|
|
+ enum CRStatus status = CR_OK;
|
|
+ CRRgb *result;
|
|
+
|
|
+ g_return_val_if_fail (a_this && a_color_name, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ result = bsearch (a_color_name,
|
|
+ gv_standard_colors,
|
|
+ G_N_ELEMENTS (gv_standard_colors),
|
|
+ sizeof (gv_standard_colors[0]),
|
|
+ cr_rgb_color_name_compare);
|
|
+ if (result != NULL)
|
|
+ cr_rgb_set_from_rgb (a_this, result);
|
|
+ else
|
|
+ status = CR_UNKNOWN_TYPE_ERROR;
|
|
+
|
|
+ return status;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_rgb_set_from_hex_str:
|
|
+ * @a_this: the current instance of #CRRgb
|
|
+ * @a_hex: the hexadecimal value to set.
|
|
+ *
|
|
+ * Returns CR_OK upon successful completion.
|
|
+ */
|
|
+enum CRStatus
|
|
+cr_rgb_set_from_hex_str (CRRgb * a_this, const guchar * a_hex)
|
|
+{
|
|
+ enum CRStatus status = CR_OK;
|
|
+ gulong i = 0;
|
|
+ guchar colors[3] = { 0 };
|
|
+
|
|
+ g_return_val_if_fail (a_this && a_hex, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ if (strlen ((const char *) a_hex) == 3) {
|
|
+ for (i = 0; i < 3; i++) {
|
|
+ if (a_hex[i] >= '0' && a_hex[i] <= '9') {
|
|
+ colors[i] = a_hex[i] - '0';
|
|
+ colors[i] = (colors[i] << 4) | colors[i];
|
|
+ } else if (a_hex[i] >= 'a' && a_hex[i] <= 'z') {
|
|
+ colors[i] = 10 + a_hex[i] - 'a';
|
|
+ colors[i] = (colors[i] << 4) | colors[i];
|
|
+ } else if (a_hex[i] >= 'A' && a_hex[i] <= 'Z') {
|
|
+ colors[i] = 10 + a_hex[i] - 'A';
|
|
+ colors[i] = (colors[i] << 4) | colors[i];
|
|
+ } else {
|
|
+ status = CR_UNKNOWN_TYPE_ERROR;
|
|
+ }
|
|
+ }
|
|
+ } else if (strlen ((const char *) a_hex) == 6) {
|
|
+ for (i = 0; i < 6; i++) {
|
|
+ if (a_hex[i] >= '0' && a_hex[i] <= '9') {
|
|
+ colors[i / 2] <<= 4;
|
|
+ colors[i / 2] |= a_hex[i] - '0';
|
|
+ status = CR_OK;
|
|
+ } else if (a_hex[i] >= 'a' && a_hex[i] <= 'z') {
|
|
+ colors[i / 2] <<= 4;
|
|
+ colors[i / 2] |= 10 + a_hex[i] - 'a';
|
|
+ status = CR_OK;
|
|
+ } else if (a_hex[i] >= 'A' && a_hex[i] <= 'Z') {
|
|
+ colors[i / 2] <<= 4;
|
|
+ colors[i / 2] |= 10 + a_hex[i] - 'A';
|
|
+ status = CR_OK;
|
|
+ } else {
|
|
+ status = CR_UNKNOWN_TYPE_ERROR;
|
|
+ }
|
|
+ }
|
|
+ } else {
|
|
+ status = CR_UNKNOWN_TYPE_ERROR;
|
|
+ }
|
|
+
|
|
+ if (status == CR_OK) {
|
|
+ status = cr_rgb_set (a_this, colors[0],
|
|
+ colors[1], colors[2], FALSE);
|
|
+ cr_rgb_set_to_transparent (a_this, FALSE) ;
|
|
+ }
|
|
+ return status;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_rgb_set_from_term:
|
|
+ *@a_this: the instance of #CRRgb to set
|
|
+ *@a_value: the terminal from which to set
|
|
+ *
|
|
+ *Set the rgb from a terminal symbol
|
|
+ *
|
|
+ * Returns CR_OK upon successful completion, an error code otherwise.
|
|
+ */
|
|
+enum CRStatus
|
|
+cr_rgb_set_from_term (CRRgb *a_this, const struct _CRTerm *a_value)
|
|
+{
|
|
+ enum CRStatus status = CR_OK ;
|
|
+ g_return_val_if_fail (a_this && a_value,
|
|
+ CR_BAD_PARAM_ERROR) ;
|
|
+
|
|
+ switch(a_value->type) {
|
|
+ case TERM_RGB:
|
|
+ if (a_value->content.rgb) {
|
|
+ cr_rgb_set_from_rgb
|
|
+ (a_this, a_value->content.rgb) ;
|
|
+ }
|
|
+ break ;
|
|
+ case TERM_IDENT:
|
|
+ if (a_value->content.str
|
|
+ && a_value->content.str->stryng
|
|
+ && a_value->content.str->stryng->str) {
|
|
+ if (!strncmp ("inherit",
|
|
+ a_value->content.str->stryng->str,
|
|
+ sizeof ("inherit")-1)) {
|
|
+ a_this->inherit = TRUE;
|
|
+ a_this->is_transparent = FALSE ;
|
|
+ } else {
|
|
+ status = cr_rgb_set_from_name
|
|
+ (a_this,
|
|
+ (const guchar *) a_value->content.str->stryng->str) ;
|
|
+ }
|
|
+ } else {
|
|
+ cr_utils_trace_info
|
|
+ ("a_value has NULL string value") ;
|
|
+ }
|
|
+ break ;
|
|
+ case TERM_HASH:
|
|
+ if (a_value->content.str
|
|
+ && a_value->content.str->stryng
|
|
+ && a_value->content.str->stryng->str) {
|
|
+ status = cr_rgb_set_from_hex_str
|
|
+ (a_this,
|
|
+ (const guchar *) a_value->content.str->stryng->str) ;
|
|
+ } else {
|
|
+ cr_utils_trace_info
|
|
+ ("a_value has NULL string value") ;
|
|
+ }
|
|
+ break ;
|
|
+ default:
|
|
+ status = CR_UNKNOWN_TYPE_ERROR ;
|
|
+ }
|
|
+ return status ;
|
|
+}
|
|
+
|
|
+enum CRStatus
|
|
+cr_rgb_copy (CRRgb *a_dest, CRRgb const *a_src)
|
|
+{
|
|
+ g_return_val_if_fail (a_dest && a_src,
|
|
+ CR_BAD_PARAM_ERROR) ;
|
|
+
|
|
+ memcpy (a_dest, a_src, sizeof (CRRgb)) ;
|
|
+ return CR_OK ;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_rgb_destroy:
|
|
+ *@a_this: the "this pointer" of the
|
|
+ *current instance of #CRRgb.
|
|
+ *
|
|
+ *Destructor of #CRRgb.
|
|
+ */
|
|
+void
|
|
+cr_rgb_destroy (CRRgb * a_this)
|
|
+{
|
|
+ g_return_if_fail (a_this);
|
|
+ g_free (a_this);
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_rgb_parse_from_buf:
|
|
+ *@a_str: a string that contains a color description
|
|
+ *@a_enc: the encoding of a_str
|
|
+ *
|
|
+ *Parses a text buffer that contains a rgb color
|
|
+ *
|
|
+ *Returns the parsed color, or NULL in case of error
|
|
+ */
|
|
+CRRgb *
|
|
+cr_rgb_parse_from_buf (const guchar *a_str,
|
|
+ enum CREncoding a_enc)
|
|
+{
|
|
+ enum CRStatus status = CR_OK ;
|
|
+ CRTerm *value = NULL ;
|
|
+ CRParser * parser = NULL;
|
|
+ CRRgb *result = NULL;
|
|
+
|
|
+ g_return_val_if_fail (a_str, NULL);
|
|
+
|
|
+ parser = cr_parser_new_from_buf ((guchar *) a_str, strlen ((const char *) a_str), a_enc, FALSE);
|
|
+
|
|
+ g_return_val_if_fail (parser, NULL);
|
|
+
|
|
+ status = cr_parser_try_to_skip_spaces_and_comments (parser) ;
|
|
+ if (status != CR_OK)
|
|
+ goto cleanup;
|
|
+
|
|
+ status = cr_parser_parse_term (parser, &value);
|
|
+ if (status != CR_OK)
|
|
+ goto cleanup;
|
|
+
|
|
+ result = cr_rgb_new ();
|
|
+ if (!result)
|
|
+ goto cleanup;
|
|
+
|
|
+ status = cr_rgb_set_from_term (result, value);
|
|
+
|
|
+cleanup:
|
|
+ if (parser) {
|
|
+ cr_parser_destroy (parser);
|
|
+ parser = NULL;
|
|
+ }
|
|
+ if (value) {
|
|
+ cr_term_destroy(value);
|
|
+ value = NULL;
|
|
+ }
|
|
+ return result ;
|
|
+}
|
|
+
|
|
diff --git a/src/st/croco/cr-rgb.h b/src/st/croco/cr-rgb.h
|
|
new file mode 100644
|
|
index 000000000..a127a440e
|
|
--- /dev/null
|
|
+++ b/src/st/croco/cr-rgb.h
|
|
@@ -0,0 +1,94 @@
|
|
+/* -*- 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
|
|
+ *
|
|
+ * see COPYRIGHTS file for copyright information.
|
|
+ */
|
|
+
|
|
+#ifndef __CR_RGB_H__
|
|
+#define __CR_RGB_H__
|
|
+
|
|
+#include <stdio.h>
|
|
+#include <glib.h>
|
|
+#include "cr-utils.h"
|
|
+#include "cr-parsing-location.h"
|
|
+
|
|
+G_BEGIN_DECLS
|
|
+
|
|
+
|
|
+typedef struct _CRRgb CRRgb ;
|
|
+struct _CRRgb
|
|
+{
|
|
+ /*
|
|
+ *the unit of the rgb.
|
|
+ *Either NO_UNIT (integer) or
|
|
+ *UNIT_PERCENTAGE (percentage).
|
|
+ */
|
|
+ const guchar *name ;
|
|
+ glong red ;
|
|
+ glong green ;
|
|
+ glong blue ;
|
|
+ gboolean is_percentage ;
|
|
+ gboolean inherit ;
|
|
+ gboolean is_transparent ;
|
|
+ CRParsingLocation location ;
|
|
+} ;
|
|
+
|
|
+CRRgb * cr_rgb_new (void) ;
|
|
+
|
|
+CRRgb * cr_rgb_new_with_vals (gulong a_red, gulong a_green,
|
|
+ gulong a_blue, gboolean a_is_percentage) ;
|
|
+
|
|
+CRRgb *cr_rgb_parse_from_buf(const guchar *a_str,
|
|
+ enum CREncoding a_enc);
|
|
+
|
|
+enum CRStatus cr_rgb_compute_from_percentage (CRRgb *a_this) ;
|
|
+
|
|
+enum CRStatus cr_rgb_set (CRRgb *a_this, gulong a_red,
|
|
+ gulong a_green, gulong a_blue,
|
|
+ gboolean a_is_percentage) ;
|
|
+
|
|
+enum CRStatus cr_rgb_copy (CRRgb *a_dest, CRRgb const *a_src) ;
|
|
+
|
|
+enum CRStatus cr_rgb_set_to_inherit (CRRgb *a_this, gboolean a_inherit) ;
|
|
+
|
|
+gboolean cr_rgb_is_set_to_inherit (CRRgb const *a_this) ;
|
|
+
|
|
+gboolean cr_rgb_is_set_to_transparent (CRRgb const *a_this) ;
|
|
+
|
|
+enum CRStatus cr_rgb_set_to_transparent (CRRgb *a_this,
|
|
+ gboolean a_is_transparent) ;
|
|
+enum CRStatus cr_rgb_set_from_rgb (CRRgb *a_this, CRRgb const *a_rgb) ;
|
|
+
|
|
+enum CRStatus cr_rgb_set_from_name (CRRgb *a_this, const guchar *a_color_name) ;
|
|
+
|
|
+enum CRStatus cr_rgb_set_from_hex_str (CRRgb *a_this, const guchar * a_hex_value) ;
|
|
+
|
|
+struct _CRTerm;
|
|
+
|
|
+enum CRStatus cr_rgb_set_from_term (CRRgb *a_this, const struct _CRTerm *a_value);
|
|
+
|
|
+guchar * cr_rgb_to_string (CRRgb const *a_this) ;
|
|
+
|
|
+void cr_rgb_dump (CRRgb const *a_this, FILE *a_fp) ;
|
|
+
|
|
+void cr_rgb_destroy (CRRgb *a_this) ;
|
|
+
|
|
+G_END_DECLS
|
|
+
|
|
+#endif /*__CR_RGB_H__*/
|
|
diff --git a/src/st/croco/cr-selector.c b/src/st/croco/cr-selector.c
|
|
new file mode 100644
|
|
index 000000000..8902e1c0f
|
|
--- /dev/null
|
|
+++ b/src/st/croco/cr-selector.c
|
|
@@ -0,0 +1,306 @@
|
|
+/* -*- 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
|
|
+ *
|
|
+ * See COPYRIGHTS file for copyright information.
|
|
+ */
|
|
+
|
|
+#include <string.h>
|
|
+#include "cr-selector.h"
|
|
+#include "cr-parser.h"
|
|
+
|
|
+/**
|
|
+ * cr_selector_new:
|
|
+ *
|
|
+ *@a_simple_sel: the initial simple selector list
|
|
+ *of the current instance of #CRSelector.
|
|
+ *
|
|
+ *Creates a new instance of #CRSelector.
|
|
+ *
|
|
+ *Returns the newly built instance of #CRSelector, or
|
|
+ *NULL in case of failure.
|
|
+ */
|
|
+CRSelector *
|
|
+cr_selector_new (CRSimpleSel * a_simple_sel)
|
|
+{
|
|
+ CRSelector *result = NULL;
|
|
+
|
|
+ result = g_try_malloc (sizeof (CRSelector));
|
|
+ if (!result) {
|
|
+ cr_utils_trace_info ("Out of memory");
|
|
+ return NULL;
|
|
+ }
|
|
+ memset (result, 0, sizeof (CRSelector));
|
|
+ result->simple_sel = a_simple_sel;
|
|
+ return result;
|
|
+}
|
|
+
|
|
+CRSelector *
|
|
+cr_selector_parse_from_buf (const guchar * a_char_buf, enum CREncoding a_enc)
|
|
+{
|
|
+ CRParser *parser = NULL;
|
|
+
|
|
+ g_return_val_if_fail (a_char_buf, NULL);
|
|
+
|
|
+ parser = cr_parser_new_from_buf ((guchar*)a_char_buf, strlen ((const char *) a_char_buf),
|
|
+ a_enc, FALSE);
|
|
+ g_return_val_if_fail (parser, NULL);
|
|
+
|
|
+ return NULL;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_selector_append:
|
|
+ *
|
|
+ *@a_this: the current instance of #CRSelector.
|
|
+ *@a_new: the instance of #CRSelector to be appended.
|
|
+ *
|
|
+ *Appends a new instance of #CRSelector to the current selector list.
|
|
+ *
|
|
+ *Returns the new list.
|
|
+ */
|
|
+CRSelector *
|
|
+cr_selector_append (CRSelector * a_this, CRSelector * a_new)
|
|
+{
|
|
+ CRSelector *cur = NULL;
|
|
+
|
|
+ if (!a_this) {
|
|
+ return a_new;
|
|
+ }
|
|
+
|
|
+ /*walk forward the list headed by a_this to get the list tail */
|
|
+ for (cur = a_this; cur && cur->next; cur = cur->next) ;
|
|
+
|
|
+ cur->next = a_new;
|
|
+ a_new->prev = cur;
|
|
+
|
|
+ return a_this;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_selector_prepend:
|
|
+ *
|
|
+ *@a_this: the current instance of #CRSelector list.
|
|
+ *@a_new: the instance of #CRSelector.
|
|
+ *
|
|
+ *Prepends an element to the #CRSelector list.
|
|
+ *
|
|
+ *Returns the new list.
|
|
+ */
|
|
+CRSelector *
|
|
+cr_selector_prepend (CRSelector * a_this, CRSelector * a_new)
|
|
+{
|
|
+ CRSelector *cur = NULL;
|
|
+
|
|
+ a_new->next = a_this;
|
|
+ a_this->prev = a_new;
|
|
+
|
|
+ for (cur = a_new; cur && cur->prev; cur = cur->prev) ;
|
|
+
|
|
+ return cur;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_selector_append_simple_sel:
|
|
+ *
|
|
+ *@a_this: the current instance of #CRSelector.
|
|
+ *@a_simple_sel: the simple selector to append.
|
|
+ *
|
|
+ *append a simple selector to the current #CRSelector list.
|
|
+ *
|
|
+ *Returns the new list or NULL in case of failure.
|
|
+ */
|
|
+CRSelector *
|
|
+cr_selector_append_simple_sel (CRSelector * a_this,
|
|
+ CRSimpleSel * a_simple_sel)
|
|
+{
|
|
+ CRSelector *selector = NULL;
|
|
+
|
|
+ selector = cr_selector_new (a_simple_sel);
|
|
+ g_return_val_if_fail (selector, NULL);
|
|
+
|
|
+ return cr_selector_append (a_this, selector);
|
|
+}
|
|
+
|
|
+guchar *
|
|
+cr_selector_to_string (CRSelector const * a_this)
|
|
+{
|
|
+ guchar *result = NULL;
|
|
+ GString *str_buf = NULL;
|
|
+
|
|
+ str_buf = g_string_new (NULL);
|
|
+ g_return_val_if_fail (str_buf, NULL);
|
|
+
|
|
+ if (a_this) {
|
|
+ CRSelector const *cur = NULL;
|
|
+
|
|
+ for (cur = a_this; cur; cur = cur->next) {
|
|
+ if (cur->simple_sel) {
|
|
+ guchar *tmp_str = NULL;
|
|
+
|
|
+ tmp_str = cr_simple_sel_to_string
|
|
+ (cur->simple_sel);
|
|
+
|
|
+ if (tmp_str) {
|
|
+ if (cur->prev)
|
|
+ g_string_append (str_buf,
|
|
+ ", ");
|
|
+
|
|
+ g_string_append (str_buf, (const gchar *) tmp_str);
|
|
+
|
|
+ g_free (tmp_str);
|
|
+ tmp_str = NULL;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (str_buf) {
|
|
+ result = (guchar *) str_buf->str;
|
|
+ g_string_free (str_buf, FALSE);
|
|
+ str_buf = NULL;
|
|
+ }
|
|
+
|
|
+ return result;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_selector_dump:
|
|
+ *
|
|
+ *@a_this: the current instance of #CRSelector.
|
|
+ *@a_fp: the destination file.
|
|
+ *
|
|
+ *Serializes the current instance of #CRSelector to a file.
|
|
+ */
|
|
+void
|
|
+cr_selector_dump (CRSelector const * a_this, FILE * a_fp)
|
|
+{
|
|
+ guchar *tmp_buf = NULL;
|
|
+
|
|
+ if (a_this) {
|
|
+ tmp_buf = cr_selector_to_string (a_this);
|
|
+ if (tmp_buf) {
|
|
+ fprintf (a_fp, "%s", tmp_buf);
|
|
+ g_free (tmp_buf);
|
|
+ tmp_buf = NULL;
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_selector_ref:
|
|
+ *
|
|
+ *@a_this: the current instance of #CRSelector.
|
|
+ *
|
|
+ *Increments the ref count of the current instance
|
|
+ *of #CRSelector.
|
|
+ */
|
|
+void
|
|
+cr_selector_ref (CRSelector * a_this)
|
|
+{
|
|
+ g_return_if_fail (a_this);
|
|
+
|
|
+ a_this->ref_count++;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_selector_unref:
|
|
+ *
|
|
+ *@a_this: the current instance of #CRSelector.
|
|
+ *
|
|
+ *Decrements the ref count of the current instance of
|
|
+ *#CRSelector.
|
|
+ *If the ref count reaches zero, the current instance of
|
|
+ *#CRSelector is destroyed.
|
|
+ *
|
|
+ *Returns TRUE if this function destroyed the current instance
|
|
+ *of #CRSelector, FALSE otherwise.
|
|
+ */
|
|
+gboolean
|
|
+cr_selector_unref (CRSelector * a_this)
|
|
+{
|
|
+ g_return_val_if_fail (a_this, FALSE);
|
|
+
|
|
+ if (a_this->ref_count) {
|
|
+ a_this->ref_count--;
|
|
+ }
|
|
+
|
|
+ if (a_this->ref_count == 0) {
|
|
+ cr_selector_destroy (a_this);
|
|
+ return TRUE;
|
|
+ }
|
|
+
|
|
+ return FALSE;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_selector_destroy:
|
|
+ *
|
|
+ *@a_this: the current instance of #CRSelector.
|
|
+ *
|
|
+ *Destroys the selector list.
|
|
+ */
|
|
+void
|
|
+cr_selector_destroy (CRSelector * a_this)
|
|
+{
|
|
+ CRSelector *cur = NULL;
|
|
+
|
|
+ g_return_if_fail (a_this);
|
|
+
|
|
+ /*
|
|
+ *go and get the list tail. In the same time, free
|
|
+ *all the simple selectors contained in the list.
|
|
+ */
|
|
+ for (cur = a_this; cur && cur->next; cur = cur->next) {
|
|
+ if (cur->simple_sel) {
|
|
+ cr_simple_sel_destroy (cur->simple_sel);
|
|
+ cur->simple_sel = NULL;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (cur) {
|
|
+ if (cur->simple_sel) {
|
|
+ cr_simple_sel_destroy (cur->simple_sel);
|
|
+ cur->simple_sel = NULL;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /*in case the list has only one element */
|
|
+ if (cur && !cur->prev) {
|
|
+ g_free (cur);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ /*walk backward the list and free each "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;
|
|
+
|
|
+ if (cur->next) {
|
|
+ g_free (cur->next);
|
|
+ cur->next = NULL;
|
|
+ }
|
|
+
|
|
+ g_free (cur);
|
|
+}
|
|
diff --git a/src/st/croco/cr-selector.h b/src/st/croco/cr-selector.h
|
|
new file mode 100644
|
|
index 000000000..dd6a7f786
|
|
--- /dev/null
|
|
+++ b/src/st/croco/cr-selector.h
|
|
@@ -0,0 +1,95 @@
|
|
+/* -*- 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.
|
|
+ */
|
|
+
|
|
+#ifndef __CR_SELECTOR_H__
|
|
+#define __CR_SELECTOR_H__
|
|
+
|
|
+#include <stdio.h>
|
|
+#include "cr-utils.h"
|
|
+#include "cr-simple-sel.h"
|
|
+#include "cr-parsing-location.h"
|
|
+
|
|
+/**
|
|
+ *@file
|
|
+ *The declaration file of the #CRSelector file.
|
|
+ */
|
|
+
|
|
+G_BEGIN_DECLS
|
|
+
|
|
+typedef struct _CRSelector CRSelector ;
|
|
+
|
|
+/**
|
|
+ *Abstracts a CSS2 selector as defined in the right part
|
|
+ *of the 'ruleset" production in the appendix D.1 of the
|
|
+ *css2 spec.
|
|
+ *It is actually the abstraction of a comma separated list
|
|
+ *of simple selectors list.
|
|
+ *In a css2 file, a selector is a list of simple selectors
|
|
+ *separated by a comma.
|
|
+ *e.g: sel0, sel1, sel2 ...
|
|
+ *Each seln is a simple selector
|
|
+ */
|
|
+struct _CRSelector
|
|
+{
|
|
+ /**
|
|
+ *A Selection expression.
|
|
+ *It is a list of basic selectors.
|
|
+ *Each basic selector can be either an element
|
|
+ *selector, an id selector, a class selector, an
|
|
+ *attribute selector, an universal selector etc ...
|
|
+ */
|
|
+ CRSimpleSel *simple_sel ;
|
|
+
|
|
+ /**The next selector list element*/
|
|
+ CRSelector *next ;
|
|
+ CRSelector *prev ;
|
|
+ CRParsingLocation location ;
|
|
+ glong ref_count ;
|
|
+};
|
|
+
|
|
+CRSelector* cr_selector_new (CRSimpleSel *a_sel_expr) ;
|
|
+
|
|
+CRSelector * cr_selector_parse_from_buf (const guchar * a_char_buf,
|
|
+ enum CREncoding a_enc) ;
|
|
+
|
|
+CRSelector* cr_selector_append (CRSelector *a_this, CRSelector *a_new) ;
|
|
+
|
|
+CRSelector* cr_selector_append_simple_sel (CRSelector *a_this,
|
|
+ CRSimpleSel *a_simple_sel) ;
|
|
+
|
|
+CRSelector* cr_selector_prepend (CRSelector *a_this, CRSelector *a_new) ;
|
|
+
|
|
+guchar * cr_selector_to_string (CRSelector const *a_this) ;
|
|
+
|
|
+void cr_selector_dump (CRSelector const *a_this, FILE *a_fp) ;
|
|
+
|
|
+void cr_selector_ref (CRSelector *a_this) ;
|
|
+
|
|
+gboolean cr_selector_unref (CRSelector *a_this) ;
|
|
+
|
|
+void cr_selector_destroy (CRSelector *a_this) ;
|
|
+
|
|
+G_END_DECLS
|
|
+
|
|
+#endif /*__CR_SELECTOR_H__*/
|
|
diff --git a/src/st/croco/cr-simple-sel.c b/src/st/croco/cr-simple-sel.c
|
|
new file mode 100644
|
|
index 000000000..ac906858d
|
|
--- /dev/null
|
|
+++ b/src/st/croco/cr-simple-sel.c
|
|
@@ -0,0 +1,325 @@
|
|
+/* -*- 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 <glib.h>
|
|
+#include "cr-simple-sel.h"
|
|
+
|
|
+/**
|
|
+ * cr_simple_sel_new:
|
|
+ *
|
|
+ *The constructor of #CRSimpleSel.
|
|
+ *
|
|
+ *Returns the new instance of #CRSimpleSel.
|
|
+ */
|
|
+CRSimpleSel *
|
|
+cr_simple_sel_new (void)
|
|
+{
|
|
+ CRSimpleSel *result = NULL;
|
|
+
|
|
+ result = g_try_malloc (sizeof (CRSimpleSel));
|
|
+ if (!result) {
|
|
+ cr_utils_trace_info ("Out of memory");
|
|
+ return NULL;
|
|
+ }
|
|
+ memset (result, 0, sizeof (CRSimpleSel));
|
|
+
|
|
+ return result;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_simple_sel_append_simple_sel:
|
|
+ *
|
|
+ *Appends a simpe selector to the current list of simple selector.
|
|
+ *
|
|
+ *@a_this: the this pointer of the current instance of #CRSimpleSel.
|
|
+ *@a_sel: the simple selector to append.
|
|
+ *
|
|
+ *Returns: the new list upon successfull completion, an error code otherwise.
|
|
+ */
|
|
+CRSimpleSel *
|
|
+cr_simple_sel_append_simple_sel (CRSimpleSel * a_this, CRSimpleSel * a_sel)
|
|
+{
|
|
+ CRSimpleSel *cur = NULL;
|
|
+
|
|
+ g_return_val_if_fail (a_sel, NULL);
|
|
+
|
|
+ if (a_this == NULL)
|
|
+ return a_sel;
|
|
+
|
|
+ for (cur = a_this; cur->next; cur = cur->next) ;
|
|
+
|
|
+ cur->next = a_sel;
|
|
+ a_sel->prev = cur;
|
|
+
|
|
+ return a_this;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_simple_sel_prepend_simple_sel:
|
|
+ *
|
|
+ *@a_this: the this pointer of the current instance of #CRSimpleSel.
|
|
+ *@a_sel: the simple selector to prepend.
|
|
+ *
|
|
+ *Prepends a simple selector to the current list of simple selectors.
|
|
+ *
|
|
+ *Returns the new list upon successfull completion, an error code otherwise.
|
|
+ */
|
|
+CRSimpleSel *
|
|
+cr_simple_sel_prepend_simple_sel (CRSimpleSel * a_this, CRSimpleSel * a_sel)
|
|
+{
|
|
+ g_return_val_if_fail (a_sel, NULL);
|
|
+
|
|
+ if (a_this == NULL)
|
|
+ return a_sel;
|
|
+
|
|
+ a_sel->next = a_this;
|
|
+ a_this->prev = a_sel;
|
|
+
|
|
+ return a_sel;
|
|
+}
|
|
+
|
|
+guchar *
|
|
+cr_simple_sel_to_string (CRSimpleSel const * a_this)
|
|
+{
|
|
+ GString *str_buf = NULL;
|
|
+ guchar *result = NULL;
|
|
+
|
|
+ CRSimpleSel const *cur = NULL;
|
|
+
|
|
+ g_return_val_if_fail (a_this, NULL);
|
|
+
|
|
+ str_buf = g_string_new (NULL);
|
|
+ for (cur = a_this; cur; cur = cur->next) {
|
|
+ if (cur->name) {
|
|
+ guchar *str = (guchar *) g_strndup (cur->name->stryng->str,
|
|
+ cur->name->stryng->len);
|
|
+
|
|
+ if (str) {
|
|
+ switch (cur->combinator) {
|
|
+ case COMB_WS:
|
|
+ g_string_append (str_buf, " ");
|
|
+ break;
|
|
+
|
|
+ case COMB_PLUS:
|
|
+ g_string_append (str_buf, "+");
|
|
+ break;
|
|
+
|
|
+ case COMB_GT:
|
|
+ g_string_append (str_buf, ">");
|
|
+ break;
|
|
+
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ g_string_append (str_buf, (const gchar *) str);
|
|
+ g_free (str);
|
|
+ str = NULL;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (cur->add_sel) {
|
|
+ guchar *tmp_str = NULL;
|
|
+
|
|
+ tmp_str = cr_additional_sel_to_string (cur->add_sel);
|
|
+ if (tmp_str) {
|
|
+ g_string_append (str_buf, (const gchar *) tmp_str);
|
|
+ g_free (tmp_str);
|
|
+ tmp_str = NULL;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (str_buf) {
|
|
+ result = (guchar *) str_buf->str;
|
|
+ g_string_free (str_buf, FALSE);
|
|
+ str_buf = NULL;
|
|
+ }
|
|
+
|
|
+ return result;
|
|
+}
|
|
+
|
|
+
|
|
+guchar *
|
|
+cr_simple_sel_one_to_string (CRSimpleSel const * a_this)
|
|
+{
|
|
+ GString *str_buf = NULL;
|
|
+ guchar *result = NULL;
|
|
+
|
|
+ g_return_val_if_fail (a_this, NULL);
|
|
+
|
|
+ str_buf = g_string_new (NULL);
|
|
+ if (a_this->name) {
|
|
+ guchar *str = (guchar *) g_strndup (a_this->name->stryng->str,
|
|
+ a_this->name->stryng->len);
|
|
+
|
|
+ if (str) {
|
|
+ g_string_append_printf (str_buf, "%s", str);
|
|
+ g_free (str);
|
|
+ str = NULL;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (a_this->add_sel) {
|
|
+ guchar *tmp_str = NULL;
|
|
+
|
|
+ tmp_str = cr_additional_sel_to_string (a_this->add_sel);
|
|
+ if (tmp_str) {
|
|
+ g_string_append_printf
|
|
+ (str_buf, "%s", tmp_str);
|
|
+ g_free (tmp_str);
|
|
+ tmp_str = NULL;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (str_buf) {
|
|
+ result = (guchar *) str_buf->str;
|
|
+ g_string_free (str_buf, FALSE);
|
|
+ str_buf = NULL;
|
|
+ }
|
|
+
|
|
+ return result;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_simple_sel_dump:
|
|
+ *@a_this: the current instance of #CRSimpleSel.
|
|
+ *@a_fp: the destination file pointer.
|
|
+ *
|
|
+ *Dumps the selector to a file.
|
|
+ *TODO: add the support of unicode in the dump.
|
|
+ *
|
|
+ *Returns CR_OK upon successfull completion, an error code
|
|
+ *otherwise.
|
|
+ */
|
|
+enum CRStatus
|
|
+cr_simple_sel_dump (CRSimpleSel const * a_this, FILE * a_fp)
|
|
+{
|
|
+ guchar *tmp_str = NULL;
|
|
+
|
|
+ g_return_val_if_fail (a_fp, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ if (a_this) {
|
|
+ tmp_str = cr_simple_sel_to_string (a_this);
|
|
+ if (tmp_str) {
|
|
+ fprintf (a_fp, "%s", tmp_str);
|
|
+ g_free (tmp_str);
|
|
+ tmp_str = NULL;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return CR_OK;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_simple_sel_compute_specificity:
|
|
+ *
|
|
+ *@a_this: the current instance of #CRSimpleSel
|
|
+ *
|
|
+ *Computes the selector (combinator separated list of simple selectors)
|
|
+ *as defined in the css2 spec in chapter 6.4.3
|
|
+ *
|
|
+ *Returns CR_OK upon successfull completion, an error code otherwise.
|
|
+ */
|
|
+enum CRStatus
|
|
+cr_simple_sel_compute_specificity (CRSimpleSel * a_this)
|
|
+{
|
|
+ CRAdditionalSel const *cur_add_sel = NULL;
|
|
+ CRSimpleSel const *cur_sel = NULL;
|
|
+ gulong a = 0,
|
|
+ b = 0,
|
|
+ c = 0;
|
|
+
|
|
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ for (cur_sel = a_this; cur_sel; cur_sel = cur_sel->next) {
|
|
+ if (cur_sel->type_mask & TYPE_SELECTOR) {
|
|
+ c++; /*hmmh, is this a new language ? */
|
|
+ } else if (!cur_sel->name
|
|
+ || !cur_sel->name->stryng
|
|
+ || !cur_sel->name->stryng->str) {
|
|
+ if (cur_sel->add_sel->type ==
|
|
+ PSEUDO_CLASS_ADD_SELECTOR) {
|
|
+ /*
|
|
+ *this is a pseudo element, and
|
|
+ *the spec says, "ignore pseudo elements".
|
|
+ */
|
|
+ continue;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ for (cur_add_sel = cur_sel->add_sel;
|
|
+ cur_add_sel; cur_add_sel = cur_add_sel->next) {
|
|
+ switch (cur_add_sel->type) {
|
|
+ case ID_ADD_SELECTOR:
|
|
+ a++;
|
|
+ break;
|
|
+
|
|
+ case NO_ADD_SELECTOR:
|
|
+ continue;
|
|
+
|
|
+ default:
|
|
+ b++;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /*we suppose a, b and c have 1 to 3 digits */
|
|
+ a_this->specificity = a * 1000000 + b * 1000 + c;
|
|
+
|
|
+ return CR_OK;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * cr_simple_sel_destroy:
|
|
+ *
|
|
+ *@a_this: the this pointer of the current instance of #CRSimpleSel.
|
|
+ *
|
|
+ *The destructor of the current instance of
|
|
+ *#CRSimpleSel.
|
|
+ */
|
|
+void
|
|
+cr_simple_sel_destroy (CRSimpleSel * a_this)
|
|
+{
|
|
+ g_return_if_fail (a_this);
|
|
+
|
|
+ if (a_this->name) {
|
|
+ cr_string_destroy (a_this->name);
|
|
+ a_this->name = NULL;
|
|
+ }
|
|
+
|
|
+ if (a_this->add_sel) {
|
|
+ cr_additional_sel_destroy (a_this->add_sel);
|
|
+ a_this->add_sel = NULL;
|
|
+ }
|
|
+
|
|
+ if (a_this->next) {
|
|
+ cr_simple_sel_destroy (a_this->next);
|
|
+ }
|
|
+
|
|
+ if (a_this) {
|
|
+ g_free (a_this);
|
|
+ }
|
|
+}
|
|
diff --git a/src/st/croco/cr-simple-sel.h b/src/st/croco/cr-simple-sel.h
|
|
new file mode 100644
|
|
index 000000000..d8edc0025
|
|
--- /dev/null
|
|
+++ b/src/st/croco/cr-simple-sel.h
|
|
@@ -0,0 +1,130 @@
|
|
+/* -*- 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.
|
|
+ */
|
|
+
|
|
+
|
|
+#ifndef __CR_SEL_H__
|
|
+#define __CR_SEL_H__
|
|
+
|
|
+#include <stdio.h>
|
|
+#include <glib.h>
|
|
+#include "cr-additional-sel.h"
|
|
+#include "cr-parsing-location.h"
|
|
+
|
|
+G_BEGIN_DECLS
|
|
+
|
|
+/**
|
|
+ *@file
|
|
+ *the declaration of the #CRSimpleSel class.
|
|
+ *
|
|
+ */
|
|
+enum Combinator
|
|
+{
|
|
+ NO_COMBINATOR,
|
|
+ COMB_WS,/*whitespace: descendent*/
|
|
+ COMB_PLUS,/*'+': preceded by*/
|
|
+ COMB_GT/*greater than ('>'): child*/
|
|
+} ;
|
|
+
|
|
+enum SimpleSelectorType
|
|
+{
|
|
+ NO_SELECTOR_TYPE = 0,
|
|
+ UNIVERSAL_SELECTOR = 1,
|
|
+ TYPE_SELECTOR = 1 << 1
|
|
+} ;
|
|
+
|
|
+typedef struct _CRSimpleSel CRSimpleSel ;
|
|
+
|
|
+/**
|
|
+ *The abstraction of a css2 simple selection list
|
|
+ *as defined by the right part of the "selector" production in the
|
|
+ *appendix D.1 of the css2 spec.
|
|
+ *It is basically a list of simple selector, each
|
|
+ *simple selector being separated by a combinator.
|
|
+ *
|
|
+ *In the libcroco's implementation, each simple selector
|
|
+ *is made of at most two parts:
|
|
+ *
|
|
+ *1/An element name or 'type selector' (which can hold a '*' and
|
|
+ *then been called 'universal selector')
|
|
+ *
|
|
+ *2/An additional selector that "specializes" the preceding type or
|
|
+ *universal selector. The additionnal selector can be either
|
|
+ *an id selector, or a class selector, or an attribute selector.
|
|
+ */
|
|
+struct _CRSimpleSel
|
|
+{
|
|
+ enum SimpleSelectorType type_mask ;
|
|
+ gboolean is_case_sentive ;
|
|
+ CRString * name ;
|
|
+ /**
|
|
+ *The combinator that separates
|
|
+ *this simple selector from the previous
|
|
+ *one.
|
|
+ */
|
|
+ enum Combinator combinator ;
|
|
+
|
|
+ /**
|
|
+ *The additional selector list of the
|
|
+ *current simple selector.
|
|
+ *An additional selector may
|
|
+ *be a class selector, an id selector,
|
|
+ *or an attribute selector.
|
|
+ *Note that this field is a linked list.
|
|
+ */
|
|
+ CRAdditionalSel *add_sel ;
|
|
+
|
|
+ /*
|
|
+ *the specificity as specified by
|
|
+ *chapter 6.4.3 of the spec.
|
|
+ */
|
|
+ gulong specificity ;
|
|
+
|
|
+ CRSimpleSel *next ;
|
|
+ CRSimpleSel *prev ;
|
|
+ CRParsingLocation location ;
|
|
+} ;
|
|
+
|
|
+CRSimpleSel * cr_simple_sel_new (void) ;
|
|
+
|
|
+CRSimpleSel * cr_simple_sel_append_simple_sel (CRSimpleSel *a_this,
|
|
+ CRSimpleSel *a_sel) ;
|
|
+
|
|
+CRSimpleSel * cr_simple_sel_prepend_simple_sel (CRSimpleSel *a_this,
|
|
+ CRSimpleSel *a_sel) ;
|
|
+
|
|
+guchar * cr_simple_sel_to_string (CRSimpleSel const *a_this) ;
|
|
+
|
|
+guchar * cr_simple_sel_one_to_string (CRSimpleSel const * a_this) ;
|
|
+
|
|
+enum CRStatus cr_simple_sel_dump (CRSimpleSel const *a_this, FILE *a_fp) ;
|
|
+
|
|
+enum CRStatus cr_simple_sel_dump_attr_sel_list (CRSimpleSel const *a_this) ;
|
|
+
|
|
+enum CRStatus cr_simple_sel_compute_specificity (CRSimpleSel *a_this) ;
|
|
+
|
|
+void cr_simple_sel_destroy (CRSimpleSel *a_this) ;
|
|
+
|
|
+G_END_DECLS
|
|
+
|
|
+
|
|
+#endif /*__CR_SIMPLE_SEL_H__*/
|
|
diff --git a/src/st/croco/cr-statement.c b/src/st/croco/cr-statement.c
|
|
new file mode 100644
|
|
index 000000000..241fa5f3b
|
|
--- /dev/null
|
|
+++ b/src/st/croco/cr-statement.c
|
|
@@ -0,0 +1,2794 @@
|
|
+/* -*- 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 instanciates
|
|
+ *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.
|
|
+ *
|
|
+ *Instanciates 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
|
|
+ *instanciate 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 sucessful 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 sucessful 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;
|
|
+}
|
|
diff --git a/src/st/croco/cr-statement.h b/src/st/croco/cr-statement.h
|
|
new file mode 100644
|
|
index 000000000..74a233055
|
|
--- /dev/null
|
|
+++ b/src/st/croco/cr-statement.h
|
|
@@ -0,0 +1,440 @@
|
|
+/* -*- 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 <stdio.h>
|
|
+#include "cr-utils.h"
|
|
+#include "cr-term.h"
|
|
+#include "cr-selector.h"
|
|
+#include "cr-declaration.h"
|
|
+
|
|
+#ifndef __CR_STATEMENT_H__
|
|
+#define __CR_STATEMENT_H__
|
|
+
|
|
+G_BEGIN_DECLS
|
|
+
|
|
+/**
|
|
+ *@file
|
|
+ *Declaration of the #CRStatement class.
|
|
+ */
|
|
+
|
|
+/*
|
|
+ *forward declaration of CRStyleSheet which is defined in
|
|
+ *cr-stylesheet.h
|
|
+ */
|
|
+
|
|
+struct _CRStatement ;
|
|
+
|
|
+/*
|
|
+ *typedef struct _CRStatement CRStatement ;
|
|
+ *this is forward declared in
|
|
+ *cr-declaration.h already.
|
|
+ */
|
|
+
|
|
+struct _CRAtMediaRule ;
|
|
+typedef struct _CRAtMediaRule CRAtMediaRule ;
|
|
+
|
|
+typedef struct _CRRuleSet CRRuleSet ;
|
|
+
|
|
+/**
|
|
+ *The abstraction of a css ruleset.
|
|
+ *A ruleset is made of a list of selectors,
|
|
+ *followed by a list of declarations.
|
|
+ */
|
|
+struct _CRRuleSet
|
|
+{
|
|
+ /**A list of instances of #CRSimpeSel*/
|
|
+ CRSelector *sel_list ;
|
|
+
|
|
+ /**A list of instances of #CRDeclaration*/
|
|
+ CRDeclaration *decl_list ;
|
|
+
|
|
+ /**
|
|
+ *The parent media rule, or NULL if
|
|
+ *no parent media rule exists.
|
|
+ */
|
|
+ CRStatement *parent_media_rule ;
|
|
+} ;
|
|
+
|
|
+/*
|
|
+ *a forward declaration of CRStylesheet.
|
|
+ *CRStylesheet is actually declared in
|
|
+ *cr-stylesheet.h
|
|
+ */
|
|
+struct _CRStyleSheet ;
|
|
+typedef struct _CRStyleSheet CRStyleSheet;
|
|
+
|
|
+
|
|
+/**The \@import rule abstraction.*/
|
|
+typedef struct _CRAtImportRule CRAtImportRule ;
|
|
+struct _CRAtImportRule
|
|
+{
|
|
+ /**the url of the import rule*/
|
|
+ CRString *url ;
|
|
+
|
|
+ GList *media_list ;
|
|
+
|
|
+ /**
|
|
+ *the stylesheet fetched from the url, if any.
|
|
+ *this is not "owned" by #CRAtImportRule which means
|
|
+ *it is not destroyed by the destructor of #CRAtImportRule.
|
|
+ */
|
|
+ CRStyleSheet * sheet;
|
|
+};
|
|
+
|
|
+
|
|
+/**abstraction of an \@media rule*/
|
|
+struct _CRAtMediaRule
|
|
+{
|
|
+ GList *media_list ;
|
|
+ CRStatement *rulesets ;
|
|
+} ;
|
|
+
|
|
+
|
|
+typedef struct _CRAtPageRule CRAtPageRule ;
|
|
+/**The \@page rule abstraction*/
|
|
+struct _CRAtPageRule
|
|
+{
|
|
+ /**a list of instances of #CRDeclaration*/
|
|
+ CRDeclaration *decl_list ;
|
|
+
|
|
+ /**page selector. Is a pseudo selector*/
|
|
+ CRString *name ;
|
|
+ CRString *pseudo ;
|
|
+} ;
|
|
+
|
|
+/**The \@charset rule abstraction*/
|
|
+typedef struct _CRAtCharsetRule CRAtCharsetRule ;
|
|
+struct _CRAtCharsetRule
|
|
+{
|
|
+ CRString * charset ;
|
|
+};
|
|
+
|
|
+/**The abstaction of the \@font-face rule.*/
|
|
+typedef struct _CRAtFontFaceRule CRAtFontFaceRule ;
|
|
+struct _CRAtFontFaceRule
|
|
+{
|
|
+ /*a list of instanaces of #CRDeclaration*/
|
|
+ CRDeclaration *decl_list ;
|
|
+} ;
|
|
+
|
|
+
|
|
+/**
|
|
+ *The possible types of css2 statements.
|
|
+ */
|
|
+enum CRStatementType
|
|
+{
|
|
+ /**
|
|
+ *A generic css at-rule
|
|
+ *each unknown at-rule will
|
|
+ *be of this type.
|
|
+ */
|
|
+
|
|
+ /**A css at-rule*/
|
|
+ AT_RULE_STMT = 0,
|
|
+
|
|
+ /*A css ruleset*/
|
|
+ RULESET_STMT,
|
|
+
|
|
+ /**A css2 import rule*/
|
|
+ AT_IMPORT_RULE_STMT,
|
|
+
|
|
+ /**A css2 media rule*/
|
|
+ AT_MEDIA_RULE_STMT,
|
|
+
|
|
+ /**A css2 page rule*/
|
|
+ AT_PAGE_RULE_STMT,
|
|
+
|
|
+ /**A css2 charset rule*/
|
|
+ AT_CHARSET_RULE_STMT,
|
|
+
|
|
+ /**A css2 font face rule*/
|
|
+ AT_FONT_FACE_RULE_STMT
|
|
+} ;
|
|
+
|
|
+
|
|
+/**
|
|
+ *The abstraction of css statement as defined
|
|
+ *in the chapter 4 and appendix D.1 of the css2 spec.
|
|
+ *A statement is actually a double chained list of
|
|
+ *statements.A statement can be a ruleset, an \@import
|
|
+ *rule, an \@page rule etc ...
|
|
+ */
|
|
+struct _CRStatement
|
|
+{
|
|
+ /**
|
|
+ *The type of the statement.
|
|
+ */
|
|
+ enum CRStatementType type ;
|
|
+
|
|
+ union
|
|
+ {
|
|
+ CRRuleSet *ruleset ;
|
|
+ CRAtImportRule *import_rule ;
|
|
+ CRAtMediaRule *media_rule ;
|
|
+ CRAtPageRule *page_rule ;
|
|
+ CRAtCharsetRule *charset_rule ;
|
|
+ CRAtFontFaceRule *font_face_rule ;
|
|
+ } kind ;
|
|
+
|
|
+ /*
|
|
+ *the specificity of the selector
|
|
+ *that matched this statement.
|
|
+ *This is only used by the cascading
|
|
+ *order determination algorithm.
|
|
+ */
|
|
+ gulong specificity ;
|
|
+
|
|
+ /*
|
|
+ *the style sheet that contains
|
|
+ *this css statement.
|
|
+ */
|
|
+ CRStyleSheet *parent_sheet ;
|
|
+ CRStatement *next ;
|
|
+ CRStatement *prev ;
|
|
+
|
|
+ CRParsingLocation location ;
|
|
+
|
|
+ /**
|
|
+ *a custom pointer useable by
|
|
+ *applications that use libcroco.
|
|
+ *libcroco itself will never modify
|
|
+ *this pointer.
|
|
+ */
|
|
+ gpointer app_data ;
|
|
+
|
|
+ /**
|
|
+ *a custom pointer used
|
|
+ *by the upper layers of libcroco.
|
|
+ *application should never use this
|
|
+ *pointer.
|
|
+ */
|
|
+ gpointer croco_data ;
|
|
+
|
|
+} ;
|
|
+
|
|
+
|
|
+gboolean
|
|
+cr_statement_does_buf_parses_against_core (const guchar *a_buf,
|
|
+ enum CREncoding a_encoding) ;
|
|
+CRStatement *
|
|
+cr_statement_parse_from_buf (const guchar *a_buf,
|
|
+ enum CREncoding a_encoding) ;
|
|
+CRStatement*
|
|
+cr_statement_new_ruleset (CRStyleSheet *a_sheet,
|
|
+ CRSelector *a_sel_list,
|
|
+ CRDeclaration *a_decl_list,
|
|
+ CRStatement *a_media_rule) ;
|
|
+CRStatement *
|
|
+cr_statement_ruleset_parse_from_buf (const guchar * a_buf,
|
|
+ enum CREncoding a_enc) ;
|
|
+
|
|
+CRStatement*
|
|
+cr_statement_new_at_import_rule (CRStyleSheet *a_container_sheet,
|
|
+ CRString *a_url,
|
|
+ GList *a_media_list,
|
|
+ CRStyleSheet *a_imported_sheet) ;
|
|
+
|
|
+CRStatement *
|
|
+cr_statement_at_import_rule_parse_from_buf (const guchar * a_buf,
|
|
+ enum CREncoding a_encoding) ;
|
|
+
|
|
+CRStatement *
|
|
+cr_statement_new_at_media_rule (CRStyleSheet *a_sheet,
|
|
+ CRStatement *a_ruleset,
|
|
+ GList *a_media) ;
|
|
+CRStatement *
|
|
+cr_statement_at_media_rule_parse_from_buf (const guchar *a_buf,
|
|
+ enum CREncoding a_enc) ;
|
|
+
|
|
+CRStatement *
|
|
+cr_statement_new_at_charset_rule (CRStyleSheet *a_sheet,
|
|
+ CRString *a_charset) ;
|
|
+CRStatement *
|
|
+cr_statement_at_charset_rule_parse_from_buf (const guchar *a_buf,
|
|
+ enum CREncoding a_encoding);
|
|
+
|
|
+
|
|
+CRStatement *
|
|
+cr_statement_new_at_font_face_rule (CRStyleSheet *a_sheet,
|
|
+ CRDeclaration *a_font_decls) ;
|
|
+CRStatement *
|
|
+cr_statement_font_face_rule_parse_from_buf (const guchar *a_buf,
|
|
+ enum CREncoding a_encoding) ;
|
|
+
|
|
+CRStatement *
|
|
+cr_statement_new_at_page_rule (CRStyleSheet *a_sheet,
|
|
+ CRDeclaration *a_decl_list,
|
|
+ CRString *a_name,
|
|
+ CRString *a_pseudo) ;
|
|
+CRStatement *
|
|
+cr_statement_at_page_rule_parse_from_buf (const guchar *a_buf,
|
|
+ enum CREncoding a_encoding) ;
|
|
+
|
|
+enum CRStatus
|
|
+cr_statement_set_parent_sheet (CRStatement *a_this,
|
|
+ CRStyleSheet *a_sheet) ;
|
|
+
|
|
+enum CRStatus
|
|
+cr_statement_get_parent_sheet (CRStatement *a_this,
|
|
+ CRStyleSheet **a_sheet) ;
|
|
+
|
|
+CRStatement *
|
|
+cr_statement_append (CRStatement *a_this,
|
|
+ CRStatement *a_new) ;
|
|
+
|
|
+CRStatement*
|
|
+cr_statement_prepend (CRStatement *a_this,
|
|
+ CRStatement *a_new) ;
|
|
+
|
|
+CRStatement *
|
|
+cr_statement_unlink (CRStatement *a_stmt) ;
|
|
+
|
|
+enum CRStatus
|
|
+cr_statement_ruleset_set_sel_list (CRStatement *a_this,
|
|
+ CRSelector *a_sel_list) ;
|
|
+
|
|
+enum CRStatus
|
|
+cr_statement_ruleset_get_sel_list (CRStatement const *a_this,
|
|
+ CRSelector **a_list) ;
|
|
+
|
|
+enum CRStatus
|
|
+cr_statement_ruleset_set_decl_list (CRStatement *a_this,
|
|
+ CRDeclaration *a_list) ;
|
|
+
|
|
+enum CRStatus
|
|
+cr_statement_ruleset_get_declarations (CRStatement *a_this,
|
|
+ CRDeclaration **a_decl_list) ;
|
|
+
|
|
+enum CRStatus
|
|
+cr_statement_ruleset_append_decl2 (CRStatement *a_this,
|
|
+ CRString *a_prop, CRTerm *a_value) ;
|
|
+
|
|
+enum CRStatus
|
|
+cr_statement_ruleset_append_decl (CRStatement *a_this,
|
|
+ CRDeclaration *a_decl) ;
|
|
+
|
|
+enum CRStatus
|
|
+cr_statement_at_import_rule_set_imported_sheet (CRStatement *a_this,
|
|
+ CRStyleSheet *a_sheet) ;
|
|
+
|
|
+enum CRStatus
|
|
+cr_statement_at_import_rule_get_imported_sheet (CRStatement *a_this,
|
|
+ CRStyleSheet **a_sheet) ;
|
|
+
|
|
+enum CRStatus
|
|
+cr_statement_at_import_rule_set_url (CRStatement *a_this,
|
|
+ CRString *a_url) ;
|
|
+
|
|
+enum CRStatus
|
|
+cr_statement_at_import_rule_get_url (CRStatement const *a_this,
|
|
+ CRString **a_url) ;
|
|
+
|
|
+gint
|
|
+cr_statement_at_media_nr_rules (CRStatement const *a_this) ;
|
|
+
|
|
+CRStatement *
|
|
+cr_statement_at_media_get_from_list (CRStatement *a_this, int itemnr) ;
|
|
+
|
|
+enum CRStatus
|
|
+cr_statement_at_page_rule_set_sel (CRStatement *a_this,
|
|
+ CRSelector *a_sel) ;
|
|
+
|
|
+enum CRStatus
|
|
+cr_statement_at_page_rule_get_sel (CRStatement const *a_this,
|
|
+ CRSelector **a_sel) ;
|
|
+
|
|
+enum CRStatus
|
|
+cr_statement_at_page_rule_set_declarations (CRStatement *a_this,
|
|
+ CRDeclaration *a_decl_list) ;
|
|
+
|
|
+enum CRStatus
|
|
+cr_statement_at_page_rule_get_declarations (CRStatement *a_this,
|
|
+ CRDeclaration **a_decl_list) ;
|
|
+
|
|
+enum CRStatus
|
|
+cr_statement_at_charset_rule_set_charset (CRStatement *a_this,
|
|
+ CRString *a_charset) ;
|
|
+
|
|
+enum CRStatus
|
|
+cr_statement_at_charset_rule_get_charset (CRStatement const *a_this,
|
|
+ CRString **a_charset) ;
|
|
+
|
|
+enum CRStatus
|
|
+cr_statement_at_font_face_rule_set_decls (CRStatement *a_this,
|
|
+ CRDeclaration *a_decls) ;
|
|
+
|
|
+enum CRStatus
|
|
+cr_statement_at_font_face_rule_get_decls (CRStatement *a_this,
|
|
+ CRDeclaration **a_decls) ;
|
|
+
|
|
+enum CRStatus
|
|
+cr_statement_at_font_face_rule_add_decl (CRStatement *a_this,
|
|
+ CRString *a_prop,
|
|
+ CRTerm *a_value) ;
|
|
+
|
|
+gchar *
|
|
+cr_statement_to_string (CRStatement const * a_this, gulong a_indent) ;
|
|
+
|
|
+gchar*
|
|
+cr_statement_list_to_string (CRStatement const *a_this, gulong a_indent) ;
|
|
+
|
|
+void
|
|
+cr_statement_dump (CRStatement const *a_this, FILE *a_fp, gulong a_indent) ;
|
|
+
|
|
+void
|
|
+cr_statement_dump_ruleset (CRStatement const * a_this, FILE * a_fp,
|
|
+ glong a_indent) ;
|
|
+
|
|
+void
|
|
+cr_statement_dump_font_face_rule (CRStatement const * a_this,
|
|
+ FILE * a_fp,
|
|
+ glong a_indent) ;
|
|
+
|
|
+void
|
|
+cr_statement_dump_page (CRStatement const * a_this, FILE * a_fp,
|
|
+ gulong a_indent) ;
|
|
+
|
|
+
|
|
+void
|
|
+cr_statement_dump_media_rule (CRStatement const * a_this,
|
|
+ FILE * a_fp,
|
|
+ gulong a_indent) ;
|
|
+
|
|
+void
|
|
+cr_statement_dump_import_rule (CRStatement const * a_this, FILE * a_fp,
|
|
+ gulong a_indent) ;
|
|
+void
|
|
+cr_statement_dump_charset (CRStatement const * a_this, FILE * a_fp,
|
|
+ gulong a_indent) ;
|
|
+gint
|
|
+cr_statement_nr_rules (CRStatement const *a_this) ;
|
|
+
|
|
+CRStatement *
|
|
+cr_statement_get_from_list (CRStatement *a_this, int itemnr) ;
|
|
+
|
|
+void
|
|
+cr_statement_destroy (CRStatement *a_this) ;
|
|
+
|
|
+G_END_DECLS
|
|
+
|
|
+#endif /*__CR_STATEMENT_H__*/
|
|
diff --git a/src/st/croco/cr-string.c b/src/st/croco/cr-string.c
|
|
new file mode 100644
|
|
index 000000000..1b10bb2ab
|
|
--- /dev/null
|
|
+++ b/src/st/croco/cr-string.c
|
|
@@ -0,0 +1,168 @@
|
|
+/* -*- 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-string.h"
|
|
+
|
|
+/**
|
|
+ *Instanciates a #CRString
|
|
+ *@return the newly instanciated #CRString
|
|
+ *Must be freed with cr_string_destroy().
|
|
+ */
|
|
+CRString *
|
|
+cr_string_new (void)
|
|
+{
|
|
+ CRString *result = NULL ;
|
|
+
|
|
+ result = g_try_malloc (sizeof (CRString)) ;
|
|
+ if (!result) {
|
|
+ cr_utils_trace_info ("Out of memory") ;
|
|
+ return NULL ;
|
|
+ }
|
|
+ memset (result, 0, sizeof (CRString)) ;
|
|
+ result->stryng = g_string_new (NULL) ;
|
|
+ return result ;
|
|
+}
|
|
+
|
|
+/**
|
|
+ *Instanciate a string and initialise it to
|
|
+ *a_string.
|
|
+ *@param a_string the initial string
|
|
+ *@return the newly instanciated string.
|
|
+ */
|
|
+CRString *
|
|
+cr_string_new_from_string (const gchar * a_string)
|
|
+{
|
|
+ CRString *result = NULL ;
|
|
+
|
|
+ result = cr_string_new () ;
|
|
+ if (!result) {
|
|
+ cr_utils_trace_info ("Out of memory") ;
|
|
+ return NULL ;
|
|
+ }
|
|
+ if (a_string)
|
|
+ g_string_append (result->stryng, a_string) ;
|
|
+ return result ;
|
|
+}
|
|
+
|
|
+/**
|
|
+ *Instanciates a #CRString from an instance of GString.
|
|
+ *@param a_string the input string that will be copied into
|
|
+ *the newly instanciated #CRString
|
|
+ *@return the newly instanciated #CRString.
|
|
+ */
|
|
+CRString *
|
|
+cr_string_new_from_gstring (GString const *a_string)
|
|
+{
|
|
+ CRString *result = NULL ;
|
|
+
|
|
+ result = cr_string_new () ;
|
|
+ if (!result) {
|
|
+ cr_utils_trace_info ("Out of memory") ;
|
|
+ return NULL ;
|
|
+ }
|
|
+ if (a_string) {
|
|
+ g_string_append_len (result->stryng,
|
|
+ a_string->str,
|
|
+ a_string->len);
|
|
+
|
|
+ }
|
|
+ return result ;
|
|
+}
|
|
+
|
|
+CRString *
|
|
+cr_string_dup (CRString const *a_this)
|
|
+{
|
|
+ CRString *result = NULL ;
|
|
+ g_return_val_if_fail (a_this, NULL) ;
|
|
+
|
|
+ result = cr_string_new_from_gstring (a_this->stryng) ;
|
|
+ if (!result) {
|
|
+ cr_utils_trace_info ("Out of memory") ;
|
|
+ return NULL ;
|
|
+ }
|
|
+ cr_parsing_location_copy (&result->location,
|
|
+ &a_this->location) ;
|
|
+ return result ;
|
|
+}
|
|
+
|
|
+gchar *
|
|
+cr_string_dup2 (CRString const *a_this)
|
|
+{
|
|
+ gchar *result = NULL ;
|
|
+
|
|
+ g_return_val_if_fail (a_this, NULL) ;
|
|
+
|
|
+ if (a_this
|
|
+ && a_this->stryng
|
|
+ && a_this->stryng->str) {
|
|
+ result = g_strndup (a_this->stryng->str,
|
|
+ a_this->stryng->len) ;
|
|
+ }
|
|
+ return result ;
|
|
+}
|
|
+
|
|
+/**
|
|
+ *Returns a pointer to the internal raw NULL terminated string
|
|
+ *of the current instance of #CRString.
|
|
+ *@param a_this the current instance of #CRString
|
|
+ */
|
|
+const gchar *
|
|
+cr_string_peek_raw_str (CRString const *a_this)
|
|
+{
|
|
+ g_return_val_if_fail (a_this, NULL) ;
|
|
+
|
|
+ if (a_this->stryng && a_this->stryng->str)
|
|
+ return a_this->stryng->str ;
|
|
+ return NULL ;
|
|
+}
|
|
+
|
|
+/**
|
|
+ *Returns the length of the internal raw NULL terminated
|
|
+ *string of the current instance of #CRString.
|
|
+ *@param a_this the current instance of #CRString.
|
|
+ *@return the len of the internal raw NULL termninated string,
|
|
+ *of -1 if no length can be returned.
|
|
+ */
|
|
+gint
|
|
+cr_string_peek_raw_str_len (CRString const *a_this)
|
|
+{
|
|
+ g_return_val_if_fail (a_this && a_this->stryng,
|
|
+ -1) ;
|
|
+ return a_this->stryng->len ;
|
|
+}
|
|
+
|
|
+/**
|
|
+ *@param a_this the #CRString to destroy.
|
|
+ */
|
|
+void
|
|
+cr_string_destroy (CRString *a_this)
|
|
+{
|
|
+ g_return_if_fail (a_this) ;
|
|
+
|
|
+ if (a_this->stryng) {
|
|
+ g_string_free (a_this->stryng, TRUE) ;
|
|
+ a_this->stryng = NULL ;
|
|
+ }
|
|
+ g_free (a_this) ;
|
|
+}
|
|
diff --git a/src/st/croco/cr-string.h b/src/st/croco/cr-string.h
|
|
new file mode 100644
|
|
index 000000000..2700f0e2e
|
|
--- /dev/null
|
|
+++ b/src/st/croco/cr-string.h
|
|
@@ -0,0 +1,76 @@
|
|
+/* -*- 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
|
|
+ *
|
|
+ * See COPYRIGHTS file for copyright information.
|
|
+ */
|
|
+
|
|
+/**
|
|
+ *@file
|
|
+ *Declaration file of the #CRString class.
|
|
+ */
|
|
+
|
|
+#ifndef __CR_STRING_H__
|
|
+#define __CR_STRING_H__
|
|
+
|
|
+#include <glib.h>
|
|
+#include "cr-utils.h"
|
|
+#include "cr-parsing-location.h"
|
|
+
|
|
+G_BEGIN_DECLS
|
|
+
|
|
+typedef struct _CRString CRString ;
|
|
+
|
|
+/**
|
|
+ *This is a ship implementation of string based on GString.
|
|
+ *Actually, the aim of CRString is to store the parsing location
|
|
+ *(line,column,byte offset) at which a given string has been parsed
|
|
+ *in the input CSS.
|
|
+ *So this class has a gstring field of type GString that users can
|
|
+ *freely manipulate, and also a CRParginLocation type where the
|
|
+ *parsing location is store. If you don't want to deal with parsing
|
|
+ *location stuffs, then use GString instead. If we were in C++ for example,
|
|
+ *CRString would just inherit GString and just add accessors to
|
|
+ *the CRParsingLocation data ... but we are not and we still have
|
|
+ *to provide the parsing location information.
|
|
+ */
|
|
+struct _CRString {
|
|
+ /**
|
|
+ *The GString where all the string
|
|
+ *operation happen.
|
|
+ */
|
|
+ GString *stryng ;
|
|
+ /**
|
|
+ *The parsing location storage area.
|
|
+ */
|
|
+ CRParsingLocation location ;
|
|
+} ;
|
|
+
|
|
+CRString * cr_string_new (void) ;
|
|
+
|
|
+CRString *cr_string_new_from_string (const gchar * a_string) ;
|
|
+CRString * cr_string_new_from_gstring (GString const *a_string) ;
|
|
+CRString *cr_string_dup (CRString const *a_this) ;
|
|
+gchar *cr_string_dup2 (CRString const *a_this) ;
|
|
+const gchar *cr_string_peek_raw_str (CRString const *a_this) ;
|
|
+gint cr_string_peek_raw_str_len (CRString const *a_this) ;
|
|
+void cr_string_destroy (CRString *a_this) ;
|
|
+
|
|
+G_END_DECLS
|
|
+
|
|
+#endif
|
|
diff --git a/src/st/croco/cr-stylesheet.c b/src/st/croco/cr-stylesheet.c
|
|
new file mode 100644
|
|
index 000000000..69909da24
|
|
--- /dev/null
|
|
+++ b/src/st/croco/cr-stylesheet.c
|
|
@@ -0,0 +1,178 @@
|
|
+/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
|
|
+
|
|
+/*
|
|
+ * This file is part of The Croco Library
|
|
+ *
|
|
+ * Copyright (C) 2002-2004 Dodji Seketeli
|
|
+ *
|
|
+ * 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
|
|
+ */
|
|
+
|
|
+#include "string.h"
|
|
+#include "cr-stylesheet.h"
|
|
+
|
|
+/**
|
|
+ *@file
|
|
+ *The definition of the #CRStyleSheet class
|
|
+ */
|
|
+
|
|
+/**
|
|
+ *Constructor of the #CRStyleSheet class.
|
|
+ *@param the initial list of css statements.
|
|
+ *@return the newly built css2 stylesheet, or NULL in case of error.
|
|
+ */
|
|
+CRStyleSheet *
|
|
+cr_stylesheet_new (CRStatement * a_stmts)
|
|
+{
|
|
+ CRStyleSheet *result;
|
|
+
|
|
+ result = g_try_malloc (sizeof (CRStyleSheet));
|
|
+ if (!result) {
|
|
+ cr_utils_trace_info ("Out of memory");
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
+ memset (result, 0, sizeof (CRStyleSheet));
|
|
+
|
|
+ if (a_stmts)
|
|
+ result->statements = a_stmts;
|
|
+
|
|
+ return result;
|
|
+}
|
|
+
|
|
+/**
|
|
+ *@param a_this the current instance of #CRStyleSheet
|
|
+ *@return the serialized stylesheet.
|
|
+ */
|
|
+gchar *
|
|
+cr_stylesheet_to_string (CRStyleSheet const *a_this)
|
|
+{
|
|
+ gchar *str = NULL;
|
|
+ GString *stringue = NULL;
|
|
+ CRStatement const *cur_stmt = NULL;
|
|
+
|
|
+ g_return_val_if_fail (a_this, NULL);
|
|
+
|
|
+ if (a_this->statements) {
|
|
+ stringue = g_string_new (NULL) ;
|
|
+ g_return_val_if_fail (stringue, NULL) ;
|
|
+ }
|
|
+ for (cur_stmt = a_this->statements;
|
|
+ cur_stmt; cur_stmt = cur_stmt->next) {
|
|
+ if (cur_stmt->prev) {
|
|
+ g_string_append (stringue, "\n\n") ;
|
|
+ }
|
|
+ str = cr_statement_to_string (cur_stmt, 0) ;
|
|
+ if (str) {
|
|
+ g_string_append (stringue, str) ;
|
|
+ g_free (str) ;
|
|
+ str = NULL ;
|
|
+ }
|
|
+ }
|
|
+ if (stringue) {
|
|
+ str = stringue->str ;
|
|
+ g_string_free (stringue, FALSE) ;
|
|
+ stringue = NULL ;
|
|
+ }
|
|
+ return str ;
|
|
+}
|
|
+
|
|
+/**
|
|
+ *Dumps the current css2 stylesheet to a file.
|
|
+ *@param a_this the current instance of #CRStyleSheet.
|
|
+ *@param a_fp the destination file
|
|
+ */
|
|
+void
|
|
+cr_stylesheet_dump (CRStyleSheet const * a_this, FILE * a_fp)
|
|
+{
|
|
+ gchar *str = NULL ;
|
|
+
|
|
+ g_return_if_fail (a_this);
|
|
+
|
|
+ str = cr_stylesheet_to_string (a_this) ;
|
|
+ if (str) {
|
|
+ fprintf (a_fp, "%s", str) ;
|
|
+ g_free (str) ;
|
|
+ str = NULL ;
|
|
+ }
|
|
+}
|
|
+
|
|
+/**
|
|
+ *Return the number of rules in the stylesheet.
|
|
+ *@param a_this the current instance of #CRStyleSheet.
|
|
+ *@return number of rules in the stylesheet.
|
|
+ */
|
|
+gint
|
|
+cr_stylesheet_nr_rules (CRStyleSheet const * a_this)
|
|
+{
|
|
+ g_return_val_if_fail (a_this, -1);
|
|
+
|
|
+ return cr_statement_nr_rules (a_this->statements);
|
|
+}
|
|
+
|
|
+/**
|
|
+ *Use an index to get a CRStatement from the rules in a given stylesheet.
|
|
+ *@param a_this the current instance of #CRStatement.
|
|
+ *@param itemnr the index into the rules.
|
|
+ *@return CRStatement at position itemnr, if itemnr > number of rules - 1,
|
|
+ *it will return NULL.
|
|
+ */
|
|
+CRStatement *
|
|
+cr_stylesheet_statement_get_from_list (CRStyleSheet * a_this, int itemnr)
|
|
+{
|
|
+ g_return_val_if_fail (a_this, NULL);
|
|
+
|
|
+ return cr_statement_get_from_list (a_this->statements, itemnr);
|
|
+}
|
|
+
|
|
+void
|
|
+cr_stylesheet_ref (CRStyleSheet * a_this)
|
|
+{
|
|
+ g_return_if_fail (a_this);
|
|
+
|
|
+ a_this->ref_count++;
|
|
+}
|
|
+
|
|
+gboolean
|
|
+cr_stylesheet_unref (CRStyleSheet * a_this)
|
|
+{
|
|
+ g_return_val_if_fail (a_this, FALSE);
|
|
+
|
|
+ if (a_this->ref_count)
|
|
+ a_this->ref_count--;
|
|
+
|
|
+ if (!a_this->ref_count) {
|
|
+ cr_stylesheet_destroy (a_this);
|
|
+ return TRUE;
|
|
+ }
|
|
+
|
|
+ return FALSE;
|
|
+}
|
|
+
|
|
+/**
|
|
+ *Destructor of the #CRStyleSheet class.
|
|
+ *@param a_this the current instance of the #CRStyleSheet class.
|
|
+ */
|
|
+void
|
|
+cr_stylesheet_destroy (CRStyleSheet * a_this)
|
|
+{
|
|
+ g_return_if_fail (a_this);
|
|
+
|
|
+ if (a_this->statements) {
|
|
+ cr_statement_destroy (a_this->statements);
|
|
+ a_this->statements = NULL;
|
|
+ }
|
|
+ g_free (a_this);
|
|
+}
|
|
diff --git a/src/st/croco/cr-stylesheet.h b/src/st/croco/cr-stylesheet.h
|
|
new file mode 100644
|
|
index 000000000..f35c94e37
|
|
--- /dev/null
|
|
+++ b/src/st/croco/cr-stylesheet.h
|
|
@@ -0,0 +1,102 @@
|
|
+/* -*- 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
|
|
+ *
|
|
+ * see COPYRIGHTS file for copyright information.
|
|
+ */
|
|
+
|
|
+
|
|
+#ifndef __CR_STYLESHEET_H__
|
|
+#define __CR_STYLESHEET_H__
|
|
+
|
|
+#include "cr-utils.h"
|
|
+#include "cr-statement.h"
|
|
+
|
|
+G_BEGIN_DECLS
|
|
+
|
|
+/**
|
|
+ *@file
|
|
+ *The declaration of the #CRStyleSheet class.
|
|
+ */
|
|
+
|
|
+
|
|
+enum CRStyleOrigin
|
|
+{
|
|
+ /*Please don't change the order of
|
|
+ *the values enumerated here ...
|
|
+ *New values should be added at the end,
|
|
+ *just before ORIGIN_END.
|
|
+ */
|
|
+ ORIGIN_UA = 0,
|
|
+ ORIGIN_USER,
|
|
+ ORIGIN_AUTHOR,
|
|
+
|
|
+ /*must always be the last one*/
|
|
+ NB_ORIGINS
|
|
+} ;
|
|
+
|
|
+/**
|
|
+ *An abstraction of a css stylesheet as defined
|
|
+ *by the css2 spec in chapter 4.
|
|
+ */
|
|
+struct _CRStyleSheet
|
|
+{
|
|
+ /**The css statements list*/
|
|
+ CRStatement *statements ;
|
|
+
|
|
+ enum CRStyleOrigin origin ;
|
|
+
|
|
+ /*the parent import rule, if any.*/
|
|
+ CRStatement *parent_import_rule ;
|
|
+
|
|
+ /**custom data used by libcroco*/
|
|
+ gpointer croco_data ;
|
|
+
|
|
+ /**
|
|
+ *custom application data pointer
|
|
+ *Can be used by applications.
|
|
+ */
|
|
+ gpointer app_data ;
|
|
+
|
|
+ /**
|
|
+ *the reference count of this insance
|
|
+ *Please, don't never ever modify it
|
|
+ *directly. Use cr_stylesheet_ref()
|
|
+ *and cr_stylesheet_unref() instead.
|
|
+ */
|
|
+ gulong ref_count ;
|
|
+} ;
|
|
+
|
|
+CRStyleSheet * cr_stylesheet_new (CRStatement *a_stmts) ;
|
|
+
|
|
+gchar * cr_stylesheet_to_string (CRStyleSheet const *a_this) ;
|
|
+void cr_stylesheet_dump (CRStyleSheet const *a_this, FILE *a_fp) ;
|
|
+
|
|
+gint cr_stylesheet_nr_rules (CRStyleSheet const *a_this) ;
|
|
+
|
|
+CRStatement * cr_stylesheet_statement_get_from_list (CRStyleSheet *a_this, int itemnr) ;
|
|
+
|
|
+void cr_stylesheet_ref (CRStyleSheet *a_this) ;
|
|
+
|
|
+gboolean cr_stylesheet_unref (CRStyleSheet *a_this) ;
|
|
+
|
|
+void cr_stylesheet_destroy (CRStyleSheet *a_this) ;
|
|
+
|
|
+G_END_DECLS
|
|
+
|
|
+#endif /*__CR_STYLESHEET_H__*/
|
|
diff --git a/src/st/croco/cr-term.c b/src/st/croco/cr-term.c
|
|
new file mode 100644
|
|
index 000000000..9ffe6727b
|
|
--- /dev/null
|
|
+++ b/src/st/croco/cr-term.c
|
|
@@ -0,0 +1,790 @@
|
|
+/* -*- 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 <stdio.h>
|
|
+#include <string.h>
|
|
+#include "cr-term.h"
|
|
+#include "cr-num.h"
|
|
+#include "cr-parser.h"
|
|
+
|
|
+/**
|
|
+ *@file
|
|
+ *Definition of the #CRTem class.
|
|
+ */
|
|
+
|
|
+static void
|
|
+cr_term_clear (CRTerm * a_this)
|
|
+{
|
|
+ g_return_if_fail (a_this);
|
|
+
|
|
+ switch (a_this->type) {
|
|
+ case TERM_NUMBER:
|
|
+ if (a_this->content.num) {
|
|
+ cr_num_destroy (a_this->content.num);
|
|
+ a_this->content.num = NULL;
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case TERM_FUNCTION:
|
|
+ if (a_this->ext_content.func_param) {
|
|
+ cr_term_destroy (a_this->ext_content.func_param);
|
|
+ a_this->ext_content.func_param = NULL;
|
|
+ }
|
|
+ case TERM_STRING:
|
|
+ case TERM_IDENT:
|
|
+ case TERM_URI:
|
|
+ case TERM_HASH:
|
|
+ if (a_this->content.str) {
|
|
+ cr_string_destroy (a_this->content.str);
|
|
+ a_this->content.str = NULL;
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case TERM_RGB:
|
|
+ if (a_this->content.rgb) {
|
|
+ cr_rgb_destroy (a_this->content.rgb);
|
|
+ a_this->content.rgb = NULL;
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case TERM_UNICODERANGE:
|
|
+ case TERM_NO_TYPE:
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ a_this->type = TERM_NO_TYPE;
|
|
+}
|
|
+
|
|
+/**
|
|
+ *Instanciate a #CRTerm.
|
|
+ *@return the newly build instance
|
|
+ *of #CRTerm.
|
|
+ */
|
|
+CRTerm *
|
|
+cr_term_new (void)
|
|
+{
|
|
+ CRTerm *result = NULL;
|
|
+
|
|
+ result = g_try_malloc (sizeof (CRTerm));
|
|
+ if (!result) {
|
|
+ cr_utils_trace_info ("Out of memory");
|
|
+ return NULL;
|
|
+ }
|
|
+ memset (result, 0, sizeof (CRTerm));
|
|
+ return result;
|
|
+}
|
|
+
|
|
+/**
|
|
+ *Parses an expresion as defined by the css2 spec
|
|
+ *and builds the expression as a list of terms.
|
|
+ *@param a_buf the buffer to parse.
|
|
+ *@return a pointer to the first term of the expression or
|
|
+ *NULL if parsing failed.
|
|
+ */
|
|
+CRTerm *
|
|
+cr_term_parse_expression_from_buf (const guchar * a_buf,
|
|
+ enum CREncoding a_encoding)
|
|
+{
|
|
+ CRParser *parser = NULL;
|
|
+ CRTerm *result = NULL;
|
|
+ enum CRStatus status = CR_OK;
|
|
+
|
|
+ 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);
|
|
+ g_return_val_if_fail (parser, NULL);
|
|
+
|
|
+ status = cr_parser_try_to_skip_spaces_and_comments (parser);
|
|
+ if (status != CR_OK) {
|
|
+ goto cleanup;
|
|
+ }
|
|
+ status = cr_parser_parse_expr (parser, &result);
|
|
+ if (status != CR_OK) {
|
|
+ if (result) {
|
|
+ cr_term_destroy (result);
|
|
+ result = NULL;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ cleanup:
|
|
+ if (parser) {
|
|
+ cr_parser_destroy (parser);
|
|
+ parser = NULL;
|
|
+ }
|
|
+
|
|
+ return result;
|
|
+}
|
|
+
|
|
+enum CRStatus
|
|
+cr_term_set_number (CRTerm * a_this, CRNum * a_num)
|
|
+{
|
|
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ cr_term_clear (a_this);
|
|
+
|
|
+ a_this->type = TERM_NUMBER;
|
|
+ a_this->content.num = a_num;
|
|
+ return CR_OK;
|
|
+}
|
|
+
|
|
+enum CRStatus
|
|
+cr_term_set_function (CRTerm * a_this, CRString * a_func_name,
|
|
+ CRTerm * a_func_param)
|
|
+{
|
|
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ cr_term_clear (a_this);
|
|
+
|
|
+ a_this->type = TERM_FUNCTION;
|
|
+ a_this->content.str = a_func_name;
|
|
+ a_this->ext_content.func_param = a_func_param;
|
|
+ return CR_OK;
|
|
+}
|
|
+
|
|
+enum CRStatus
|
|
+cr_term_set_string (CRTerm * a_this, CRString * a_str)
|
|
+{
|
|
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ cr_term_clear (a_this);
|
|
+
|
|
+ a_this->type = TERM_STRING;
|
|
+ a_this->content.str = a_str;
|
|
+ return CR_OK;
|
|
+}
|
|
+
|
|
+enum CRStatus
|
|
+cr_term_set_ident (CRTerm * a_this, CRString * a_str)
|
|
+{
|
|
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ cr_term_clear (a_this);
|
|
+
|
|
+ a_this->type = TERM_IDENT;
|
|
+ a_this->content.str = a_str;
|
|
+ return CR_OK;
|
|
+}
|
|
+
|
|
+enum CRStatus
|
|
+cr_term_set_uri (CRTerm * a_this, CRString * a_str)
|
|
+{
|
|
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ cr_term_clear (a_this);
|
|
+
|
|
+ a_this->type = TERM_URI;
|
|
+ a_this->content.str = a_str;
|
|
+ return CR_OK;
|
|
+}
|
|
+
|
|
+enum CRStatus
|
|
+cr_term_set_rgb (CRTerm * a_this, CRRgb * a_rgb)
|
|
+{
|
|
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ cr_term_clear (a_this);
|
|
+
|
|
+ a_this->type = TERM_RGB;
|
|
+ a_this->content.rgb = a_rgb;
|
|
+ return CR_OK;
|
|
+}
|
|
+
|
|
+enum CRStatus
|
|
+cr_term_set_hash (CRTerm * a_this, CRString * a_str)
|
|
+{
|
|
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ cr_term_clear (a_this);
|
|
+
|
|
+ a_this->type = TERM_HASH;
|
|
+ a_this->content.str = a_str;
|
|
+ return CR_OK;
|
|
+}
|
|
+
|
|
+/**
|
|
+ *Appends a new term to the current list of #CRTerm.
|
|
+ *
|
|
+ *@param a_this the "this pointer" of the current instance
|
|
+ *of #CRTerm .
|
|
+ *@param a_new_term the term to append.
|
|
+ *@return the list of terms with the a_new_term appended to it.
|
|
+ */
|
|
+CRTerm *
|
|
+cr_term_append_term (CRTerm * a_this, CRTerm * a_new_term)
|
|
+{
|
|
+ CRTerm *cur = NULL;
|
|
+
|
|
+ g_return_val_if_fail (a_new_term, NULL);
|
|
+
|
|
+ if (a_this == NULL)
|
|
+ return a_new_term;
|
|
+
|
|
+ for (cur = a_this; cur->next; cur = cur->next) ;
|
|
+
|
|
+ cur->next = a_new_term;
|
|
+ a_new_term->prev = cur;
|
|
+
|
|
+ return a_this;
|
|
+}
|
|
+
|
|
+/**
|
|
+ *Prepends a term to the list of terms represented by a_this.
|
|
+ *
|
|
+ *@param a_this the "this pointer" of the current instance of
|
|
+ *#CRTerm .
|
|
+ *@param a_new_term the term to prepend.
|
|
+ *@return the head of the new list.
|
|
+ */
|
|
+CRTerm *
|
|
+cr_term_prepend_term (CRTerm * a_this, CRTerm * a_new_term)
|
|
+{
|
|
+ g_return_val_if_fail (a_this && a_new_term, NULL);
|
|
+
|
|
+ a_new_term->next = a_this;
|
|
+ a_this->prev = a_new_term;
|
|
+
|
|
+ return a_new_term;
|
|
+}
|
|
+
|
|
+/**
|
|
+ *Serializes the expression represented by
|
|
+ *the chained instances of #CRterm.
|
|
+ *@param a_this the current instance of #CRTerm
|
|
+ *@return the zero terminated string containing the serialized
|
|
+ *form of #CRTerm. MUST BE FREED BY THE CALLER using g_free().
|
|
+ */
|
|
+guchar *
|
|
+cr_term_to_string (CRTerm const * a_this)
|
|
+{
|
|
+ GString *str_buf = NULL;
|
|
+ CRTerm const *cur = NULL;
|
|
+ guchar *result = NULL,
|
|
+ *content = NULL;
|
|
+
|
|
+ g_return_val_if_fail (a_this, NULL);
|
|
+
|
|
+ str_buf = g_string_new (NULL);
|
|
+ g_return_val_if_fail (str_buf, NULL);
|
|
+
|
|
+ for (cur = a_this; cur; cur = cur->next) {
|
|
+ if ((cur->content.str == NULL)
|
|
+ && (cur->content.num == NULL)
|
|
+ && (cur->content.str == NULL)
|
|
+ && (cur->content.rgb == NULL))
|
|
+ continue;
|
|
+
|
|
+ switch (cur->the_operator) {
|
|
+ case DIVIDE:
|
|
+ g_string_append (str_buf, " / ");
|
|
+ break;
|
|
+
|
|
+ case COMMA:
|
|
+ g_string_append (str_buf, ", ");
|
|
+ break;
|
|
+
|
|
+ case NO_OP:
|
|
+ if (cur->prev) {
|
|
+ g_string_append (str_buf, " ");
|
|
+ }
|
|
+ break;
|
|
+ default:
|
|
+
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ switch (cur->unary_op) {
|
|
+ case PLUS_UOP:
|
|
+ g_string_append (str_buf, "+");
|
|
+ break;
|
|
+
|
|
+ case MINUS_UOP:
|
|
+ g_string_append (str_buf, "-");
|
|
+ break;
|
|
+
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ switch (cur->type) {
|
|
+ case TERM_NUMBER:
|
|
+ if (cur->content.num) {
|
|
+ content = cr_num_to_string (cur->content.num);
|
|
+ }
|
|
+
|
|
+ if (content) {
|
|
+ g_string_append (str_buf, (const gchar *) content);
|
|
+ g_free (content);
|
|
+ content = NULL;
|
|
+ }
|
|
+
|
|
+ break;
|
|
+
|
|
+ case TERM_FUNCTION:
|
|
+ if (cur->content.str) {
|
|
+ content = (guchar *) g_strndup
|
|
+ (cur->content.str->stryng->str,
|
|
+ cur->content.str->stryng->len);
|
|
+ }
|
|
+
|
|
+ if (content) {
|
|
+ g_string_append_printf (str_buf, "%s(",
|
|
+ content);
|
|
+
|
|
+ if (cur->ext_content.func_param) {
|
|
+ guchar *tmp_str = NULL;
|
|
+
|
|
+ tmp_str = cr_term_to_string
|
|
+ (cur->
|
|
+ ext_content.func_param);
|
|
+
|
|
+ if (tmp_str) {
|
|
+ g_string_append (str_buf,
|
|
+ (const gchar *) tmp_str);
|
|
+ g_free (tmp_str);
|
|
+ tmp_str = NULL;
|
|
+ }
|
|
+ }
|
|
+ g_string_append (str_buf, ")");
|
|
+ g_free (content);
|
|
+ content = NULL;
|
|
+ }
|
|
+
|
|
+ break;
|
|
+
|
|
+ case TERM_STRING:
|
|
+ if (cur->content.str) {
|
|
+ content = (guchar *) g_strndup
|
|
+ (cur->content.str->stryng->str,
|
|
+ cur->content.str->stryng->len);
|
|
+ }
|
|
+
|
|
+ if (content) {
|
|
+ g_string_append_printf (str_buf,
|
|
+ "\"%s\"", content);
|
|
+ g_free (content);
|
|
+ content = NULL;
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case TERM_IDENT:
|
|
+ if (cur->content.str) {
|
|
+ content = (guchar *) g_strndup
|
|
+ (cur->content.str->stryng->str,
|
|
+ cur->content.str->stryng->len);
|
|
+ }
|
|
+
|
|
+ if (content) {
|
|
+ g_string_append (str_buf, (const gchar *) content);
|
|
+ g_free (content);
|
|
+ content = NULL;
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case TERM_URI:
|
|
+ if (cur->content.str) {
|
|
+ content = (guchar *) g_strndup
|
|
+ (cur->content.str->stryng->str,
|
|
+ cur->content.str->stryng->len);
|
|
+ }
|
|
+
|
|
+ if (content) {
|
|
+ g_string_append_printf
|
|
+ (str_buf, "url(%s)", content);
|
|
+ g_free (content);
|
|
+ content = NULL;
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case TERM_RGB:
|
|
+ if (cur->content.rgb) {
|
|
+ guchar *tmp_str = NULL;
|
|
+
|
|
+ g_string_append (str_buf, "rgb(");
|
|
+ tmp_str = cr_rgb_to_string (cur->content.rgb);
|
|
+
|
|
+ if (tmp_str) {
|
|
+ g_string_append (str_buf, (const gchar *) tmp_str);
|
|
+ g_free (tmp_str);
|
|
+ tmp_str = NULL;
|
|
+ }
|
|
+ g_string_append (str_buf, ")");
|
|
+ }
|
|
+
|
|
+ break;
|
|
+
|
|
+ case TERM_UNICODERANGE:
|
|
+ g_string_append
|
|
+ (str_buf,
|
|
+ "?found unicoderange: dump not supported yet?");
|
|
+ break;
|
|
+
|
|
+ case TERM_HASH:
|
|
+ if (cur->content.str) {
|
|
+ content = (guchar *) g_strndup
|
|
+ (cur->content.str->stryng->str,
|
|
+ cur->content.str->stryng->len);
|
|
+ }
|
|
+
|
|
+ if (content) {
|
|
+ g_string_append_printf (str_buf,
|
|
+ "#%s", content);
|
|
+ g_free (content);
|
|
+ content = NULL;
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ default:
|
|
+ g_string_append (str_buf,
|
|
+ "Unrecognized Term type");
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (str_buf) {
|
|
+ result =(guchar *) str_buf->str;
|
|
+ g_string_free (str_buf, FALSE);
|
|
+ str_buf = NULL;
|
|
+ }
|
|
+
|
|
+ return result;
|
|
+}
|
|
+
|
|
+guchar *
|
|
+cr_term_one_to_string (CRTerm const * a_this)
|
|
+{
|
|
+ GString *str_buf = NULL;
|
|
+ guchar *result = NULL,
|
|
+ *content = NULL;
|
|
+
|
|
+ g_return_val_if_fail (a_this, NULL);
|
|
+
|
|
+ str_buf = g_string_new (NULL);
|
|
+ g_return_val_if_fail (str_buf, NULL);
|
|
+
|
|
+ if ((a_this->content.str == NULL)
|
|
+ && (a_this->content.num == NULL)
|
|
+ && (a_this->content.str == NULL)
|
|
+ && (a_this->content.rgb == NULL))
|
|
+ return NULL ;
|
|
+
|
|
+ switch (a_this->the_operator) {
|
|
+ case DIVIDE:
|
|
+ g_string_append_printf (str_buf, " / ");
|
|
+ break;
|
|
+
|
|
+ case COMMA:
|
|
+ g_string_append_printf (str_buf, ", ");
|
|
+ break;
|
|
+
|
|
+ case NO_OP:
|
|
+ if (a_this->prev) {
|
|
+ g_string_append_printf (str_buf, " ");
|
|
+ }
|
|
+ break;
|
|
+ default:
|
|
+
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ switch (a_this->unary_op) {
|
|
+ case PLUS_UOP:
|
|
+ g_string_append_printf (str_buf, "+");
|
|
+ break;
|
|
+
|
|
+ case MINUS_UOP:
|
|
+ g_string_append_printf (str_buf, "-");
|
|
+ break;
|
|
+
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ switch (a_this->type) {
|
|
+ case TERM_NUMBER:
|
|
+ if (a_this->content.num) {
|
|
+ content = cr_num_to_string (a_this->content.num);
|
|
+ }
|
|
+
|
|
+ if (content) {
|
|
+ g_string_append (str_buf, (const gchar *) content);
|
|
+ g_free (content);
|
|
+ content = NULL;
|
|
+ }
|
|
+
|
|
+ break;
|
|
+
|
|
+ case TERM_FUNCTION:
|
|
+ if (a_this->content.str) {
|
|
+ content = (guchar *) g_strndup
|
|
+ (a_this->content.str->stryng->str,
|
|
+ a_this->content.str->stryng->len);
|
|
+ }
|
|
+
|
|
+ if (content) {
|
|
+ g_string_append_printf (str_buf, "%s(",
|
|
+ content);
|
|
+
|
|
+ if (a_this->ext_content.func_param) {
|
|
+ guchar *tmp_str = NULL;
|
|
+
|
|
+ tmp_str = cr_term_to_string
|
|
+ (a_this->
|
|
+ ext_content.func_param);
|
|
+
|
|
+ if (tmp_str) {
|
|
+ g_string_append_printf
|
|
+ (str_buf,
|
|
+ "%s", tmp_str);
|
|
+ g_free (tmp_str);
|
|
+ tmp_str = NULL;
|
|
+ }
|
|
+
|
|
+ g_string_append_printf (str_buf, ")");
|
|
+ g_free (content);
|
|
+ content = NULL;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ break;
|
|
+
|
|
+ case TERM_STRING:
|
|
+ if (a_this->content.str) {
|
|
+ content = (guchar *) g_strndup
|
|
+ (a_this->content.str->stryng->str,
|
|
+ a_this->content.str->stryng->len);
|
|
+ }
|
|
+
|
|
+ if (content) {
|
|
+ g_string_append_printf (str_buf,
|
|
+ "\"%s\"", content);
|
|
+ g_free (content);
|
|
+ content = NULL;
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case TERM_IDENT:
|
|
+ if (a_this->content.str) {
|
|
+ content = (guchar *) g_strndup
|
|
+ (a_this->content.str->stryng->str,
|
|
+ a_this->content.str->stryng->len);
|
|
+ }
|
|
+
|
|
+ if (content) {
|
|
+ g_string_append (str_buf, (const gchar *) content);
|
|
+ g_free (content);
|
|
+ content = NULL;
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case TERM_URI:
|
|
+ if (a_this->content.str) {
|
|
+ content = (guchar *) g_strndup
|
|
+ (a_this->content.str->stryng->str,
|
|
+ a_this->content.str->stryng->len);
|
|
+ }
|
|
+
|
|
+ if (content) {
|
|
+ g_string_append_printf
|
|
+ (str_buf, "url(%s)", content);
|
|
+ g_free (content);
|
|
+ content = NULL;
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case TERM_RGB:
|
|
+ if (a_this->content.rgb) {
|
|
+ guchar *tmp_str = NULL;
|
|
+
|
|
+ g_string_append_printf (str_buf, "rgb(");
|
|
+ tmp_str = cr_rgb_to_string (a_this->content.rgb);
|
|
+
|
|
+ if (tmp_str) {
|
|
+ g_string_append (str_buf, (const gchar *) tmp_str);
|
|
+ g_free (tmp_str);
|
|
+ tmp_str = NULL;
|
|
+ }
|
|
+ g_string_append_printf (str_buf, ")");
|
|
+ }
|
|
+
|
|
+ break;
|
|
+
|
|
+ case TERM_UNICODERANGE:
|
|
+ g_string_append_printf
|
|
+ (str_buf,
|
|
+ "?found unicoderange: dump not supported yet?");
|
|
+ break;
|
|
+
|
|
+ case TERM_HASH:
|
|
+ if (a_this->content.str) {
|
|
+ content = (guchar *) g_strndup
|
|
+ (a_this->content.str->stryng->str,
|
|
+ a_this->content.str->stryng->len);
|
|
+ }
|
|
+
|
|
+ if (content) {
|
|
+ g_string_append_printf (str_buf,
|
|
+ "#%s", content);
|
|
+ g_free (content);
|
|
+ content = NULL;
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ default:
|
|
+ g_string_append_printf (str_buf,
|
|
+ "%s",
|
|
+ "Unrecognized Term type");
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ if (str_buf) {
|
|
+ result = (guchar *) str_buf->str;
|
|
+ g_string_free (str_buf, FALSE);
|
|
+ str_buf = NULL;
|
|
+ }
|
|
+
|
|
+ return result;
|
|
+}
|
|
+
|
|
+/**
|
|
+ *Dumps the expression (a list of terms connected by operators)
|
|
+ *to a file.
|
|
+ *TODO: finish the dump. The dump of some type of terms have not yet been
|
|
+ *implemented.
|
|
+ *@param a_this the current instance of #CRTerm.
|
|
+ *@param a_fp the destination file pointer.
|
|
+ */
|
|
+void
|
|
+cr_term_dump (CRTerm const * a_this, FILE * a_fp)
|
|
+{
|
|
+ guchar *content = NULL;
|
|
+
|
|
+ g_return_if_fail (a_this);
|
|
+
|
|
+ content = cr_term_to_string (a_this);
|
|
+
|
|
+ if (content) {
|
|
+ fprintf (a_fp, "%s", content);
|
|
+ g_free (content);
|
|
+ }
|
|
+}
|
|
+
|
|
+/**
|
|
+ *Return the number of terms in the expression.
|
|
+ *@param a_this the current instance of #CRTerm.
|
|
+ *@return number of terms in the expression.
|
|
+ */
|
|
+int
|
|
+cr_term_nr_values (CRTerm const *a_this)
|
|
+{
|
|
+ CRTerm 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;
|
|
+}
|
|
+
|
|
+/**
|
|
+ *Use an index to get a CRTerm from the expression.
|
|
+ *@param a_this the current instance of #CRTerm.
|
|
+ *@param itemnr the index into the expression.
|
|
+ *@return CRTerm at position itemnr, if itemnr > number of terms - 1,
|
|
+ *it will return NULL.
|
|
+ */
|
|
+CRTerm *
|
|
+cr_term_get_from_list (CRTerm *a_this, int itemnr)
|
|
+{
|
|
+ CRTerm *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;
|
|
+}
|
|
+
|
|
+/**
|
|
+ *Increments the reference counter of the current instance
|
|
+ *of #CRTerm.*
|
|
+ *@param a_this the current instance of #CRTerm.
|
|
+ */
|
|
+void
|
|
+cr_term_ref (CRTerm * a_this)
|
|
+{
|
|
+ g_return_if_fail (a_this);
|
|
+
|
|
+ a_this->ref_count++;
|
|
+}
|
|
+
|
|
+/**
|
|
+ *Decrements the ref count of the current instance of
|
|
+ *#CRTerm. If the ref count reaches zero, the instance is
|
|
+ *destroyed.
|
|
+ *@param a_this the current instance of #CRTerm.
|
|
+ *@return TRUE if the current instance has been destroyed, FALSE otherwise.
|
|
+ */
|
|
+gboolean
|
|
+cr_term_unref (CRTerm * a_this)
|
|
+{
|
|
+ g_return_val_if_fail (a_this, FALSE);
|
|
+
|
|
+ if (a_this->ref_count) {
|
|
+ a_this->ref_count--;
|
|
+ }
|
|
+
|
|
+ if (a_this->ref_count == 0) {
|
|
+ cr_term_destroy (a_this);
|
|
+ return TRUE;
|
|
+ }
|
|
+
|
|
+ return FALSE;
|
|
+}
|
|
+
|
|
+/**
|
|
+ *The destructor of the the #CRTerm class.
|
|
+ *@param a_this the "this pointer" of the current instance
|
|
+ *of #CRTerm.
|
|
+ */
|
|
+void
|
|
+cr_term_destroy (CRTerm * a_this)
|
|
+{
|
|
+ g_return_if_fail (a_this);
|
|
+
|
|
+ cr_term_clear (a_this);
|
|
+
|
|
+ if (a_this->next) {
|
|
+ cr_term_destroy (a_this->next);
|
|
+ a_this->next = NULL;
|
|
+ }
|
|
+
|
|
+ if (a_this) {
|
|
+ g_free (a_this);
|
|
+ }
|
|
+
|
|
+}
|
|
diff --git a/src/st/croco/cr-term.h b/src/st/croco/cr-term.h
|
|
new file mode 100644
|
|
index 000000000..0f22dda75
|
|
--- /dev/null
|
|
+++ b/src/st/croco/cr-term.h
|
|
@@ -0,0 +1,190 @@
|
|
+/* -*- 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 <stdio.h>
|
|
+#include <glib.h>
|
|
+#include "cr-utils.h"
|
|
+#include "cr-rgb.h"
|
|
+#include "cr-num.h"
|
|
+#include "cr-string.h"
|
|
+
|
|
+#ifndef __CR_TERM_H__
|
|
+#define __CR_TERM_H__
|
|
+
|
|
+G_BEGIN_DECLS
|
|
+
|
|
+/**
|
|
+ *@file
|
|
+ *Declaration of the #CRTem class.
|
|
+ */
|
|
+
|
|
+enum CRTermType
|
|
+{
|
|
+ TERM_NO_TYPE = 0,
|
|
+ TERM_NUMBER,
|
|
+ TERM_FUNCTION,
|
|
+ TERM_STRING,
|
|
+ TERM_IDENT,
|
|
+ TERM_URI,
|
|
+ TERM_RGB,
|
|
+ TERM_UNICODERANGE,
|
|
+ TERM_HASH
|
|
+} ;
|
|
+
|
|
+
|
|
+enum UnaryOperator
|
|
+{
|
|
+ NO_UNARY_UOP = 0,
|
|
+ PLUS_UOP,
|
|
+ MINUS_UOP,
|
|
+ EMPTY_UNARY_UOP
|
|
+} ;
|
|
+
|
|
+enum Operator
|
|
+{
|
|
+ NO_OP = 0,
|
|
+ DIVIDE,
|
|
+ COMMA
|
|
+} ;
|
|
+
|
|
+struct _CRTerm ;
|
|
+typedef struct _CRTerm CRTerm ;
|
|
+
|
|
+/**
|
|
+ *An abstraction of a css2 term as
|
|
+ *defined in the CSS2 spec in appendix D.1:
|
|
+ *term ::=
|
|
+ *[ NUMBER S* | PERCENTAGE S* | LENGTH S* | EMS S* | EXS S*
|
|
+ *| ANGLE S* | TIME S* | FREQ S* | function ]
|
|
+ * | STRING S* | IDENT S* | URI S* | RGB S*
|
|
+ *| UNICODERANGE S* | hexcolor
|
|
+ */
|
|
+struct _CRTerm
|
|
+{
|
|
+ /**
|
|
+ *The type of the term.
|
|
+ */
|
|
+ enum CRTermType type ;
|
|
+
|
|
+ /**
|
|
+ *The unary operator associated to
|
|
+ *the current term.
|
|
+ */
|
|
+ enum UnaryOperator unary_op ;
|
|
+
|
|
+ /**
|
|
+ *The operator associated to the current term.
|
|
+ */
|
|
+ enum Operator the_operator ;
|
|
+
|
|
+
|
|
+ /**
|
|
+ *The content of the term.
|
|
+ *Depending of the type of the term,
|
|
+ *this holds either a number, a percentage ...
|
|
+ */
|
|
+ union
|
|
+ {
|
|
+ CRNum *num ;
|
|
+ CRString * str ;
|
|
+ CRRgb * rgb ;
|
|
+ } content ;
|
|
+
|
|
+ /**
|
|
+ *If the term is of type UNICODERANGE,
|
|
+ *this field holds the upper bound of the range.
|
|
+ *if the term is of type FUNCTION, this holds
|
|
+ *an instance of CRTerm that represents
|
|
+ * the expression which is the argument of the function.
|
|
+ */
|
|
+ union
|
|
+ {
|
|
+ CRTerm *func_param ;
|
|
+ } ext_content ;
|
|
+
|
|
+ /**
|
|
+ *A spare pointer, just in case.
|
|
+ *Can be used by the application.
|
|
+ */
|
|
+ gpointer app_data ;
|
|
+
|
|
+ glong ref_count ;
|
|
+
|
|
+ /**
|
|
+ *A pointer to the next term,
|
|
+ *just in case this term is part of
|
|
+ *an expression.
|
|
+ */
|
|
+ CRTerm *next ;
|
|
+
|
|
+ /**
|
|
+ *A pointer to the previous
|
|
+ *term.
|
|
+ */
|
|
+ CRTerm *prev ;
|
|
+ CRParsingLocation location ;
|
|
+} ;
|
|
+
|
|
+CRTerm * cr_term_parse_expression_from_buf (const guchar *a_buf,
|
|
+ enum CREncoding a_encoding) ;
|
|
+CRTerm * cr_term_new (void) ;
|
|
+
|
|
+enum CRStatus cr_term_set_number (CRTerm *a_this, CRNum *a_num) ;
|
|
+
|
|
+enum CRStatus cr_term_set_function (CRTerm *a_this,
|
|
+ CRString *a_func_name,
|
|
+ CRTerm *a_func_param) ;
|
|
+
|
|
+enum CRStatus cr_term_set_string (CRTerm *a_this, CRString *a_str) ;
|
|
+
|
|
+enum CRStatus cr_term_set_ident (CRTerm *a_this, CRString *a_str) ;
|
|
+
|
|
+enum CRStatus cr_term_set_uri (CRTerm *a_this, CRString *a_str) ;
|
|
+
|
|
+enum CRStatus cr_term_set_rgb (CRTerm *a_this, CRRgb *a_rgb) ;
|
|
+
|
|
+enum CRStatus cr_term_set_hash (CRTerm *a_this, CRString *a_str) ;
|
|
+
|
|
+CRTerm * cr_term_append_term (CRTerm *a_this, CRTerm *a_new_term) ;
|
|
+
|
|
+CRTerm * cr_term_prepend_term (CRTerm *a_this, CRTerm *a_new_term) ;
|
|
+
|
|
+guchar * cr_term_to_string (CRTerm const *a_this) ;
|
|
+
|
|
+guchar * cr_term_one_to_string (CRTerm const * a_this) ;
|
|
+
|
|
+void cr_term_dump (CRTerm const *a_this, FILE *a_fp) ;
|
|
+
|
|
+int cr_term_nr_values (CRTerm const *a_this) ;
|
|
+
|
|
+CRTerm * cr_term_get_from_list (CRTerm *a_this, int itemnr) ;
|
|
+
|
|
+void cr_term_ref (CRTerm *a_this) ;
|
|
+
|
|
+gboolean cr_term_unref (CRTerm *a_this) ;
|
|
+
|
|
+void cr_term_destroy (CRTerm * a_term) ;
|
|
+
|
|
+G_END_DECLS
|
|
+
|
|
+#endif /*__CR_TERM_H__*/
|
|
diff --git a/src/st/croco/cr-tknzr.c b/src/st/croco/cr-tknzr.c
|
|
new file mode 100644
|
|
index 000000000..1548c35c6
|
|
--- /dev/null
|
|
+++ b/src/st/croco/cr-tknzr.c
|
|
@@ -0,0 +1,2762 @@
|
|
+/* -*- 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 the COPYRIGHTS file for copyrights information.
|
|
+ */
|
|
+
|
|
+/**
|
|
+ *@file
|
|
+ *The definition of the #CRTknzr (tokenizer)
|
|
+ *class.
|
|
+ */
|
|
+
|
|
+#include "string.h"
|
|
+#include "cr-tknzr.h"
|
|
+#include "cr-doc-handler.h"
|
|
+
|
|
+struct _CRTknzrPriv {
|
|
+ /**The parser input stream of bytes*/
|
|
+ CRInput *input;
|
|
+
|
|
+ /**
|
|
+ *A cache where tknzr_unget_token()
|
|
+ *puts back the token. tknzr_get_next_token()
|
|
+ *first look in this cache, and if and
|
|
+ *only if it's empty, fetches the next token
|
|
+ *from the input stream.
|
|
+ */
|
|
+ CRToken *token_cache;
|
|
+
|
|
+ /**
|
|
+ *The position of the end of the previous token
|
|
+ *or char fetched.
|
|
+ */
|
|
+ CRInputPos prev_pos;
|
|
+
|
|
+ CRDocHandler *sac_handler;
|
|
+
|
|
+ /**
|
|
+ *The reference count of the current instance
|
|
+ *of #CRTknzr. Is manipulated by cr_tknzr_ref()
|
|
+ *and cr_tknzr_unref().
|
|
+ */
|
|
+ glong ref_count;
|
|
+};
|
|
+
|
|
+#define PRIVATE(obj) ((obj)->priv)
|
|
+
|
|
+/**
|
|
+ *return TRUE if the character is a number ([0-9]), FALSE otherwise
|
|
+ *@param a_char the char to test.
|
|
+ */
|
|
+#define IS_NUM(a_char) (((a_char) >= '0' && (a_char) <= '9')?TRUE:FALSE)
|
|
+
|
|
+/**
|
|
+ *Checks if 'status' equals CR_OK. If not, goto the 'error' label.
|
|
+ *
|
|
+ *@param status the status (of type enum CRStatus) to test.
|
|
+ *@param is_exception if set to FALSE, the final status returned the
|
|
+ *current function will be CR_PARSING_ERROR. If set to TRUE, the
|
|
+ *current status will be the current value of the 'status' variable.
|
|
+ *
|
|
+ */
|
|
+#define CHECK_PARSING_STATUS(status, is_exception) \
|
|
+if ((status) != CR_OK) \
|
|
+{ \
|
|
+ if (is_exception == FALSE) \
|
|
+ { \
|
|
+ status = CR_PARSING_ERROR ; \
|
|
+ } \
|
|
+ goto error ; \
|
|
+}
|
|
+
|
|
+/**
|
|
+ *Peeks the next char from the input stream of the current tokenizer.
|
|
+ *invokes CHECK_PARSING_STATUS on the status returned by
|
|
+ *cr_tknzr_input_peek_char().
|
|
+ *
|
|
+ *@param the current instance of #CRTkzr.
|
|
+ *@param to_char a pointer to the char where to store the
|
|
+ *char peeked.
|
|
+ */
|
|
+#define PEEK_NEXT_CHAR(a_tknzr, a_to_char) \
|
|
+{\
|
|
+status = cr_tknzr_peek_char (a_tknzr, a_to_char) ; \
|
|
+CHECK_PARSING_STATUS (status, TRUE) \
|
|
+}
|
|
+
|
|
+/**
|
|
+ *Reads the next char from the input stream of the current parser.
|
|
+ *In case of error, jumps to the "error:" label located in the
|
|
+ *function where this macro is called.
|
|
+ *@param parser the curent instance of #CRTknzr
|
|
+ *@param to_char a pointer to the guint32 char where to store
|
|
+ *the character read.
|
|
+ */
|
|
+#define READ_NEXT_CHAR(a_tknzr, to_char) \
|
|
+status = cr_tknzr_read_char (a_tknzr, to_char) ;\
|
|
+CHECK_PARSING_STATUS (status, TRUE)
|
|
+
|
|
+/**
|
|
+ *Gets information about the current position in
|
|
+ *the input of the parser.
|
|
+ *In case of failure, this macro returns from the
|
|
+ *calling function and
|
|
+ *returns a status code of type enum #CRStatus.
|
|
+ *@param parser the current instance of #CRTknzr.
|
|
+ *@param pos out parameter. A pointer to the position
|
|
+ *inside the current parser input. Must
|
|
+ */
|
|
+#define RECORD_INITIAL_POS(a_tknzr, a_pos) \
|
|
+status = cr_input_get_cur_pos (PRIVATE \
|
|
+(a_tknzr)->input, a_pos) ; \
|
|
+g_return_val_if_fail (status == CR_OK, status)
|
|
+
|
|
+/**
|
|
+ *Gets the address of the current byte inside the
|
|
+ *parser input.
|
|
+ *@param parser the current instance of #CRTknzr.
|
|
+ *@param addr out parameter a pointer (guchar*)
|
|
+ *to where the address must be put.
|
|
+ */
|
|
+#define RECORD_CUR_BYTE_ADDR(a_tknzr, a_addr) \
|
|
+status = cr_input_get_cur_byte_addr \
|
|
+ (PRIVATE (a_tknzr)->input, a_addr) ; \
|
|
+CHECK_PARSING_STATUS (status, TRUE)
|
|
+
|
|
+/**
|
|
+ *Peeks a byte from the topmost parser input at
|
|
+ *a given offset from the current position.
|
|
+ *If it fails, goto the "error:" label.
|
|
+ *
|
|
+ *@param a_parser the current instance of #CRTknzr.
|
|
+ *@param a_offset the offset of the byte to peek, the
|
|
+ *current byte having the offset '0'.
|
|
+ *@param a_byte_ptr out parameter a pointer (guchar*) to
|
|
+ *where the peeked char is to be stored.
|
|
+ */
|
|
+#define PEEK_BYTE(a_tknzr, a_offset, a_byte_ptr) \
|
|
+status = cr_tknzr_peek_byte (a_tknzr, \
|
|
+ a_offset, \
|
|
+ a_byte_ptr) ; \
|
|
+CHECK_PARSING_STATUS (status, TRUE) ;
|
|
+
|
|
+#define BYTE(a_input, a_n, a_eof) \
|
|
+cr_input_peek_byte2 (a_input, a_n, a_eof)
|
|
+
|
|
+/**
|
|
+ *Reads a byte from the topmost parser input
|
|
+ *steam.
|
|
+ *If it fails, goto the "error" label.
|
|
+ *@param a_parser the current instance of #CRTknzr.
|
|
+ *@param a_byte_ptr the guchar * where to put the read char.
|
|
+ */
|
|
+#define READ_NEXT_BYTE(a_tknzr, a_byte_ptr) \
|
|
+status = \
|
|
+cr_input_read_byte (PRIVATE (a_tknzr)->input, a_byte_ptr) ;\
|
|
+CHECK_PARSING_STATUS (status, TRUE) ;
|
|
+
|
|
+/**
|
|
+ *Skips a given number of byte in the topmost
|
|
+ *parser input. Don't update line and column number.
|
|
+ *In case of error, jumps to the "error:" label
|
|
+ *of the surrounding function.
|
|
+ *@param a_parser the current instance of #CRTknzr.
|
|
+ *@param a_nb_bytes the number of bytes to skip.
|
|
+ */
|
|
+#define SKIP_BYTES(a_tknzr, a_nb_bytes) \
|
|
+status = cr_input_seek_index (PRIVATE (a_tknzr)->input, \
|
|
+ CR_SEEK_CUR, a_nb_bytes) ; \
|
|
+CHECK_PARSING_STATUS (status, TRUE) ;
|
|
+
|
|
+/**
|
|
+ *Skip utf8 encoded characters.
|
|
+ *Updates line and column numbers.
|
|
+ *@param a_parser the current instance of #CRTknzr.
|
|
+ *@param a_nb_chars the number of chars to skip. Must be of
|
|
+ *type glong.
|
|
+ */
|
|
+#define SKIP_CHARS(a_tknzr, a_nb_chars) \
|
|
+{ \
|
|
+gulong nb_chars = a_nb_chars ; \
|
|
+status = cr_input_consume_chars \
|
|
+ (PRIVATE (a_tknzr)->input,0, &nb_chars) ; \
|
|
+CHECK_PARSING_STATUS (status, TRUE) ; \
|
|
+}
|
|
+
|
|
+/**
|
|
+ *Tests the condition and if it is false, sets
|
|
+ *status to "CR_PARSING_ERROR" and goto the 'error'
|
|
+ *label.
|
|
+ *@param condition the condition to test.
|
|
+ */
|
|
+#define ENSURE_PARSING_COND(condition) \
|
|
+if (! (condition)) {status = CR_PARSING_ERROR; goto error ;}
|
|
+
|
|
+static enum CRStatus cr_tknzr_parse_nl (CRTknzr * a_this,
|
|
+ guchar ** a_start,
|
|
+ guchar ** a_end,
|
|
+ CRParsingLocation *a_location);
|
|
+
|
|
+static enum CRStatus cr_tknzr_parse_w (CRTknzr * a_this,
|
|
+ guchar ** a_start,
|
|
+ guchar ** a_end,
|
|
+ CRParsingLocation *a_location) ;
|
|
+
|
|
+static enum CRStatus cr_tknzr_parse_unicode_escape (CRTknzr * a_this,
|
|
+ guint32 * a_unicode,
|
|
+ CRParsingLocation *a_location) ;
|
|
+
|
|
+static enum CRStatus cr_tknzr_parse_escape (CRTknzr * a_this,
|
|
+ guint32 * a_esc_code,
|
|
+ CRParsingLocation *a_location);
|
|
+
|
|
+static enum CRStatus cr_tknzr_parse_string (CRTknzr * a_this,
|
|
+ CRString ** a_str);
|
|
+
|
|
+static enum CRStatus cr_tknzr_parse_comment (CRTknzr * a_this,
|
|
+ CRString ** a_comment);
|
|
+
|
|
+static enum CRStatus cr_tknzr_parse_nmstart (CRTknzr * a_this,
|
|
+ guint32 * a_char,
|
|
+ CRParsingLocation *a_location);
|
|
+
|
|
+static enum CRStatus cr_tknzr_parse_num (CRTknzr * a_this,
|
|
+ CRNum ** a_num);
|
|
+
|
|
+/**********************************
|
|
+ *PRIVATE methods
|
|
+ **********************************/
|
|
+
|
|
+/**
|
|
+ *Parses a "w" as defined by the css spec at [4.1.1]:
|
|
+ * w ::= [ \t\r\n\f]*
|
|
+ *
|
|
+ *@param a_this the current instance of #CRTknzr.
|
|
+ *@param a_start out param. Upon successfull completion, points
|
|
+ *to the beginning of the parsed white space, points to NULL otherwise.
|
|
+ *Can also point to NULL is there is no white space actually.
|
|
+ *@param a_end out param. Upon successfull completion, points
|
|
+ *to the end of the parsed white space, points to NULL otherwise.
|
|
+ *Can also point to NULL is there is no white space actually.
|
|
+ */
|
|
+static enum CRStatus
|
|
+cr_tknzr_parse_w (CRTknzr * a_this,
|
|
+ guchar ** a_start,
|
|
+ guchar ** a_end,
|
|
+ CRParsingLocation *a_location)
|
|
+{
|
|
+ guint32 cur_char = 0;
|
|
+ CRInputPos init_pos;
|
|
+ enum CRStatus status = CR_OK;
|
|
+
|
|
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
|
|
+ && PRIVATE (a_this)->input
|
|
+ && a_start && a_end,
|
|
+ CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ RECORD_INITIAL_POS (a_this, &init_pos);
|
|
+
|
|
+ *a_start = NULL;
|
|
+ *a_end = NULL;
|
|
+
|
|
+ READ_NEXT_CHAR (a_this, &cur_char);
|
|
+
|
|
+ if (cr_utils_is_white_space (cur_char) == FALSE) {
|
|
+ status = CR_PARSING_ERROR;
|
|
+ goto error;
|
|
+ }
|
|
+ if (a_location) {
|
|
+ cr_tknzr_get_parsing_location (a_this,
|
|
+ a_location) ;
|
|
+ }
|
|
+ RECORD_CUR_BYTE_ADDR (a_this, a_start);
|
|
+ *a_end = *a_start;
|
|
+
|
|
+ for (;;) {
|
|
+ gboolean is_eof = FALSE;
|
|
+
|
|
+ cr_input_get_end_of_file (PRIVATE (a_this)->input, &is_eof);
|
|
+ if (is_eof)
|
|
+ break;
|
|
+
|
|
+ status = cr_tknzr_peek_char (a_this, &cur_char);
|
|
+ if (status == CR_END_OF_INPUT_ERROR) {
|
|
+ break;
|
|
+ } else if (status != CR_OK) {
|
|
+ goto error;
|
|
+ }
|
|
+
|
|
+ if (cr_utils_is_white_space (cur_char) == TRUE) {
|
|
+ READ_NEXT_CHAR (a_this, &cur_char);
|
|
+ RECORD_CUR_BYTE_ADDR (a_this, a_end);
|
|
+ } else {
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return CR_OK;
|
|
+
|
|
+ error:
|
|
+ cr_tknzr_set_cur_pos (a_this, &init_pos);
|
|
+
|
|
+ return status;
|
|
+}
|
|
+
|
|
+/**
|
|
+ *Parses a newline as defined in the css2 spec:
|
|
+ * nl ::= \n|\r\n|\r|\f
|
|
+ *
|
|
+ *@param a_this the "this pointer" of the current instance of #CRTknzr.
|
|
+ *@param a_start a pointer to the first character of the successfully
|
|
+ *parsed string.
|
|
+ *@param a_end a pointer to the last character of the successfully parsed
|
|
+ *string.
|
|
+ *@result CR_OK uppon successfull completion, an error code otherwise.
|
|
+ */
|
|
+static enum CRStatus
|
|
+cr_tknzr_parse_nl (CRTknzr * a_this,
|
|
+ guchar ** a_start,
|
|
+ guchar ** a_end,
|
|
+ CRParsingLocation *a_location)
|
|
+{
|
|
+ CRInputPos init_pos;
|
|
+ guchar next_chars[2] = { 0 };
|
|
+ enum CRStatus status = CR_PARSING_ERROR;
|
|
+
|
|
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
|
|
+ && a_start && a_end, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ RECORD_INITIAL_POS (a_this, &init_pos);
|
|
+
|
|
+ PEEK_BYTE (a_this, 1, &next_chars[0]);
|
|
+ PEEK_BYTE (a_this, 2, &next_chars[1]);
|
|
+
|
|
+ if ((next_chars[0] == '\r' && next_chars[1] == '\n')) {
|
|
+ SKIP_BYTES (a_this, 1);
|
|
+ if (a_location) {
|
|
+ cr_tknzr_get_parsing_location
|
|
+ (a_this, a_location) ;
|
|
+ }
|
|
+ SKIP_CHARS (a_this, 1);
|
|
+
|
|
+ RECORD_CUR_BYTE_ADDR (a_this, a_end);
|
|
+
|
|
+ status = CR_OK;
|
|
+ } else if (next_chars[0] == '\n'
|
|
+ || next_chars[0] == '\r' || next_chars[0] == '\f') {
|
|
+ SKIP_CHARS (a_this, 1);
|
|
+ if (a_location) {
|
|
+ cr_tknzr_get_parsing_location
|
|
+ (a_this, a_location) ;
|
|
+ }
|
|
+ RECORD_CUR_BYTE_ADDR (a_this, a_start);
|
|
+ *a_end = *a_start;
|
|
+ status = CR_OK;
|
|
+ } else {
|
|
+ status = CR_PARSING_ERROR;
|
|
+ goto error;
|
|
+ }
|
|
+ return CR_OK ;
|
|
+
|
|
+ error:
|
|
+ cr_tknzr_set_cur_pos (a_this, &init_pos) ;
|
|
+ return status;
|
|
+}
|
|
+
|
|
+/**
|
|
+ *Go ahead in the parser input, skipping all the spaces.
|
|
+ *If the next char if not a white space, this function does nothing.
|
|
+ *In any cases, it stops when it encounters a non white space character.
|
|
+ *
|
|
+ *@param a_this the current instance of #CRTknzr.
|
|
+ *@return CR_OK upon successfull completion, an error code otherwise.
|
|
+ */
|
|
+static enum CRStatus
|
|
+cr_tknzr_try_to_skip_spaces (CRTknzr * a_this)
|
|
+{
|
|
+ enum CRStatus status = CR_ERROR;
|
|
+ guint32 cur_char = 0;
|
|
+
|
|
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
|
|
+ && PRIVATE (a_this)->input, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ status = cr_input_peek_char (PRIVATE (a_this)->input, &cur_char);
|
|
+
|
|
+ if (status != CR_OK) {
|
|
+ if (status == CR_END_OF_INPUT_ERROR)
|
|
+ return CR_OK;
|
|
+ return status;
|
|
+ }
|
|
+
|
|
+ if (cr_utils_is_white_space (cur_char) == TRUE) {
|
|
+ gulong nb_chars = -1; /*consume all spaces */
|
|
+
|
|
+ status = cr_input_consume_white_spaces
|
|
+ (PRIVATE (a_this)->input, &nb_chars);
|
|
+ }
|
|
+
|
|
+ return status;
|
|
+}
|
|
+
|
|
+/**
|
|
+ *Parses a "comment" as defined in the css spec at [4.1.1]:
|
|
+ *COMMENT ::= \/\*[^*]*\*+([^/][^*]*\*+)*\/ .
|
|
+ *This complex regexp is just to say that comments start
|
|
+ *with the two chars '/''*' and ends with the two chars '*''/'.
|
|
+ *It also means that comments cannot be nested.
|
|
+ *So based on that, I've just tried to implement the parsing function
|
|
+ *simply and in a straight forward manner.
|
|
+ */
|
|
+static enum CRStatus
|
|
+cr_tknzr_parse_comment (CRTknzr * a_this,
|
|
+ CRString ** a_comment)
|
|
+{
|
|
+ enum CRStatus status = CR_OK;
|
|
+ CRInputPos init_pos;
|
|
+ guint32 cur_char = 0, next_char= 0;
|
|
+ CRString *comment = NULL;
|
|
+ CRParsingLocation loc = {0} ;
|
|
+
|
|
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
|
|
+ && PRIVATE (a_this)->input,
|
|
+ CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ RECORD_INITIAL_POS (a_this, &init_pos);
|
|
+ READ_NEXT_CHAR (a_this, &cur_char) ;
|
|
+ ENSURE_PARSING_COND (cur_char == '/');
|
|
+ cr_tknzr_get_parsing_location (a_this, &loc) ;
|
|
+
|
|
+ READ_NEXT_CHAR (a_this, &cur_char);
|
|
+ ENSURE_PARSING_COND (cur_char == '*');
|
|
+ comment = cr_string_new ();
|
|
+ for (;;) { /* [^*]* */
|
|
+ PEEK_NEXT_CHAR (a_this, &next_char);
|
|
+ if (next_char == '*')
|
|
+ break;
|
|
+ READ_NEXT_CHAR (a_this, &cur_char);
|
|
+ g_string_append_unichar (comment->stryng, cur_char);
|
|
+ }
|
|
+ /* Stop condition: next_char == '*' */
|
|
+ for (;;) { /* \*+ */
|
|
+ READ_NEXT_CHAR(a_this, &cur_char);
|
|
+ ENSURE_PARSING_COND (cur_char == '*');
|
|
+ g_string_append_unichar (comment->stryng, cur_char);
|
|
+ PEEK_NEXT_CHAR (a_this, &next_char);
|
|
+ if (next_char != '*')
|
|
+ break;
|
|
+ }
|
|
+ /* Stop condition: next_char != '*' */
|
|
+ for (;;) { /* ([^/][^*]*\*+)* */
|
|
+ if (next_char == '/')
|
|
+ break;
|
|
+ READ_NEXT_CHAR(a_this, &cur_char);
|
|
+ g_string_append_unichar (comment->stryng, cur_char);
|
|
+ for (;;) { /* [^*]* */
|
|
+ PEEK_NEXT_CHAR (a_this, &next_char);
|
|
+ if (next_char == '*')
|
|
+ break;
|
|
+ READ_NEXT_CHAR (a_this, &cur_char);
|
|
+ g_string_append_unichar (comment->stryng, cur_char);
|
|
+ }
|
|
+ /* Stop condition: next_char = '*', no need to verify, because peek and read exit to error anyway */
|
|
+ for (;;) { /* \*+ */
|
|
+ READ_NEXT_CHAR(a_this, &cur_char);
|
|
+ ENSURE_PARSING_COND (cur_char == '*');
|
|
+ g_string_append_unichar (comment->stryng, cur_char);
|
|
+ PEEK_NEXT_CHAR (a_this, &next_char);
|
|
+ if (next_char != '*')
|
|
+ break;
|
|
+ }
|
|
+ /* Continue condition: next_char != '*' */
|
|
+ }
|
|
+ /* Stop condition: next_char == '\/' */
|
|
+ READ_NEXT_CHAR(a_this, &cur_char);
|
|
+ g_string_append_unichar (comment->stryng, cur_char);
|
|
+
|
|
+ if (status == CR_OK) {
|
|
+ cr_parsing_location_copy (&comment->location,
|
|
+ &loc) ;
|
|
+ *a_comment = comment;
|
|
+ return CR_OK;
|
|
+ }
|
|
+ error:
|
|
+
|
|
+ if (comment) {
|
|
+ cr_string_destroy (comment);
|
|
+ comment = NULL;
|
|
+ }
|
|
+
|
|
+ cr_tknzr_set_cur_pos (a_this, &init_pos);
|
|
+
|
|
+ return status;
|
|
+}
|
|
+
|
|
+/**
|
|
+ *Parses an 'unicode' escape sequence defined
|
|
+ *in css spec at chap 4.1.1:
|
|
+ *unicode ::= \\[0-9a-f]{1,6}[ \n\r\t\f]?
|
|
+ *@param a_this the current instance of #CRTknzr.
|
|
+ *@param a_start out parameter. A pointer to the start
|
|
+ *of the unicode escape sequence. Must *NOT* be deleted by
|
|
+ *the caller.
|
|
+ *@param a_end out parameter. A pointer to the last character
|
|
+ *of the unicode escape sequence. Must *NOT* be deleted by the caller.
|
|
+ *@return CR_OK if parsing succeded, an error code otherwise.
|
|
+ *Error code can be either CR_PARSING_ERROR if the string
|
|
+ *parsed just doesn't
|
|
+ *respect the production or another error if a
|
|
+ *lower level error occurred.
|
|
+ */
|
|
+static enum CRStatus
|
|
+cr_tknzr_parse_unicode_escape (CRTknzr * a_this,
|
|
+ guint32 * a_unicode,
|
|
+ CRParsingLocation *a_location)
|
|
+{
|
|
+ guint32 cur_char;
|
|
+ CRInputPos init_pos;
|
|
+ glong occur = 0;
|
|
+ guint32 unicode = 0;
|
|
+ guchar *tmp_char_ptr1 = NULL,
|
|
+ *tmp_char_ptr2 = NULL;
|
|
+ enum CRStatus status = CR_OK;
|
|
+
|
|
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
|
|
+ && a_unicode, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ /*first, let's backup the current position pointer */
|
|
+ RECORD_INITIAL_POS (a_this, &init_pos);
|
|
+
|
|
+ READ_NEXT_CHAR (a_this, &cur_char);
|
|
+
|
|
+ if (cur_char != '\\') {
|
|
+ status = CR_PARSING_ERROR;
|
|
+ goto error;
|
|
+ }
|
|
+ if (a_location) {
|
|
+ cr_tknzr_get_parsing_location
|
|
+ (a_this, a_location) ;
|
|
+ }
|
|
+ PEEK_NEXT_CHAR (a_this, &cur_char);
|
|
+
|
|
+ for (occur = 0, unicode = 0; ((cur_char >= '0' && cur_char <= '9')
|
|
+ || (cur_char >= 'a' && cur_char <= 'f')
|
|
+ || (cur_char >= 'A' && cur_char <= 'F'))
|
|
+ && occur < 6; occur++) {
|
|
+ gint cur_char_val = 0;
|
|
+
|
|
+ READ_NEXT_CHAR (a_this, &cur_char);
|
|
+
|
|
+ if ((cur_char >= '0' && cur_char <= '9')) {
|
|
+ cur_char_val = (cur_char - '0');
|
|
+ } else if ((cur_char >= 'a' && cur_char <= 'f')) {
|
|
+ cur_char_val = 10 + (cur_char - 'a');
|
|
+ } else if ((cur_char >= 'A' && cur_char <= 'F')) {
|
|
+ cur_char_val = 10 + (cur_char - 'A');
|
|
+ }
|
|
+
|
|
+ unicode = unicode * 16 + cur_char_val;
|
|
+
|
|
+ PEEK_NEXT_CHAR (a_this, &cur_char);
|
|
+ }
|
|
+
|
|
+ /* Eat a whitespace if possible. */
|
|
+ cr_tknzr_parse_w (a_this, &tmp_char_ptr1,
|
|
+ &tmp_char_ptr2, NULL);
|
|
+ *a_unicode = unicode;
|
|
+ return CR_OK;
|
|
+
|
|
+ error:
|
|
+ /*
|
|
+ *restore the initial position pointer backuped at
|
|
+ *the beginning of this function.
|
|
+ */
|
|
+ cr_tknzr_set_cur_pos (a_this, &init_pos);
|
|
+
|
|
+ return status;
|
|
+}
|
|
+
|
|
+/**
|
|
+ *parses an escape sequence as defined by the css spec:
|
|
+ *escape ::= {unicode}|\\[ -~\200-\4177777]
|
|
+ *@param a_this the current instance of #CRTknzr .
|
|
+ */
|
|
+static enum CRStatus
|
|
+cr_tknzr_parse_escape (CRTknzr * a_this, guint32 * a_esc_code,
|
|
+ CRParsingLocation *a_location)
|
|
+{
|
|
+ enum CRStatus status = CR_OK;
|
|
+ guint32 cur_char = 0;
|
|
+ CRInputPos init_pos;
|
|
+ guchar next_chars[2];
|
|
+
|
|
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
|
|
+ && a_esc_code, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ RECORD_INITIAL_POS (a_this, &init_pos);
|
|
+
|
|
+ PEEK_BYTE (a_this, 1, &next_chars[0]);
|
|
+ PEEK_BYTE (a_this, 2, &next_chars[1]);
|
|
+
|
|
+ if (next_chars[0] != '\\') {
|
|
+ status = CR_PARSING_ERROR;
|
|
+ goto error;
|
|
+ }
|
|
+
|
|
+ if ((next_chars[1] >= '0' && next_chars[1] <= '9')
|
|
+ || (next_chars[1] >= 'a' && next_chars[1] <= 'f')
|
|
+ || (next_chars[1] >= 'A' && next_chars[1] <= 'F')) {
|
|
+ status = cr_tknzr_parse_unicode_escape (a_this, a_esc_code,
|
|
+ a_location);
|
|
+ } else {
|
|
+ /*consume the '\' char */
|
|
+ READ_NEXT_CHAR (a_this, &cur_char);
|
|
+ if (a_location) {
|
|
+ cr_tknzr_get_parsing_location (a_this,
|
|
+ a_location) ;
|
|
+ }
|
|
+ /*then read the char after the '\' */
|
|
+ READ_NEXT_CHAR (a_this, &cur_char);
|
|
+
|
|
+ if (cur_char != ' ' && (cur_char < 200 || cur_char > 4177777)) {
|
|
+ status = CR_PARSING_ERROR;
|
|
+ goto error;
|
|
+ }
|
|
+ *a_esc_code = cur_char;
|
|
+
|
|
+ }
|
|
+ if (status == CR_OK) {
|
|
+ return CR_OK;
|
|
+ }
|
|
+ error:
|
|
+ cr_tknzr_set_cur_pos (a_this, &init_pos);
|
|
+ return status;
|
|
+}
|
|
+
|
|
+/**
|
|
+ *Parses a string type as defined in css spec [4.1.1]:
|
|
+ *
|
|
+ *string ::= {string1}|{string2}
|
|
+ *string1 ::= \"([\t !#$%&(-~]|\\{nl}|\'|{nonascii}|{escape})*\"
|
|
+ *string2 ::= \'([\t !#$%&(-~]|\\{nl}|\"|{nonascii}|{escape})*\'
|
|
+ *
|
|
+ *@param a_this the current instance of #CRTknzr.
|
|
+ *@param a_start out parameter. Upon successfull completion,
|
|
+ *points to the beginning of the string, points to an undefined value
|
|
+ *otherwise.
|
|
+ *@param a_end out parameter. Upon successfull completion, points to
|
|
+ *the beginning of the string, points to an undefined value otherwise.
|
|
+ *@return CR_OK upon successfull completion, an error code otherwise.
|
|
+ */
|
|
+static enum CRStatus
|
|
+cr_tknzr_parse_string (CRTknzr * a_this, CRString ** a_str)
|
|
+{
|
|
+ guint32 cur_char = 0,
|
|
+ delim = 0;
|
|
+ CRInputPos init_pos;
|
|
+ enum CRStatus status = CR_OK;
|
|
+ CRString *str = NULL;
|
|
+
|
|
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
|
|
+ && PRIVATE (a_this)->input
|
|
+ && a_str, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ RECORD_INITIAL_POS (a_this, &init_pos);
|
|
+ READ_NEXT_CHAR (a_this, &cur_char);
|
|
+
|
|
+ if (cur_char == '"')
|
|
+ delim = '"';
|
|
+ else if (cur_char == '\'')
|
|
+ delim = '\'';
|
|
+ else {
|
|
+ status = CR_PARSING_ERROR;
|
|
+ goto error;
|
|
+ }
|
|
+ str = cr_string_new ();
|
|
+ if (str) {
|
|
+ cr_tknzr_get_parsing_location
|
|
+ (a_this, &str->location) ;
|
|
+ }
|
|
+ for (;;) {
|
|
+ guchar next_chars[2] = { 0 };
|
|
+
|
|
+ PEEK_BYTE (a_this, 1, &next_chars[0]);
|
|
+ PEEK_BYTE (a_this, 2, &next_chars[1]);
|
|
+
|
|
+ if (next_chars[0] == '\\') {
|
|
+ guchar *tmp_char_ptr1 = NULL,
|
|
+ *tmp_char_ptr2 = NULL;
|
|
+ guint32 esc_code = 0;
|
|
+
|
|
+ if (next_chars[1] == '\'' || next_chars[1] == '"') {
|
|
+ g_string_append_unichar (str->stryng,
|
|
+ next_chars[1]);
|
|
+ SKIP_BYTES (a_this, 2);
|
|
+ status = CR_OK;
|
|
+ } else {
|
|
+ status = cr_tknzr_parse_escape
|
|
+ (a_this, &esc_code, NULL);
|
|
+
|
|
+ if (status == CR_OK) {
|
|
+ g_string_append_unichar
|
|
+ (str->stryng,
|
|
+ esc_code);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (status != CR_OK) {
|
|
+ /*
|
|
+ *consume the '\' char, and try to parse
|
|
+ *a newline.
|
|
+ */
|
|
+ READ_NEXT_CHAR (a_this, &cur_char);
|
|
+
|
|
+ status = cr_tknzr_parse_nl
|
|
+ (a_this, &tmp_char_ptr1,
|
|
+ &tmp_char_ptr2, NULL);
|
|
+ }
|
|
+
|
|
+ CHECK_PARSING_STATUS (status, FALSE);
|
|
+ } else if (strchr ("\t !#$%&", next_chars[0])
|
|
+ || (next_chars[0] >= '(' && next_chars[0] <= '~')) {
|
|
+ READ_NEXT_CHAR (a_this, &cur_char);
|
|
+ g_string_append_unichar (str->stryng,
|
|
+ cur_char);
|
|
+ status = CR_OK;
|
|
+ }
|
|
+
|
|
+ else if (cr_utils_is_nonascii (next_chars[0])) {
|
|
+ READ_NEXT_CHAR (a_this, &cur_char);
|
|
+ g_string_append_unichar (str->stryng, cur_char);
|
|
+ } else if (next_chars[0] == delim) {
|
|
+ READ_NEXT_CHAR (a_this, &cur_char);
|
|
+ break;
|
|
+ } else {
|
|
+ status = CR_PARSING_ERROR;
|
|
+ goto error;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (status == CR_OK) {
|
|
+ if (*a_str == NULL) {
|
|
+ *a_str = str;
|
|
+ str = NULL;
|
|
+ } else {
|
|
+ (*a_str)->stryng = g_string_append_len
|
|
+ ((*a_str)->stryng,
|
|
+ str->stryng->str,
|
|
+ str->stryng->len);
|
|
+ cr_string_destroy (str);
|
|
+ }
|
|
+ return CR_OK;
|
|
+ }
|
|
+
|
|
+ error:
|
|
+
|
|
+ if (str) {
|
|
+ cr_string_destroy (str) ;
|
|
+ str = NULL;
|
|
+ }
|
|
+ cr_tknzr_set_cur_pos (a_this, &init_pos);
|
|
+ return status;
|
|
+}
|
|
+
|
|
+/**
|
|
+ *Parses the an nmstart as defined by the css2 spec [4.1.1]:
|
|
+ * nmstart [a-zA-Z]|{nonascii}|{escape}
|
|
+ *
|
|
+ *@param a_this the current instance of #CRTknzr.
|
|
+ *@param a_start out param. A pointer to the starting point of
|
|
+ *the token.
|
|
+ *@param a_end out param. A pointer to the ending point of the
|
|
+ *token.
|
|
+ *@param a_char out param. The actual parsed nmchar.
|
|
+ *@return CR_OK upon successfull completion,
|
|
+ *an error code otherwise.
|
|
+ */
|
|
+static enum CRStatus
|
|
+cr_tknzr_parse_nmstart (CRTknzr * a_this,
|
|
+ guint32 * a_char,
|
|
+ CRParsingLocation *a_location)
|
|
+{
|
|
+ CRInputPos init_pos;
|
|
+ enum CRStatus status = CR_OK;
|
|
+ guint32 cur_char = 0,
|
|
+ next_char = 0;
|
|
+
|
|
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
|
|
+ && PRIVATE (a_this)->input
|
|
+ && a_char, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ RECORD_INITIAL_POS (a_this, &init_pos);
|
|
+
|
|
+ PEEK_NEXT_CHAR (a_this, &next_char);
|
|
+
|
|
+ if (next_char == '\\') {
|
|
+ status = cr_tknzr_parse_escape (a_this, a_char,
|
|
+ a_location);
|
|
+
|
|
+ if (status != CR_OK)
|
|
+ goto error;
|
|
+
|
|
+ } else if (cr_utils_is_nonascii (next_char) == TRUE
|
|
+ || ((next_char >= 'a') && (next_char <= 'z'))
|
|
+ || ((next_char >= 'A') && (next_char <= 'Z'))
|
|
+ ) {
|
|
+ READ_NEXT_CHAR (a_this, &cur_char);
|
|
+ if (a_location) {
|
|
+ cr_tknzr_get_parsing_location (a_this,
|
|
+ a_location) ;
|
|
+ }
|
|
+ *a_char = cur_char;
|
|
+ status = CR_OK;
|
|
+ } else {
|
|
+ status = CR_PARSING_ERROR;
|
|
+ goto error;
|
|
+ }
|
|
+
|
|
+ return CR_OK;
|
|
+
|
|
+ error:
|
|
+ cr_tknzr_set_cur_pos (a_this, &init_pos);
|
|
+
|
|
+ return status;
|
|
+
|
|
+}
|
|
+
|
|
+/**
|
|
+ *Parses an nmchar as described in the css spec at
|
|
+ *chap 4.1.1:
|
|
+ *nmchar ::= [a-z0-9-]|{nonascii}|{escape}
|
|
+ *
|
|
+ *Humm, I have added the possibility for nmchar to
|
|
+ *contain upper case letters.
|
|
+ *
|
|
+ *@param a_this the current instance of #CRTknzr.
|
|
+ *@param a_start out param. A pointer to the starting point of
|
|
+ *the token.
|
|
+ *@param a_end out param. A pointer to the ending point of the
|
|
+ *token.
|
|
+ *@param a_char out param. The actual parsed nmchar.
|
|
+ *@return CR_OK upon successfull completion,
|
|
+ *an error code otherwise.
|
|
+ */
|
|
+static enum CRStatus
|
|
+cr_tknzr_parse_nmchar (CRTknzr * a_this, guint32 * a_char,
|
|
+ CRParsingLocation *a_location)
|
|
+{
|
|
+ guint32 cur_char = 0,
|
|
+ next_char = 0;
|
|
+ enum CRStatus status = CR_OK;
|
|
+ CRInputPos init_pos;
|
|
+
|
|
+ g_return_val_if_fail (a_this && PRIVATE (a_this) && a_char,
|
|
+ CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ RECORD_INITIAL_POS (a_this, &init_pos);
|
|
+
|
|
+ status = cr_input_peek_char (PRIVATE (a_this)->input,
|
|
+ &next_char) ;
|
|
+ if (status != CR_OK)
|
|
+ goto error;
|
|
+
|
|
+ if (next_char == '\\') {
|
|
+ status = cr_tknzr_parse_escape (a_this, a_char,
|
|
+ a_location);
|
|
+
|
|
+ if (status != CR_OK)
|
|
+ goto error;
|
|
+
|
|
+ } else if (cr_utils_is_nonascii (next_char) == TRUE
|
|
+ || ((next_char >= 'a') && (next_char <= 'z'))
|
|
+ || ((next_char >= 'A') && (next_char <= 'Z'))
|
|
+ || ((next_char >= '0') && (next_char <= '9'))
|
|
+ || (next_char == '-')
|
|
+ || (next_char == '_') /*'_' not allowed by the spec. */
|
|
+ ) {
|
|
+ READ_NEXT_CHAR (a_this, &cur_char);
|
|
+ *a_char = cur_char;
|
|
+ status = CR_OK;
|
|
+ if (a_location) {
|
|
+ cr_tknzr_get_parsing_location
|
|
+ (a_this, a_location) ;
|
|
+ }
|
|
+ } else {
|
|
+ status = CR_PARSING_ERROR;
|
|
+ goto error;
|
|
+ }
|
|
+ return CR_OK;
|
|
+
|
|
+ error:
|
|
+ cr_tknzr_set_cur_pos (a_this, &init_pos);
|
|
+ return status;
|
|
+}
|
|
+
|
|
+/**
|
|
+ *Parses an "ident" as defined in css spec [4.1.1]:
|
|
+ *ident ::= {nmstart}{nmchar}*
|
|
+ *
|
|
+ *Actually parses it using the css3 grammar:
|
|
+ *ident ::= -?{nmstart}{nmchar}*
|
|
+ *@param a_this the currens instance of #CRTknzr.
|
|
+ *
|
|
+ *@param a_str a pointer to parsed ident. If *a_str is NULL,
|
|
+ *this function allocates a new instance of CRString. If not,
|
|
+ *the function just appends the parsed string to the one passed.
|
|
+ *In both cases it is up to the caller to free *a_str.
|
|
+ *
|
|
+ *@return CR_OK upon successfull completion, an error code
|
|
+ *otherwise.
|
|
+ */
|
|
+static enum CRStatus
|
|
+cr_tknzr_parse_ident (CRTknzr * a_this, CRString ** a_str)
|
|
+{
|
|
+ guint32 tmp_char = 0;
|
|
+ CRString *stringue = NULL ;
|
|
+ CRInputPos init_pos;
|
|
+ enum CRStatus status = CR_OK;
|
|
+ gboolean location_is_set = FALSE ;
|
|
+
|
|
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
|
|
+ && PRIVATE (a_this)->input
|
|
+ && a_str, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ RECORD_INITIAL_POS (a_this, &init_pos);
|
|
+ PEEK_NEXT_CHAR (a_this, &tmp_char) ;
|
|
+ stringue = cr_string_new () ;
|
|
+ g_return_val_if_fail (stringue,
|
|
+ CR_OUT_OF_MEMORY_ERROR) ;
|
|
+
|
|
+ if (tmp_char == '-') {
|
|
+ READ_NEXT_CHAR (a_this, &tmp_char) ;
|
|
+ cr_tknzr_get_parsing_location
|
|
+ (a_this, &stringue->location) ;
|
|
+ location_is_set = TRUE ;
|
|
+ g_string_append_unichar (stringue->stryng,
|
|
+ tmp_char) ;
|
|
+ }
|
|
+ status = cr_tknzr_parse_nmstart (a_this, &tmp_char, NULL);
|
|
+ if (status != CR_OK) {
|
|
+ status = CR_PARSING_ERROR;
|
|
+ goto end ;
|
|
+ }
|
|
+ if (location_is_set == FALSE) {
|
|
+ cr_tknzr_get_parsing_location
|
|
+ (a_this, &stringue->location) ;
|
|
+ location_is_set = TRUE ;
|
|
+ }
|
|
+ g_string_append_unichar (stringue->stryng, tmp_char);
|
|
+ for (;;) {
|
|
+ status = cr_tknzr_parse_nmchar (a_this,
|
|
+ &tmp_char,
|
|
+ NULL);
|
|
+ if (status != CR_OK) {
|
|
+ status = CR_OK ;
|
|
+ break;
|
|
+ }
|
|
+ g_string_append_unichar (stringue->stryng, tmp_char);
|
|
+ }
|
|
+ if (status == CR_OK) {
|
|
+ if (!*a_str) {
|
|
+ *a_str = stringue ;
|
|
+
|
|
+ } else {
|
|
+ g_string_append_len ((*a_str)->stryng,
|
|
+ stringue->stryng->str,
|
|
+ stringue->stryng->len) ;
|
|
+ cr_string_destroy (stringue) ;
|
|
+ }
|
|
+ stringue = NULL ;
|
|
+ }
|
|
+
|
|
+ error:
|
|
+ end:
|
|
+ if (stringue) {
|
|
+ cr_string_destroy (stringue) ;
|
|
+ stringue = NULL ;
|
|
+ }
|
|
+ if (status != CR_OK ) {
|
|
+ cr_tknzr_set_cur_pos (a_this, &init_pos) ;
|
|
+ }
|
|
+ return status ;
|
|
+}
|
|
+
|
|
+
|
|
+/**
|
|
+ *Parses a "name" as defined by css spec [4.1.1]:
|
|
+ *name ::= {nmchar}+
|
|
+ *
|
|
+ *@param a_this the current instance of #CRTknzr.
|
|
+ *
|
|
+ *@param a_str out parameter. A pointer to the successfully parsed
|
|
+ *name. If *a_str is set to NULL, this function allocates a new instance
|
|
+ *of CRString. If not, it just appends the parsed name to the passed *a_str.
|
|
+ *In both cases, it is up to the caller to free *a_str.
|
|
+ *
|
|
+ *@return CR_OK upon successfull completion, an error code otherwise.
|
|
+ */
|
|
+static enum CRStatus
|
|
+cr_tknzr_parse_name (CRTknzr * a_this,
|
|
+ CRString ** a_str)
|
|
+{
|
|
+ guint32 tmp_char = 0;
|
|
+ CRInputPos init_pos;
|
|
+ enum CRStatus status = CR_OK;
|
|
+ gboolean str_needs_free = FALSE,
|
|
+ is_first_nmchar=TRUE ;
|
|
+ glong i = 0;
|
|
+ CRParsingLocation loc = {0} ;
|
|
+
|
|
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
|
|
+ && PRIVATE (a_this)->input
|
|
+ && a_str,
|
|
+ CR_BAD_PARAM_ERROR) ;
|
|
+
|
|
+ RECORD_INITIAL_POS (a_this, &init_pos);
|
|
+
|
|
+ if (*a_str == NULL) {
|
|
+ *a_str = cr_string_new ();
|
|
+ str_needs_free = TRUE;
|
|
+ }
|
|
+ for (i = 0;; i++) {
|
|
+ if (is_first_nmchar == TRUE) {
|
|
+ status = cr_tknzr_parse_nmchar
|
|
+ (a_this, &tmp_char,
|
|
+ &loc) ;
|
|
+ is_first_nmchar = FALSE ;
|
|
+ } else {
|
|
+ status = cr_tknzr_parse_nmchar
|
|
+ (a_this, &tmp_char, NULL) ;
|
|
+ }
|
|
+ if (status != CR_OK)
|
|
+ break;
|
|
+ g_string_append_unichar ((*a_str)->stryng,
|
|
+ tmp_char);
|
|
+ }
|
|
+ if (i > 0) {
|
|
+ cr_parsing_location_copy
|
|
+ (&(*a_str)->location, &loc) ;
|
|
+ return CR_OK;
|
|
+ }
|
|
+ if (str_needs_free == TRUE && *a_str) {
|
|
+ cr_string_destroy (*a_str);
|
|
+ *a_str = NULL;
|
|
+ }
|
|
+ cr_tknzr_set_cur_pos (a_this, &init_pos);
|
|
+ return CR_PARSING_ERROR;
|
|
+}
|
|
+
|
|
+/**
|
|
+ *Parses a "hash" as defined by the css spec in [4.1.1]:
|
|
+ *HASH ::= #{name}
|
|
+ */
|
|
+static enum CRStatus
|
|
+cr_tknzr_parse_hash (CRTknzr * a_this, CRString ** a_str)
|
|
+{
|
|
+ guint32 cur_char = 0;
|
|
+ CRInputPos init_pos;
|
|
+ enum CRStatus status = CR_OK;
|
|
+ gboolean str_needs_free = FALSE;
|
|
+ CRParsingLocation loc = {0} ;
|
|
+
|
|
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
|
|
+ && PRIVATE (a_this)->input,
|
|
+ CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ RECORD_INITIAL_POS (a_this, &init_pos);
|
|
+ READ_NEXT_CHAR (a_this, &cur_char);
|
|
+ if (cur_char != '#') {
|
|
+ status = CR_PARSING_ERROR;
|
|
+ goto error;
|
|
+ }
|
|
+ if (*a_str == NULL) {
|
|
+ *a_str = cr_string_new ();
|
|
+ str_needs_free = TRUE;
|
|
+ }
|
|
+ cr_tknzr_get_parsing_location (a_this,
|
|
+ &loc) ;
|
|
+ status = cr_tknzr_parse_name (a_this, a_str);
|
|
+ cr_parsing_location_copy (&(*a_str)->location, &loc) ;
|
|
+ if (status != CR_OK) {
|
|
+ goto error;
|
|
+ }
|
|
+ return CR_OK;
|
|
+
|
|
+ error:
|
|
+ if (str_needs_free == TRUE && *a_str) {
|
|
+ cr_string_destroy (*a_str);
|
|
+ *a_str = NULL;
|
|
+ }
|
|
+
|
|
+ cr_tknzr_set_cur_pos (a_this, &init_pos);
|
|
+ return status;
|
|
+}
|
|
+
|
|
+/**
|
|
+ *Parses an uri as defined by the css spec [4.1.1]:
|
|
+ * URI ::= url\({w}{string}{w}\)
|
|
+ * |url\({w}([!#$%&*-~]|{nonascii}|{escape})*{w}\)
|
|
+ *
|
|
+ *@param a_this the current instance of #CRTknzr.
|
|
+ *@param a_str the successfully parsed url.
|
|
+ *@return CR_OK upon successfull completion, an error code otherwise.
|
|
+ */
|
|
+static enum CRStatus
|
|
+cr_tknzr_parse_uri (CRTknzr * a_this,
|
|
+ CRString ** a_str)
|
|
+{
|
|
+ guint32 cur_char = 0;
|
|
+ CRInputPos init_pos;
|
|
+ enum CRStatus status = CR_PARSING_ERROR;
|
|
+ guchar tab[4] = { 0 }, *tmp_ptr1 = NULL, *tmp_ptr2 = NULL;
|
|
+ CRString *str = NULL;
|
|
+ CRParsingLocation location = {0} ;
|
|
+
|
|
+ g_return_val_if_fail (a_this
|
|
+ && PRIVATE (a_this)
|
|
+ && PRIVATE (a_this)->input
|
|
+ && a_str,
|
|
+ CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ RECORD_INITIAL_POS (a_this, &init_pos);
|
|
+
|
|
+ PEEK_BYTE (a_this, 1, &tab[0]);
|
|
+ PEEK_BYTE (a_this, 2, &tab[1]);
|
|
+ PEEK_BYTE (a_this, 3, &tab[2]);
|
|
+ PEEK_BYTE (a_this, 4, &tab[3]);
|
|
+
|
|
+ if (tab[0] != 'u' || tab[1] != 'r' || tab[2] != 'l' || tab[3] != '(') {
|
|
+ status = CR_PARSING_ERROR;
|
|
+ goto error;
|
|
+ }
|
|
+ /*
|
|
+ *Here, we want to skip 4 bytes ('u''r''l''(').
|
|
+ *But we also need to keep track of the parsing location
|
|
+ *of the 'u'. So, we skip 1 byte, we record the parsing
|
|
+ *location, then we skip the 3 remaining bytes.
|
|
+ */
|
|
+ SKIP_CHARS (a_this, 1);
|
|
+ cr_tknzr_get_parsing_location (a_this, &location) ;
|
|
+ SKIP_CHARS (a_this, 3);
|
|
+ cr_tknzr_try_to_skip_spaces (a_this);
|
|
+ status = cr_tknzr_parse_string (a_this, a_str);
|
|
+
|
|
+ if (status == CR_OK) {
|
|
+ guint32 next_char = 0;
|
|
+ status = cr_tknzr_parse_w (a_this, &tmp_ptr1,
|
|
+ &tmp_ptr2, NULL);
|
|
+ cr_tknzr_try_to_skip_spaces (a_this);
|
|
+ PEEK_NEXT_CHAR (a_this, &next_char);
|
|
+ if (next_char == ')') {
|
|
+ READ_NEXT_CHAR (a_this, &cur_char);
|
|
+ status = CR_OK;
|
|
+ } else {
|
|
+ status = CR_PARSING_ERROR;
|
|
+ }
|
|
+ }
|
|
+ if (status != CR_OK) {
|
|
+ str = cr_string_new ();
|
|
+ for (;;) {
|
|
+ guint32 next_char = 0;
|
|
+ PEEK_NEXT_CHAR (a_this, &next_char);
|
|
+ if (strchr ("!#$%&", next_char)
|
|
+ || (next_char >= '*' && next_char <= '~')
|
|
+ || (cr_utils_is_nonascii (next_char) == TRUE)) {
|
|
+ READ_NEXT_CHAR (a_this, &cur_char);
|
|
+ g_string_append_unichar
|
|
+ (str->stryng, cur_char);
|
|
+ status = CR_OK;
|
|
+ } else {
|
|
+ guint32 esc_code = 0;
|
|
+ status = cr_tknzr_parse_escape
|
|
+ (a_this, &esc_code, NULL);
|
|
+ if (status == CR_OK) {
|
|
+ g_string_append_unichar
|
|
+ (str->stryng,
|
|
+ esc_code);
|
|
+ } else {
|
|
+ status = CR_OK;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ cr_tknzr_try_to_skip_spaces (a_this);
|
|
+ READ_NEXT_CHAR (a_this, &cur_char);
|
|
+ if (cur_char == ')') {
|
|
+ status = CR_OK;
|
|
+ } else {
|
|
+ status = CR_PARSING_ERROR;
|
|
+ goto error;
|
|
+ }
|
|
+ if (str) {
|
|
+ if (*a_str == NULL) {
|
|
+ *a_str = str;
|
|
+ str = NULL;
|
|
+ } else {
|
|
+ g_string_append_len
|
|
+ ((*a_str)->stryng,
|
|
+ str->stryng->str,
|
|
+ str->stryng->len);
|
|
+ cr_string_destroy (str);
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ cr_parsing_location_copy
|
|
+ (&(*a_str)->location,
|
|
+ &location) ;
|
|
+ return CR_OK ;
|
|
+ error:
|
|
+ if (str) {
|
|
+ cr_string_destroy (str);
|
|
+ str = NULL;
|
|
+ }
|
|
+ cr_tknzr_set_cur_pos (a_this, &init_pos);
|
|
+ return status;
|
|
+}
|
|
+
|
|
+/**
|
|
+ *parses an RGB as defined in the css2 spec.
|
|
+ *rgb: rgb '('S*{num}%?S* ',' {num}#?S*,S*{num}#?S*')'
|
|
+ *
|
|
+ *@param a_this the "this pointer" of the current instance of
|
|
+ *@param a_rgb out parameter the parsed rgb.
|
|
+ *@return CR_OK upon successfull completion, an error code otherwise.
|
|
+ */
|
|
+static enum CRStatus
|
|
+cr_tknzr_parse_rgb (CRTknzr * a_this, CRRgb ** a_rgb)
|
|
+{
|
|
+ enum CRStatus status = CR_OK;
|
|
+ CRInputPos init_pos;
|
|
+ CRNum *num = NULL;
|
|
+ guchar next_bytes[3] = { 0 }, cur_byte = 0;
|
|
+ glong red = 0,
|
|
+ green = 0,
|
|
+ blue = 0,
|
|
+ i = 0;
|
|
+ gboolean is_percentage = FALSE;
|
|
+ CRParsingLocation location = {0} ;
|
|
+
|
|
+ g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ RECORD_INITIAL_POS (a_this, &init_pos);
|
|
+
|
|
+ PEEK_BYTE (a_this, 1, &next_bytes[0]);
|
|
+ PEEK_BYTE (a_this, 2, &next_bytes[1]);
|
|
+ PEEK_BYTE (a_this, 3, &next_bytes[2]);
|
|
+
|
|
+ if (((next_bytes[0] == 'r') || (next_bytes[0] == 'R'))
|
|
+ && ((next_bytes[1] == 'g') || (next_bytes[1] == 'G'))
|
|
+ && ((next_bytes[2] == 'b') || (next_bytes[2] == 'B'))) {
|
|
+ SKIP_CHARS (a_this, 1);
|
|
+ cr_tknzr_get_parsing_location (a_this, &location) ;
|
|
+ SKIP_CHARS (a_this, 2);
|
|
+ } else {
|
|
+ status = CR_PARSING_ERROR;
|
|
+ goto error;
|
|
+ }
|
|
+ READ_NEXT_BYTE (a_this, &cur_byte);
|
|
+ ENSURE_PARSING_COND (cur_byte == '(');
|
|
+
|
|
+ cr_tknzr_try_to_skip_spaces (a_this);
|
|
+ status = cr_tknzr_parse_num (a_this, &num);
|
|
+ ENSURE_PARSING_COND ((status == CR_OK) && (num != NULL));
|
|
+
|
|
+ if (num->val > G_MAXLONG) {
|
|
+ status = CR_PARSING_ERROR;
|
|
+ goto error;
|
|
+ }
|
|
+
|
|
+ red = num->val;
|
|
+ cr_num_destroy (num);
|
|
+ num = NULL;
|
|
+
|
|
+ PEEK_BYTE (a_this, 1, &next_bytes[0]);
|
|
+ if (next_bytes[0] == '%') {
|
|
+ SKIP_CHARS (a_this, 1);
|
|
+ is_percentage = TRUE;
|
|
+ }
|
|
+ cr_tknzr_try_to_skip_spaces (a_this);
|
|
+
|
|
+ for (i = 0; i < 2; i++) {
|
|
+ READ_NEXT_BYTE (a_this, &cur_byte);
|
|
+ ENSURE_PARSING_COND (cur_byte == ',');
|
|
+
|
|
+ cr_tknzr_try_to_skip_spaces (a_this);
|
|
+ status = cr_tknzr_parse_num (a_this, &num);
|
|
+ ENSURE_PARSING_COND ((status == CR_OK) && (num != NULL));
|
|
+
|
|
+ if (num->val > G_MAXLONG) {
|
|
+ status = CR_PARSING_ERROR;
|
|
+ goto error;
|
|
+ }
|
|
+
|
|
+ PEEK_BYTE (a_this, 1, &next_bytes[0]);
|
|
+ if (next_bytes[0] == '%') {
|
|
+ SKIP_CHARS (a_this, 1);
|
|
+ is_percentage = 1;
|
|
+ }
|
|
+
|
|
+ if (i == 0) {
|
|
+ green = num->val;
|
|
+ } else if (i == 1) {
|
|
+ blue = num->val;
|
|
+ }
|
|
+
|
|
+ if (num) {
|
|
+ cr_num_destroy (num);
|
|
+ num = NULL;
|
|
+ }
|
|
+ cr_tknzr_try_to_skip_spaces (a_this);
|
|
+ }
|
|
+
|
|
+ READ_NEXT_BYTE (a_this, &cur_byte);
|
|
+ if (*a_rgb == NULL) {
|
|
+ *a_rgb = cr_rgb_new_with_vals (red, green, blue,
|
|
+ is_percentage);
|
|
+
|
|
+ if (*a_rgb == NULL) {
|
|
+ status = CR_ERROR;
|
|
+ goto error;
|
|
+ }
|
|
+ status = CR_OK;
|
|
+ } else {
|
|
+ (*a_rgb)->red = red;
|
|
+ (*a_rgb)->green = green;
|
|
+ (*a_rgb)->blue = blue;
|
|
+ (*a_rgb)->is_percentage = is_percentage;
|
|
+
|
|
+ status = CR_OK;
|
|
+ }
|
|
+
|
|
+ if (status == CR_OK) {
|
|
+ if (a_rgb && *a_rgb) {
|
|
+ cr_parsing_location_copy
|
|
+ (&(*a_rgb)->location,
|
|
+ &location) ;
|
|
+ }
|
|
+ return CR_OK;
|
|
+ }
|
|
+
|
|
+ error:
|
|
+ if (num) {
|
|
+ cr_num_destroy (num);
|
|
+ num = NULL;
|
|
+ }
|
|
+
|
|
+ cr_tknzr_set_cur_pos (a_this, &init_pos);
|
|
+ return CR_OK;
|
|
+}
|
|
+
|
|
+/**
|
|
+ *Parses a atkeyword as defined by the css spec in [4.1.1]:
|
|
+ *ATKEYWORD ::= @{ident}
|
|
+ *
|
|
+ *@param a_this the "this pointer" of the current instance of
|
|
+ *#CRTknzr.
|
|
+ *
|
|
+ *@param a_str out parameter. The parsed atkeyword. If *a_str is
|
|
+ *set to NULL this function allocates a new instance of CRString and
|
|
+ *sets it to the parsed atkeyword. If not, this function just appends
|
|
+ *the parsed atkeyword to the end of *a_str. In both cases it is up to
|
|
+ *the caller to free *a_str.
|
|
+ *
|
|
+ *@return CR_OK upon successfull completion, an error code otherwise.
|
|
+ */
|
|
+static enum CRStatus
|
|
+cr_tknzr_parse_atkeyword (CRTknzr * a_this,
|
|
+ CRString ** a_str)
|
|
+{
|
|
+ guint32 cur_char = 0;
|
|
+ CRInputPos init_pos;
|
|
+ gboolean str_needs_free = FALSE;
|
|
+ enum CRStatus status = CR_OK;
|
|
+
|
|
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
|
|
+ && PRIVATE (a_this)->input
|
|
+ && a_str, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ RECORD_INITIAL_POS (a_this, &init_pos);
|
|
+
|
|
+ READ_NEXT_CHAR (a_this, &cur_char);
|
|
+
|
|
+ if (cur_char != '@') {
|
|
+ status = CR_PARSING_ERROR;
|
|
+ goto error;
|
|
+ }
|
|
+
|
|
+ if (*a_str == NULL) {
|
|
+ *a_str = cr_string_new ();
|
|
+ str_needs_free = TRUE;
|
|
+ }
|
|
+ status = cr_tknzr_parse_ident (a_this, a_str);
|
|
+ if (status != CR_OK) {
|
|
+ goto error;
|
|
+ }
|
|
+ return CR_OK;
|
|
+ error:
|
|
+
|
|
+ if (str_needs_free == TRUE && *a_str) {
|
|
+ cr_string_destroy (*a_str);
|
|
+ *a_str = NULL;
|
|
+ }
|
|
+ cr_tknzr_set_cur_pos (a_this, &init_pos);
|
|
+ return status;
|
|
+}
|
|
+
|
|
+static enum CRStatus
|
|
+cr_tknzr_parse_important (CRTknzr * a_this,
|
|
+ CRParsingLocation *a_location)
|
|
+{
|
|
+ guint32 cur_char = 0;
|
|
+ CRInputPos init_pos;
|
|
+ enum CRStatus status = CR_OK;
|
|
+
|
|
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
|
|
+ && PRIVATE (a_this)->input,
|
|
+ CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ RECORD_INITIAL_POS (a_this, &init_pos);
|
|
+ READ_NEXT_CHAR (a_this, &cur_char);
|
|
+ ENSURE_PARSING_COND (cur_char == '!');
|
|
+ if (a_location) {
|
|
+ cr_tknzr_get_parsing_location (a_this,
|
|
+ a_location) ;
|
|
+ }
|
|
+ cr_tknzr_try_to_skip_spaces (a_this);
|
|
+
|
|
+ if (BYTE (PRIVATE (a_this)->input, 1, NULL) == 'i'
|
|
+ && BYTE (PRIVATE (a_this)->input, 2, NULL) == 'm'
|
|
+ && BYTE (PRIVATE (a_this)->input, 3, NULL) == 'p'
|
|
+ && BYTE (PRIVATE (a_this)->input, 4, NULL) == 'o'
|
|
+ && BYTE (PRIVATE (a_this)->input, 5, NULL) == 'r'
|
|
+ && BYTE (PRIVATE (a_this)->input, 6, NULL) == 't'
|
|
+ && BYTE (PRIVATE (a_this)->input, 7, NULL) == 'a'
|
|
+ && BYTE (PRIVATE (a_this)->input, 8, NULL) == 'n'
|
|
+ && BYTE (PRIVATE (a_this)->input, 9, NULL) == 't') {
|
|
+ SKIP_BYTES (a_this, 9);
|
|
+ if (a_location) {
|
|
+ cr_tknzr_get_parsing_location (a_this,
|
|
+ a_location) ;
|
|
+ }
|
|
+ return CR_OK;
|
|
+ } else {
|
|
+ status = CR_PARSING_ERROR;
|
|
+ }
|
|
+
|
|
+ error:
|
|
+ cr_tknzr_set_cur_pos (a_this, &init_pos);
|
|
+
|
|
+ return status;
|
|
+}
|
|
+
|
|
+/**
|
|
+ *Parses a num as defined in the css spec [4.1.1]:
|
|
+ *[0-9]+|[0-9]*\.[0-9]+
|
|
+ *@param a_this the current instance of #CRTknzr.
|
|
+ *@param a_num out parameter. The parsed number.
|
|
+ *@return CR_OK upon successfull completion,
|
|
+ *an error code otherwise.
|
|
+ *
|
|
+ *The CSS specification says that numbers may be
|
|
+ *preceeded by '+' or '-' to indicate the sign.
|
|
+ *Technically, the "num" construction as defined
|
|
+ *by the tokenizer doesn't allow this, but we parse
|
|
+ *it here for simplicity.
|
|
+ */
|
|
+static enum CRStatus
|
|
+cr_tknzr_parse_num (CRTknzr * a_this,
|
|
+ CRNum ** a_num)
|
|
+{
|
|
+ enum CRStatus status = CR_PARSING_ERROR;
|
|
+ enum CRNumType val_type = NUM_GENERIC;
|
|
+ gboolean parsing_dec, /* true iff seen decimal point. */
|
|
+ parsed; /* true iff the substring seen so far is a valid CSS
|
|
+ number, i.e. `[0-9]+|[0-9]*\.[0-9]+'. */
|
|
+ guint32 cur_char = 0,
|
|
+ next_char = 0;
|
|
+ gdouble numerator, denominator = 1;
|
|
+ CRInputPos init_pos;
|
|
+ CRParsingLocation location = {0} ;
|
|
+ int sign = 1;
|
|
+
|
|
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
|
|
+ && PRIVATE (a_this)->input,
|
|
+ CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ RECORD_INITIAL_POS (a_this, &init_pos);
|
|
+ READ_NEXT_CHAR (a_this, &cur_char);
|
|
+
|
|
+ if (cur_char == '+' || cur_char == '-') {
|
|
+ if (cur_char == '-') {
|
|
+ sign = -1;
|
|
+ }
|
|
+ READ_NEXT_CHAR (a_this, &cur_char);
|
|
+ }
|
|
+
|
|
+ if (IS_NUM (cur_char)) {
|
|
+ numerator = (cur_char - '0');
|
|
+ parsing_dec = FALSE;
|
|
+ parsed = TRUE;
|
|
+ } else if (cur_char == '.') {
|
|
+ numerator = 0;
|
|
+ parsing_dec = TRUE;
|
|
+ parsed = FALSE;
|
|
+ } else {
|
|
+ status = CR_PARSING_ERROR;
|
|
+ goto error;
|
|
+ }
|
|
+ cr_tknzr_get_parsing_location (a_this, &location) ;
|
|
+
|
|
+ for (;;) {
|
|
+ status = cr_tknzr_peek_char (a_this, &next_char);
|
|
+ if (status != CR_OK) {
|
|
+ if (status == CR_END_OF_INPUT_ERROR)
|
|
+ status = CR_OK;
|
|
+ break;
|
|
+ }
|
|
+ if (next_char == '.') {
|
|
+ if (parsing_dec) {
|
|
+ status = CR_PARSING_ERROR;
|
|
+ goto error;
|
|
+ }
|
|
+
|
|
+ READ_NEXT_CHAR (a_this, &cur_char);
|
|
+ parsing_dec = TRUE;
|
|
+ parsed = FALSE; /* In CSS, there must be at least
|
|
+ one digit after `.'. */
|
|
+ } else if (IS_NUM (next_char)) {
|
|
+ READ_NEXT_CHAR (a_this, &cur_char);
|
|
+ parsed = TRUE;
|
|
+
|
|
+ numerator = numerator * 10 + (cur_char - '0');
|
|
+ if (parsing_dec) {
|
|
+ denominator *= 10;
|
|
+ }
|
|
+ } else {
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (!parsed) {
|
|
+ status = CR_PARSING_ERROR;
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ *Now, set the output param values.
|
|
+ */
|
|
+ if (status == CR_OK) {
|
|
+ gdouble val = (numerator / denominator) * sign;
|
|
+ if (*a_num == NULL) {
|
|
+ *a_num = cr_num_new_with_val (val, val_type);
|
|
+
|
|
+ if (*a_num == NULL) {
|
|
+ status = CR_ERROR;
|
|
+ goto error;
|
|
+ }
|
|
+ } else {
|
|
+ (*a_num)->val = val;
|
|
+ (*a_num)->type = val_type;
|
|
+ }
|
|
+ cr_parsing_location_copy (&(*a_num)->location,
|
|
+ &location) ;
|
|
+ return CR_OK;
|
|
+ }
|
|
+
|
|
+ error:
|
|
+
|
|
+ cr_tknzr_set_cur_pos (a_this, &init_pos);
|
|
+
|
|
+ return status;
|
|
+}
|
|
+
|
|
+/*********************************************
|
|
+ *PUBLIC methods
|
|
+ ********************************************/
|
|
+
|
|
+CRTknzr *
|
|
+cr_tknzr_new (CRInput * a_input)
|
|
+{
|
|
+ CRTknzr *result = NULL;
|
|
+
|
|
+ result = g_try_malloc (sizeof (CRTknzr));
|
|
+
|
|
+ if (result == NULL) {
|
|
+ cr_utils_trace_info ("Out of memory");
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
+ memset (result, 0, sizeof (CRTknzr));
|
|
+
|
|
+ result->priv = g_try_malloc (sizeof (CRTknzrPriv));
|
|
+
|
|
+ if (result->priv == NULL) {
|
|
+ cr_utils_trace_info ("Out of memory");
|
|
+
|
|
+ if (result) {
|
|
+ g_free (result);
|
|
+ result = NULL;
|
|
+ }
|
|
+
|
|
+ return NULL;
|
|
+ }
|
|
+ memset (result->priv, 0, sizeof (CRTknzrPriv));
|
|
+ if (a_input)
|
|
+ cr_tknzr_set_input (result, a_input);
|
|
+ return result;
|
|
+}
|
|
+
|
|
+CRTknzr *
|
|
+cr_tknzr_new_from_buf (guchar * a_buf, gulong a_len,
|
|
+ enum CREncoding a_enc,
|
|
+ gboolean a_free_at_destroy)
|
|
+{
|
|
+ CRTknzr *result = NULL;
|
|
+ CRInput *input = NULL;
|
|
+
|
|
+ input = cr_input_new_from_buf (a_buf, a_len, a_enc,
|
|
+ a_free_at_destroy);
|
|
+
|
|
+ g_return_val_if_fail (input != NULL, NULL);
|
|
+
|
|
+ result = cr_tknzr_new (input);
|
|
+
|
|
+ return result;
|
|
+}
|
|
+
|
|
+CRTknzr *
|
|
+cr_tknzr_new_from_uri (const guchar * a_file_uri,
|
|
+ enum CREncoding a_enc)
|
|
+{
|
|
+ CRTknzr *result = NULL;
|
|
+ CRInput *input = NULL;
|
|
+
|
|
+ input = cr_input_new_from_uri ((const gchar *) a_file_uri, a_enc);
|
|
+ g_return_val_if_fail (input != NULL, NULL);
|
|
+
|
|
+ result = cr_tknzr_new (input);
|
|
+
|
|
+ return result;
|
|
+}
|
|
+
|
|
+void
|
|
+cr_tknzr_ref (CRTknzr * a_this)
|
|
+{
|
|
+ g_return_if_fail (a_this && PRIVATE (a_this));
|
|
+
|
|
+ PRIVATE (a_this)->ref_count++;
|
|
+}
|
|
+
|
|
+gboolean
|
|
+cr_tknzr_unref (CRTknzr * a_this)
|
|
+{
|
|
+ g_return_val_if_fail (a_this && PRIVATE (a_this), FALSE);
|
|
+
|
|
+ if (PRIVATE (a_this)->ref_count > 0) {
|
|
+ PRIVATE (a_this)->ref_count--;
|
|
+ }
|
|
+
|
|
+ if (PRIVATE (a_this)->ref_count == 0) {
|
|
+ cr_tknzr_destroy (a_this);
|
|
+ return TRUE;
|
|
+ }
|
|
+
|
|
+ return FALSE;
|
|
+}
|
|
+
|
|
+enum CRStatus
|
|
+cr_tknzr_set_input (CRTknzr * a_this, CRInput * a_input)
|
|
+{
|
|
+ g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ if (PRIVATE (a_this)->input) {
|
|
+ cr_input_unref (PRIVATE (a_this)->input);
|
|
+ }
|
|
+
|
|
+ PRIVATE (a_this)->input = a_input;
|
|
+
|
|
+ cr_input_ref (PRIVATE (a_this)->input);
|
|
+
|
|
+ return CR_OK;
|
|
+}
|
|
+
|
|
+enum CRStatus
|
|
+cr_tknzr_get_input (CRTknzr * a_this, CRInput ** a_input)
|
|
+{
|
|
+ g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ *a_input = PRIVATE (a_this)->input;
|
|
+
|
|
+ return CR_OK;
|
|
+}
|
|
+
|
|
+/*********************************
|
|
+ *Tokenizer input handling routines
|
|
+ *********************************/
|
|
+
|
|
+/**
|
|
+ *Reads the next byte from the parser input stream.
|
|
+ *@param a_this the "this pointer" of the current instance of
|
|
+ *#CRParser.
|
|
+ *@param a_byte out parameter the place where to store the byte
|
|
+ *read.
|
|
+ *@return CR_OK upon successfull completion, an error
|
|
+ *code otherwise.
|
|
+ */
|
|
+enum CRStatus
|
|
+cr_tknzr_read_byte (CRTknzr * a_this, guchar * a_byte)
|
|
+{
|
|
+ g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ return cr_input_read_byte (PRIVATE (a_this)->input, a_byte);
|
|
+
|
|
+}
|
|
+
|
|
+/**
|
|
+ *Reads the next char from the parser input stream.
|
|
+ *@param a_this the current instance of #CRTknzr.
|
|
+ *@param a_char out parameter. The read char.
|
|
+ *@return CR_OK upon successfull completion, an error code
|
|
+ *otherwise.
|
|
+ */
|
|
+enum CRStatus
|
|
+cr_tknzr_read_char (CRTknzr * a_this, guint32 * a_char)
|
|
+{
|
|
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
|
|
+ && PRIVATE (a_this)->input
|
|
+ && a_char, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ if (PRIVATE (a_this)->token_cache) {
|
|
+ cr_input_set_cur_pos (PRIVATE (a_this)->input,
|
|
+ &PRIVATE (a_this)->prev_pos);
|
|
+ cr_token_destroy (PRIVATE (a_this)->token_cache);
|
|
+ PRIVATE (a_this)->token_cache = NULL;
|
|
+ }
|
|
+
|
|
+ return cr_input_read_char (PRIVATE (a_this)->input, a_char);
|
|
+}
|
|
+
|
|
+/**
|
|
+ *Peeks a char from the parser input stream.
|
|
+ *To "peek a char" means reads the next char without consuming it.
|
|
+ *Subsequent calls to this function return the same char.
|
|
+ *@param a_this the current instance of #CRTknzr.
|
|
+ *@param a_char out parameter. The peeked char uppon successfull completion.
|
|
+ *@return CR_OK upon successfull completion, an error code otherwise.
|
|
+ */
|
|
+enum CRStatus
|
|
+cr_tknzr_peek_char (CRTknzr * a_this, guint32 * a_char)
|
|
+{
|
|
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
|
|
+ && PRIVATE (a_this)->input
|
|
+ && a_char, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ if (PRIVATE (a_this)->token_cache) {
|
|
+ cr_input_set_cur_pos (PRIVATE (a_this)->input,
|
|
+ &PRIVATE (a_this)->prev_pos);
|
|
+ cr_token_destroy (PRIVATE (a_this)->token_cache);
|
|
+ PRIVATE (a_this)->token_cache = NULL;
|
|
+ }
|
|
+
|
|
+ return cr_input_peek_char (PRIVATE (a_this)->input, a_char);
|
|
+}
|
|
+
|
|
+/**
|
|
+ *Peeks a byte ahead at a given postion in the parser input stream.
|
|
+ *@param a_this the current instance of #CRTknzr.
|
|
+ *@param a_offset the offset of the peeked byte starting from the current
|
|
+ *byte in the parser input stream.
|
|
+ *@param a_byte out parameter. The peeked byte upon
|
|
+ *successfull completion.
|
|
+ *@return CR_OK upon successfull completion, an error code otherwise.
|
|
+ */
|
|
+enum CRStatus
|
|
+cr_tknzr_peek_byte (CRTknzr * a_this, gulong a_offset, guchar * a_byte)
|
|
+{
|
|
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
|
|
+ && PRIVATE (a_this)->input && a_byte,
|
|
+ CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ if (PRIVATE (a_this)->token_cache) {
|
|
+ cr_input_set_cur_pos (PRIVATE (a_this)->input,
|
|
+ &PRIVATE (a_this)->prev_pos);
|
|
+ cr_token_destroy (PRIVATE (a_this)->token_cache);
|
|
+ PRIVATE (a_this)->token_cache = NULL;
|
|
+ }
|
|
+
|
|
+ return cr_input_peek_byte (PRIVATE (a_this)->input,
|
|
+ CR_SEEK_CUR, a_offset, a_byte);
|
|
+}
|
|
+
|
|
+/**
|
|
+ *Same as cr_tknzr_peek_byte() but this api returns the byte peeked.
|
|
+ *@param a_this the current instance of #CRTknzr.
|
|
+ *@param a_offset the offset of the peeked byte starting from the current
|
|
+ *byte in the parser input stream.
|
|
+ *@param a_eof out parameter. If not NULL, is set to TRUE if we reached end of
|
|
+ *file, FALE otherwise. If the caller sets it to NULL, this parameter
|
|
+ *is just ignored.
|
|
+ *@return the peeked byte.
|
|
+ */
|
|
+guchar
|
|
+cr_tknzr_peek_byte2 (CRTknzr * a_this, gulong a_offset, gboolean * a_eof)
|
|
+{
|
|
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
|
|
+ && PRIVATE (a_this)->input, 0);
|
|
+
|
|
+ return cr_input_peek_byte2 (PRIVATE (a_this)->input, a_offset, a_eof);
|
|
+}
|
|
+
|
|
+/**
|
|
+ *Gets the number of bytes left in the topmost input stream
|
|
+ *associated to this parser.
|
|
+ *@param a_this the current instance of #CRTknzr
|
|
+ *@return the number of bytes left or -1 in case of error.
|
|
+ */
|
|
+glong
|
|
+cr_tknzr_get_nb_bytes_left (CRTknzr * a_this)
|
|
+{
|
|
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
|
|
+ && PRIVATE (a_this)->input, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ if (PRIVATE (a_this)->token_cache) {
|
|
+ cr_input_set_cur_pos (PRIVATE (a_this)->input,
|
|
+ &PRIVATE (a_this)->prev_pos);
|
|
+ cr_token_destroy (PRIVATE (a_this)->token_cache);
|
|
+ PRIVATE (a_this)->token_cache = NULL;
|
|
+ }
|
|
+
|
|
+ return cr_input_get_nb_bytes_left (PRIVATE (a_this)->input);
|
|
+}
|
|
+
|
|
+enum CRStatus
|
|
+cr_tknzr_get_cur_pos (CRTknzr * a_this, CRInputPos * a_pos)
|
|
+{
|
|
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
|
|
+ && PRIVATE (a_this)->input
|
|
+ && a_pos, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ if (PRIVATE (a_this)->token_cache) {
|
|
+ cr_input_set_cur_pos (PRIVATE (a_this)->input,
|
|
+ &PRIVATE (a_this)->prev_pos);
|
|
+ cr_token_destroy (PRIVATE (a_this)->token_cache);
|
|
+ PRIVATE (a_this)->token_cache = NULL;
|
|
+ }
|
|
+
|
|
+ return cr_input_get_cur_pos (PRIVATE (a_this)->input, a_pos);
|
|
+}
|
|
+
|
|
+enum CRStatus
|
|
+cr_tknzr_get_parsing_location (CRTknzr *a_this,
|
|
+ CRParsingLocation *a_loc)
|
|
+{
|
|
+ g_return_val_if_fail (a_this
|
|
+ && PRIVATE (a_this)
|
|
+ && a_loc,
|
|
+ CR_BAD_PARAM_ERROR) ;
|
|
+
|
|
+ return cr_input_get_parsing_location
|
|
+ (PRIVATE (a_this)->input, a_loc) ;
|
|
+}
|
|
+
|
|
+enum CRStatus
|
|
+cr_tknzr_get_cur_byte_addr (CRTknzr * a_this, guchar ** a_addr)
|
|
+{
|
|
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
|
|
+ && PRIVATE (a_this)->input, CR_BAD_PARAM_ERROR);
|
|
+ if (PRIVATE (a_this)->token_cache) {
|
|
+ cr_input_set_cur_pos (PRIVATE (a_this)->input,
|
|
+ &PRIVATE (a_this)->prev_pos);
|
|
+ cr_token_destroy (PRIVATE (a_this)->token_cache);
|
|
+ PRIVATE (a_this)->token_cache = NULL;
|
|
+ }
|
|
+
|
|
+ return cr_input_get_cur_byte_addr (PRIVATE (a_this)->input, a_addr);
|
|
+}
|
|
+
|
|
+enum CRStatus
|
|
+cr_tknzr_seek_index (CRTknzr * a_this, enum CRSeekPos a_origin, gint a_pos)
|
|
+{
|
|
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
|
|
+ && PRIVATE (a_this)->input, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ if (PRIVATE (a_this)->token_cache) {
|
|
+ cr_input_set_cur_pos (PRIVATE (a_this)->input,
|
|
+ &PRIVATE (a_this)->prev_pos);
|
|
+ cr_token_destroy (PRIVATE (a_this)->token_cache);
|
|
+ PRIVATE (a_this)->token_cache = NULL;
|
|
+ }
|
|
+
|
|
+ return cr_input_seek_index (PRIVATE (a_this)->input, a_origin, a_pos);
|
|
+}
|
|
+
|
|
+enum CRStatus
|
|
+cr_tknzr_consume_chars (CRTknzr * a_this, guint32 a_char, glong * a_nb_char)
|
|
+{
|
|
+ gulong consumed = *(gulong *) a_nb_char;
|
|
+ enum CRStatus status;
|
|
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
|
|
+ && PRIVATE (a_this)->input, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ if (PRIVATE (a_this)->token_cache) {
|
|
+ cr_input_set_cur_pos (PRIVATE (a_this)->input,
|
|
+ &PRIVATE (a_this)->prev_pos);
|
|
+ cr_token_destroy (PRIVATE (a_this)->token_cache);
|
|
+ PRIVATE (a_this)->token_cache = NULL;
|
|
+ }
|
|
+
|
|
+ status = cr_input_consume_chars (PRIVATE (a_this)->input,
|
|
+ a_char, &consumed);
|
|
+ *a_nb_char = (glong) consumed;
|
|
+ return status;
|
|
+}
|
|
+
|
|
+enum CRStatus
|
|
+cr_tknzr_set_cur_pos (CRTknzr * a_this, CRInputPos * a_pos)
|
|
+{
|
|
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
|
|
+ && PRIVATE (a_this)->input, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ if (PRIVATE (a_this)->token_cache) {
|
|
+ cr_token_destroy (PRIVATE (a_this)->token_cache);
|
|
+ PRIVATE (a_this)->token_cache = NULL;
|
|
+ }
|
|
+
|
|
+ return cr_input_set_cur_pos (PRIVATE (a_this)->input, a_pos);
|
|
+}
|
|
+
|
|
+enum CRStatus
|
|
+cr_tknzr_unget_token (CRTknzr * a_this, CRToken * a_token)
|
|
+{
|
|
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
|
|
+ && PRIVATE (a_this)->token_cache == NULL,
|
|
+ CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ PRIVATE (a_this)->token_cache = a_token;
|
|
+
|
|
+ return CR_OK;
|
|
+}
|
|
+
|
|
+/**
|
|
+ *Returns the next token of the input stream.
|
|
+ *This method is really central. Each parsing
|
|
+ *method calls it.
|
|
+ *@param a_this the current tokenizer.
|
|
+ *@param a_tk out parameter. The returned token.
|
|
+ *for the sake of mem leak avoidance, *a_tk must
|
|
+ *be NULL.
|
|
+ *@param CR_OK upon successfull completion, an error code
|
|
+ *otherwise.
|
|
+ */
|
|
+enum CRStatus
|
|
+cr_tknzr_get_next_token (CRTknzr * a_this, CRToken ** a_tk)
|
|
+{
|
|
+ enum CRStatus status = CR_OK;
|
|
+ CRToken *token = NULL;
|
|
+ CRInputPos init_pos;
|
|
+ guint32 next_char = 0;
|
|
+ guchar next_bytes[4] = { 0 };
|
|
+ gboolean reached_eof = FALSE;
|
|
+ CRInput *input = NULL;
|
|
+ CRString *str = NULL;
|
|
+ CRRgb *rgb = NULL;
|
|
+ CRParsingLocation location = {0} ;
|
|
+
|
|
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
|
|
+ && a_tk && *a_tk == NULL
|
|
+ && PRIVATE (a_this)->input,
|
|
+ CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ if (PRIVATE (a_this)->token_cache) {
|
|
+ *a_tk = PRIVATE (a_this)->token_cache;
|
|
+ PRIVATE (a_this)->token_cache = NULL;
|
|
+ return CR_OK;
|
|
+ }
|
|
+
|
|
+ RECORD_INITIAL_POS (a_this, &init_pos);
|
|
+
|
|
+ status = cr_input_get_end_of_file
|
|
+ (PRIVATE (a_this)->input, &reached_eof);
|
|
+ ENSURE_PARSING_COND (status == CR_OK);
|
|
+
|
|
+ if (reached_eof == TRUE) {
|
|
+ status = CR_END_OF_INPUT_ERROR;
|
|
+ goto error;
|
|
+ }
|
|
+
|
|
+ input = PRIVATE (a_this)->input;
|
|
+
|
|
+ PEEK_NEXT_CHAR (a_this, &next_char);
|
|
+ token = cr_token_new ();
|
|
+ ENSURE_PARSING_COND (token);
|
|
+
|
|
+ switch (next_char) {
|
|
+ case '@':
|
|
+ {
|
|
+ if (BYTE (input, 2, NULL) == 'f'
|
|
+ && BYTE (input, 3, NULL) == 'o'
|
|
+ && BYTE (input, 4, NULL) == 'n'
|
|
+ && BYTE (input, 5, NULL) == 't'
|
|
+ && BYTE (input, 6, NULL) == '-'
|
|
+ && BYTE (input, 7, NULL) == 'f'
|
|
+ && BYTE (input, 8, NULL) == 'a'
|
|
+ && BYTE (input, 9, NULL) == 'c'
|
|
+ && BYTE (input, 10, NULL) == 'e') {
|
|
+ SKIP_CHARS (a_this, 1);
|
|
+ cr_tknzr_get_parsing_location
|
|
+ (a_this, &location) ;
|
|
+ SKIP_CHARS (a_this, 9);
|
|
+ status = cr_token_set_font_face_sym (token);
|
|
+ CHECK_PARSING_STATUS (status, TRUE);
|
|
+ cr_parsing_location_copy (&token->location,
|
|
+ &location) ;
|
|
+ goto done;
|
|
+ }
|
|
+
|
|
+ if (BYTE (input, 2, NULL) == 'c'
|
|
+ && BYTE (input, 3, NULL) == 'h'
|
|
+ && BYTE (input, 4, NULL) == 'a'
|
|
+ && BYTE (input, 5, NULL) == 'r'
|
|
+ && BYTE (input, 6, NULL) == 's'
|
|
+ && BYTE (input, 7, NULL) == 'e'
|
|
+ && BYTE (input, 8, NULL) == 't') {
|
|
+ SKIP_CHARS (a_this, 1);
|
|
+ cr_tknzr_get_parsing_location
|
|
+ (a_this, &location) ;
|
|
+ SKIP_CHARS (a_this, 7);
|
|
+ status = cr_token_set_charset_sym (token);
|
|
+ CHECK_PARSING_STATUS (status, TRUE);
|
|
+ cr_parsing_location_copy (&token->location,
|
|
+ &location) ;
|
|
+ goto done;
|
|
+ }
|
|
+
|
|
+ if (BYTE (input, 2, NULL) == 'i'
|
|
+ && BYTE (input, 3, NULL) == 'm'
|
|
+ && BYTE (input, 4, NULL) == 'p'
|
|
+ && BYTE (input, 5, NULL) == 'o'
|
|
+ && BYTE (input, 6, NULL) == 'r'
|
|
+ && BYTE (input, 7, NULL) == 't') {
|
|
+ SKIP_CHARS (a_this, 1);
|
|
+ cr_tknzr_get_parsing_location
|
|
+ (a_this, &location) ;
|
|
+ SKIP_CHARS (a_this, 6);
|
|
+ status = cr_token_set_import_sym (token);
|
|
+ CHECK_PARSING_STATUS (status, TRUE);
|
|
+ cr_parsing_location_copy (&token->location,
|
|
+ &location) ;
|
|
+ goto done;
|
|
+ }
|
|
+
|
|
+ if (BYTE (input, 2, NULL) == 'm'
|
|
+ && BYTE (input, 3, NULL) == 'e'
|
|
+ && BYTE (input, 4, NULL) == 'd'
|
|
+ && BYTE (input, 5, NULL) == 'i'
|
|
+ && BYTE (input, 6, NULL) == 'a') {
|
|
+ SKIP_CHARS (a_this, 1);
|
|
+ cr_tknzr_get_parsing_location (a_this,
|
|
+ &location) ;
|
|
+ SKIP_CHARS (a_this, 5);
|
|
+ status = cr_token_set_media_sym (token);
|
|
+ CHECK_PARSING_STATUS (status, TRUE);
|
|
+ cr_parsing_location_copy (&token->location,
|
|
+ &location) ;
|
|
+ goto done;
|
|
+ }
|
|
+
|
|
+ if (BYTE (input, 2, NULL) == 'p'
|
|
+ && BYTE (input, 3, NULL) == 'a'
|
|
+ && BYTE (input, 4, NULL) == 'g'
|
|
+ && BYTE (input, 5, NULL) == 'e') {
|
|
+ SKIP_CHARS (a_this, 1);
|
|
+ cr_tknzr_get_parsing_location (a_this,
|
|
+ &location) ;
|
|
+ SKIP_CHARS (a_this, 4);
|
|
+ status = cr_token_set_page_sym (token);
|
|
+ CHECK_PARSING_STATUS (status, TRUE);
|
|
+ cr_parsing_location_copy (&token->location,
|
|
+ &location) ;
|
|
+ goto done;
|
|
+ }
|
|
+ status = cr_tknzr_parse_atkeyword (a_this, &str);
|
|
+ if (status == CR_OK) {
|
|
+ status = cr_token_set_atkeyword (token, str);
|
|
+ CHECK_PARSING_STATUS (status, TRUE);
|
|
+ if (str) {
|
|
+ cr_parsing_location_copy (&token->location,
|
|
+ &str->location) ;
|
|
+ }
|
|
+ goto done;
|
|
+ }
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case 'u':
|
|
+
|
|
+ if (BYTE (input, 2, NULL) == 'r'
|
|
+ && BYTE (input, 3, NULL) == 'l'
|
|
+ && BYTE (input, 4, NULL) == '(') {
|
|
+ CRString *str2 = NULL;
|
|
+
|
|
+ status = cr_tknzr_parse_uri (a_this, &str2);
|
|
+ if (status == CR_OK) {
|
|
+ status = cr_token_set_uri (token, str2);
|
|
+ CHECK_PARSING_STATUS (status, TRUE);
|
|
+ if (str2) {
|
|
+ cr_parsing_location_copy (&token->location,
|
|
+ &str2->location) ;
|
|
+ }
|
|
+ goto done;
|
|
+ }
|
|
+ }
|
|
+ goto fallback;
|
|
+ break;
|
|
+
|
|
+ case 'r':
|
|
+ if (BYTE (input, 2, NULL) == 'g'
|
|
+ && BYTE (input, 3, NULL) == 'b'
|
|
+ && BYTE (input, 4, NULL) == '(') {
|
|
+ status = cr_tknzr_parse_rgb (a_this, &rgb);
|
|
+ if (status == CR_OK && rgb) {
|
|
+ status = cr_token_set_rgb (token, rgb);
|
|
+ CHECK_PARSING_STATUS (status, TRUE);
|
|
+ if (rgb) {
|
|
+ cr_parsing_location_copy (&token->location,
|
|
+ &rgb->location) ;
|
|
+ }
|
|
+ rgb = NULL;
|
|
+ goto done;
|
|
+ }
|
|
+
|
|
+ }
|
|
+ goto fallback;
|
|
+ break;
|
|
+
|
|
+ case '<':
|
|
+ if (BYTE (input, 2, NULL) == '!'
|
|
+ && BYTE (input, 3, NULL) == '-'
|
|
+ && BYTE (input, 4, NULL) == '-') {
|
|
+ SKIP_CHARS (a_this, 1);
|
|
+ cr_tknzr_get_parsing_location (a_this,
|
|
+ &location) ;
|
|
+ SKIP_CHARS (a_this, 3);
|
|
+ status = cr_token_set_cdo (token);
|
|
+ CHECK_PARSING_STATUS (status, TRUE);
|
|
+ cr_parsing_location_copy (&token->location,
|
|
+ &location) ;
|
|
+ goto done;
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case '-':
|
|
+ if (BYTE (input, 2, NULL) == '-'
|
|
+ && BYTE (input, 3, NULL) == '>') {
|
|
+ SKIP_CHARS (a_this, 1);
|
|
+ cr_tknzr_get_parsing_location (a_this,
|
|
+ &location) ;
|
|
+ SKIP_CHARS (a_this, 2);
|
|
+ status = cr_token_set_cdc (token);
|
|
+ CHECK_PARSING_STATUS (status, TRUE);
|
|
+ cr_parsing_location_copy (&token->location,
|
|
+ &location) ;
|
|
+ goto done;
|
|
+ } else {
|
|
+ status = cr_tknzr_parse_ident
|
|
+ (a_this, &str);
|
|
+ if (status == CR_OK) {
|
|
+ cr_token_set_ident
|
|
+ (token, str);
|
|
+ if (str) {
|
|
+ cr_parsing_location_copy (&token->location,
|
|
+ &str->location) ;
|
|
+ }
|
|
+ goto done;
|
|
+ } else {
|
|
+ goto parse_number;
|
|
+ }
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case '~':
|
|
+ if (BYTE (input, 2, NULL) == '=') {
|
|
+ SKIP_CHARS (a_this, 1);
|
|
+ cr_tknzr_get_parsing_location (a_this,
|
|
+ &location) ;
|
|
+ SKIP_CHARS (a_this, 1);
|
|
+ status = cr_token_set_includes (token);
|
|
+ CHECK_PARSING_STATUS (status, TRUE);
|
|
+ cr_parsing_location_copy (&token->location,
|
|
+ &location) ;
|
|
+ goto done;
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case '|':
|
|
+ if (BYTE (input, 2, NULL) == '=') {
|
|
+ SKIP_CHARS (a_this, 1);
|
|
+ cr_tknzr_get_parsing_location (a_this,
|
|
+ &location) ;
|
|
+ SKIP_CHARS (a_this, 1);
|
|
+ status = cr_token_set_dashmatch (token);
|
|
+ CHECK_PARSING_STATUS (status, TRUE);
|
|
+ cr_parsing_location_copy (&token->location,
|
|
+ &location) ;
|
|
+ goto done;
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case '/':
|
|
+ if (BYTE (input, 2, NULL) == '*') {
|
|
+ status = cr_tknzr_parse_comment (a_this, &str);
|
|
+
|
|
+ if (status == CR_OK) {
|
|
+ status = cr_token_set_comment (token, str);
|
|
+ str = NULL;
|
|
+ CHECK_PARSING_STATUS (status, TRUE);
|
|
+ if (str) {
|
|
+ cr_parsing_location_copy (&token->location,
|
|
+ &str->location) ;
|
|
+ }
|
|
+ goto done;
|
|
+ }
|
|
+ }
|
|
+ break ;
|
|
+
|
|
+ case ';':
|
|
+ SKIP_CHARS (a_this, 1);
|
|
+ cr_tknzr_get_parsing_location (a_this,
|
|
+ &location) ;
|
|
+ status = cr_token_set_semicolon (token);
|
|
+ CHECK_PARSING_STATUS (status, TRUE);
|
|
+ cr_parsing_location_copy (&token->location,
|
|
+ &location) ;
|
|
+ goto done;
|
|
+
|
|
+ case '{':
|
|
+ SKIP_CHARS (a_this, 1);
|
|
+ cr_tknzr_get_parsing_location (a_this,
|
|
+ &location) ;
|
|
+ status = cr_token_set_cbo (token);
|
|
+ CHECK_PARSING_STATUS (status, TRUE);
|
|
+ cr_tknzr_get_parsing_location (a_this,
|
|
+ &location) ;
|
|
+ goto done;
|
|
+
|
|
+ case '}':
|
|
+ SKIP_CHARS (a_this, 1);
|
|
+ cr_tknzr_get_parsing_location (a_this,
|
|
+ &location) ;
|
|
+ status = cr_token_set_cbc (token);
|
|
+ CHECK_PARSING_STATUS (status, TRUE);
|
|
+ cr_parsing_location_copy (&token->location,
|
|
+ &location) ;
|
|
+ goto done;
|
|
+
|
|
+ case '(':
|
|
+ SKIP_CHARS (a_this, 1);
|
|
+ cr_tknzr_get_parsing_location (a_this,
|
|
+ &location) ;
|
|
+ status = cr_token_set_po (token);
|
|
+ CHECK_PARSING_STATUS (status, TRUE);
|
|
+ cr_parsing_location_copy (&token->location,
|
|
+ &location) ;
|
|
+ goto done;
|
|
+
|
|
+ case ')':
|
|
+ SKIP_CHARS (a_this, 1);
|
|
+ cr_tknzr_get_parsing_location (a_this,
|
|
+ &location) ;
|
|
+ status = cr_token_set_pc (token);
|
|
+ CHECK_PARSING_STATUS (status, TRUE);
|
|
+ cr_parsing_location_copy (&token->location,
|
|
+ &location) ;
|
|
+ goto done;
|
|
+
|
|
+ case '[':
|
|
+ SKIP_CHARS (a_this, 1);
|
|
+ cr_tknzr_get_parsing_location (a_this,
|
|
+ &location) ;
|
|
+ status = cr_token_set_bo (token);
|
|
+ CHECK_PARSING_STATUS (status, TRUE);
|
|
+ cr_parsing_location_copy (&token->location,
|
|
+ &location) ;
|
|
+ goto done;
|
|
+
|
|
+ case ']':
|
|
+ SKIP_CHARS (a_this, 1);
|
|
+ cr_tknzr_get_parsing_location (a_this,
|
|
+ &location) ;
|
|
+ status = cr_token_set_bc (token);
|
|
+ CHECK_PARSING_STATUS (status, TRUE);
|
|
+ cr_parsing_location_copy (&token->location,
|
|
+ &location) ;
|
|
+ goto done;
|
|
+
|
|
+ case ' ':
|
|
+ case '\t':
|
|
+ case '\n':
|
|
+ case '\f':
|
|
+ case '\r':
|
|
+ {
|
|
+ guchar *start = NULL,
|
|
+ *end = NULL;
|
|
+
|
|
+ status = cr_tknzr_parse_w (a_this, &start,
|
|
+ &end, &location);
|
|
+ if (status == CR_OK) {
|
|
+ status = cr_token_set_s (token);
|
|
+ CHECK_PARSING_STATUS (status, TRUE);
|
|
+ cr_tknzr_get_parsing_location (a_this,
|
|
+ &location) ;
|
|
+ goto done;
|
|
+ }
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case '#':
|
|
+ {
|
|
+ status = cr_tknzr_parse_hash (a_this, &str);
|
|
+ if (status == CR_OK && str) {
|
|
+ status = cr_token_set_hash (token, str);
|
|
+ CHECK_PARSING_STATUS (status, TRUE);
|
|
+ if (str) {
|
|
+ cr_parsing_location_copy (&token->location,
|
|
+ &str->location) ;
|
|
+ }
|
|
+ str = NULL;
|
|
+ goto done;
|
|
+ }
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case '\'':
|
|
+ case '"':
|
|
+ status = cr_tknzr_parse_string (a_this, &str);
|
|
+ if (status == CR_OK && str) {
|
|
+ status = cr_token_set_string (token, str);
|
|
+ CHECK_PARSING_STATUS (status, TRUE);
|
|
+ if (str) {
|
|
+ cr_parsing_location_copy (&token->location,
|
|
+ &str->location) ;
|
|
+ }
|
|
+ str = NULL;
|
|
+ goto done;
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case '!':
|
|
+ status = cr_tknzr_parse_important (a_this, &location);
|
|
+ if (status == CR_OK) {
|
|
+ status = cr_token_set_important_sym (token);
|
|
+ CHECK_PARSING_STATUS (status, TRUE);
|
|
+ cr_parsing_location_copy (&token->location,
|
|
+ &location) ;
|
|
+ goto done;
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case '0':
|
|
+ case '1':
|
|
+ case '2':
|
|
+ case '3':
|
|
+ case '4':
|
|
+ case '5':
|
|
+ case '6':
|
|
+ case '7':
|
|
+ case '8':
|
|
+ case '9':
|
|
+ case '.':
|
|
+ case '+':
|
|
+ /* '-' case is handled separately above for --> comments */
|
|
+ parse_number:
|
|
+ {
|
|
+ CRNum *num = NULL;
|
|
+
|
|
+ status = cr_tknzr_parse_num (a_this, &num);
|
|
+ if (status == CR_OK && num) {
|
|
+ next_bytes[0] = BYTE (input, 1, NULL);
|
|
+ next_bytes[1] = BYTE (input, 2, NULL);
|
|
+ next_bytes[2] = BYTE (input, 3, NULL);
|
|
+ next_bytes[3] = BYTE (input, 4, NULL);
|
|
+
|
|
+ if (next_bytes[0] == 'e'
|
|
+ && next_bytes[1] == 'm') {
|
|
+ num->type = NUM_LENGTH_EM;
|
|
+ status = cr_token_set_ems (token,
|
|
+ num);
|
|
+ num = NULL;
|
|
+ SKIP_CHARS (a_this, 2);
|
|
+ } else if (next_bytes[0] == 'e'
|
|
+ && next_bytes[1] == 'x') {
|
|
+ num->type = NUM_LENGTH_EX;
|
|
+ status = cr_token_set_exs (token,
|
|
+ num);
|
|
+ num = NULL;
|
|
+ SKIP_CHARS (a_this, 2);
|
|
+ } else if (next_bytes[0] == 'p'
|
|
+ && next_bytes[1] == 'x') {
|
|
+ num->type = NUM_LENGTH_PX;
|
|
+ status = cr_token_set_length
|
|
+ (token, num, LENGTH_PX_ET);
|
|
+ num = NULL;
|
|
+ SKIP_CHARS (a_this, 2);
|
|
+ } else if (next_bytes[0] == 'c'
|
|
+ && next_bytes[1] == 'm') {
|
|
+ num->type = NUM_LENGTH_CM;
|
|
+ status = cr_token_set_length
|
|
+ (token, num, LENGTH_CM_ET);
|
|
+ num = NULL;
|
|
+ SKIP_CHARS (a_this, 2);
|
|
+ } else if (next_bytes[0] == 'm'
|
|
+ && next_bytes[1] == 'm') {
|
|
+ num->type = NUM_LENGTH_MM;
|
|
+ status = cr_token_set_length
|
|
+ (token, num, LENGTH_MM_ET);
|
|
+ num = NULL;
|
|
+ SKIP_CHARS (a_this, 2);
|
|
+ } else if (next_bytes[0] == 'i'
|
|
+ && next_bytes[1] == 'n') {
|
|
+ num->type = NUM_LENGTH_IN;
|
|
+ status = cr_token_set_length
|
|
+ (token, num, LENGTH_IN_ET);
|
|
+ num = NULL;
|
|
+ SKIP_CHARS (a_this, 2);
|
|
+ } else if (next_bytes[0] == 'p'
|
|
+ && next_bytes[1] == 't') {
|
|
+ num->type = NUM_LENGTH_PT;
|
|
+ status = cr_token_set_length
|
|
+ (token, num, LENGTH_PT_ET);
|
|
+ num = NULL;
|
|
+ SKIP_CHARS (a_this, 2);
|
|
+ } else if (next_bytes[0] == 'p'
|
|
+ && next_bytes[1] == 'c') {
|
|
+ num->type = NUM_LENGTH_PC;
|
|
+ status = cr_token_set_length
|
|
+ (token, num, LENGTH_PC_ET);
|
|
+ num = NULL;
|
|
+ SKIP_CHARS (a_this, 2);
|
|
+ } else if (next_bytes[0] == 'd'
|
|
+ && next_bytes[1] == 'e'
|
|
+ && next_bytes[2] == 'g') {
|
|
+ num->type = NUM_ANGLE_DEG;
|
|
+ status = cr_token_set_angle
|
|
+ (token, num, ANGLE_DEG_ET);
|
|
+ num = NULL;
|
|
+ SKIP_CHARS (a_this, 3);
|
|
+ } else if (next_bytes[0] == 'r'
|
|
+ && next_bytes[1] == 'a'
|
|
+ && next_bytes[2] == 'd') {
|
|
+ num->type = NUM_ANGLE_RAD;
|
|
+ status = cr_token_set_angle
|
|
+ (token, num, ANGLE_RAD_ET);
|
|
+ num = NULL;
|
|
+ SKIP_CHARS (a_this, 3);
|
|
+ } else if (next_bytes[0] == 'g'
|
|
+ && next_bytes[1] == 'r'
|
|
+ && next_bytes[2] == 'a'
|
|
+ && next_bytes[3] == 'd') {
|
|
+ num->type = NUM_ANGLE_GRAD;
|
|
+ status = cr_token_set_angle
|
|
+ (token, num, ANGLE_GRAD_ET);
|
|
+ num = NULL;
|
|
+ SKIP_CHARS (a_this, 4);
|
|
+ } else if (next_bytes[0] == 'm'
|
|
+ && next_bytes[1] == 's') {
|
|
+ num->type = NUM_TIME_MS;
|
|
+ status = cr_token_set_time
|
|
+ (token, num, TIME_MS_ET);
|
|
+ num = NULL;
|
|
+ SKIP_CHARS (a_this, 2);
|
|
+ } else if (next_bytes[0] == 's') {
|
|
+ num->type = NUM_TIME_S;
|
|
+ status = cr_token_set_time
|
|
+ (token, num, TIME_S_ET);
|
|
+ num = NULL;
|
|
+ SKIP_CHARS (a_this, 1);
|
|
+ } else if (next_bytes[0] == 'H'
|
|
+ && next_bytes[1] == 'z') {
|
|
+ num->type = NUM_FREQ_HZ;
|
|
+ status = cr_token_set_freq
|
|
+ (token, num, FREQ_HZ_ET);
|
|
+ num = NULL;
|
|
+ SKIP_CHARS (a_this, 2);
|
|
+ } else if (next_bytes[0] == 'k'
|
|
+ && next_bytes[1] == 'H'
|
|
+ && next_bytes[2] == 'z') {
|
|
+ num->type = NUM_FREQ_KHZ;
|
|
+ status = cr_token_set_freq
|
|
+ (token, num, FREQ_KHZ_ET);
|
|
+ num = NULL;
|
|
+ SKIP_CHARS (a_this, 3);
|
|
+ } else if (next_bytes[0] == '%') {
|
|
+ num->type = NUM_PERCENTAGE;
|
|
+ status = cr_token_set_percentage
|
|
+ (token, num);
|
|
+ num = NULL;
|
|
+ SKIP_CHARS (a_this, 1);
|
|
+ } else {
|
|
+ status = cr_tknzr_parse_ident (a_this,
|
|
+ &str);
|
|
+ if (status == CR_OK && str) {
|
|
+ num->type = NUM_UNKNOWN_TYPE;
|
|
+ status = cr_token_set_dimen
|
|
+ (token, num, str);
|
|
+ num = NULL;
|
|
+ CHECK_PARSING_STATUS (status,
|
|
+ TRUE);
|
|
+ str = NULL;
|
|
+ } else {
|
|
+ status = cr_token_set_number
|
|
+ (token, num);
|
|
+ num = NULL;
|
|
+ CHECK_PARSING_STATUS (status, CR_OK);
|
|
+ str = NULL;
|
|
+ }
|
|
+ }
|
|
+ if (token && token->u.num) {
|
|
+ cr_parsing_location_copy (&token->location,
|
|
+ &token->u.num->location) ;
|
|
+ } else {
|
|
+ status = CR_ERROR ;
|
|
+ }
|
|
+ goto done ;
|
|
+ }
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ default:
|
|
+ fallback:
|
|
+ /*process the fallback cases here */
|
|
+
|
|
+ if (next_char == '\\'
|
|
+ || (cr_utils_is_nonascii (next_bytes[0]) == TRUE)
|
|
+ || ((next_char >= 'a') && (next_char <= 'z'))
|
|
+ || ((next_char >= 'A') && (next_char <= 'Z'))) {
|
|
+ status = cr_tknzr_parse_ident (a_this, &str);
|
|
+ if (status == CR_OK && str) {
|
|
+ guint32 next_c = 0;
|
|
+
|
|
+ status = cr_input_peek_char
|
|
+ (PRIVATE (a_this)->input, &next_c);
|
|
+
|
|
+ if (status == CR_OK && next_c == '(') {
|
|
+
|
|
+ SKIP_CHARS (a_this, 1);
|
|
+ status = cr_token_set_function
|
|
+ (token, str);
|
|
+ CHECK_PARSING_STATUS (status, TRUE);
|
|
+ /*ownership is transfered
|
|
+ *to token by cr_token_set_function.
|
|
+ */
|
|
+ if (str) {
|
|
+ cr_parsing_location_copy (&token->location,
|
|
+ &str->location) ;
|
|
+ }
|
|
+ str = NULL;
|
|
+ } else {
|
|
+ status = cr_token_set_ident (token,
|
|
+ str);
|
|
+ CHECK_PARSING_STATUS (status, TRUE);
|
|
+ if (str) {
|
|
+ cr_parsing_location_copy (&token->location,
|
|
+ &str->location) ;
|
|
+ }
|
|
+ str = NULL;
|
|
+ }
|
|
+ goto done;
|
|
+ } else {
|
|
+ if (str) {
|
|
+ cr_string_destroy (str);
|
|
+ str = NULL;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ READ_NEXT_CHAR (a_this, &next_char);
|
|
+ cr_tknzr_get_parsing_location (a_this,
|
|
+ &location) ;
|
|
+ status = cr_token_set_delim (token, next_char);
|
|
+ CHECK_PARSING_STATUS (status, TRUE);
|
|
+ cr_parsing_location_copy (&token->location,
|
|
+ &location) ;
|
|
+ done:
|
|
+
|
|
+ if (status == CR_OK && token) {
|
|
+ *a_tk = token;
|
|
+ /*
|
|
+ *store the previous position input stream pos.
|
|
+ */
|
|
+ memmove (&PRIVATE (a_this)->prev_pos,
|
|
+ &init_pos, sizeof (CRInputPos));
|
|
+ return CR_OK;
|
|
+ }
|
|
+
|
|
+ error:
|
|
+ if (token) {
|
|
+ cr_token_destroy (token);
|
|
+ token = NULL;
|
|
+ }
|
|
+
|
|
+ if (str) {
|
|
+ cr_string_destroy (str);
|
|
+ str = NULL;
|
|
+ }
|
|
+ cr_tknzr_set_cur_pos (a_this, &init_pos);
|
|
+ return status;
|
|
+
|
|
+}
|
|
+
|
|
+enum CRStatus
|
|
+cr_tknzr_parse_token (CRTknzr * a_this, enum CRTokenType a_type,
|
|
+ enum CRTokenExtraType a_et, gpointer a_res,
|
|
+ gpointer a_extra_res)
|
|
+{
|
|
+ enum CRStatus status = CR_OK;
|
|
+ CRToken *token = NULL;
|
|
+
|
|
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
|
|
+ && PRIVATE (a_this)->input
|
|
+ && a_res, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ status = cr_tknzr_get_next_token (a_this, &token);
|
|
+ if (status != CR_OK)
|
|
+ return status;
|
|
+ if (token == NULL)
|
|
+ return CR_PARSING_ERROR;
|
|
+
|
|
+ if (token->type == a_type) {
|
|
+ switch (a_type) {
|
|
+ case NO_TK:
|
|
+ case S_TK:
|
|
+ case CDO_TK:
|
|
+ case CDC_TK:
|
|
+ case INCLUDES_TK:
|
|
+ case DASHMATCH_TK:
|
|
+ case IMPORT_SYM_TK:
|
|
+ case PAGE_SYM_TK:
|
|
+ case MEDIA_SYM_TK:
|
|
+ case FONT_FACE_SYM_TK:
|
|
+ case CHARSET_SYM_TK:
|
|
+ case IMPORTANT_SYM_TK:
|
|
+ status = CR_OK;
|
|
+ break;
|
|
+
|
|
+ case STRING_TK:
|
|
+ case IDENT_TK:
|
|
+ case HASH_TK:
|
|
+ case ATKEYWORD_TK:
|
|
+ case FUNCTION_TK:
|
|
+ case COMMENT_TK:
|
|
+ case URI_TK:
|
|
+ *((CRString **) a_res) = token->u.str;
|
|
+ token->u.str = NULL;
|
|
+ status = CR_OK;
|
|
+ break;
|
|
+
|
|
+ case EMS_TK:
|
|
+ case EXS_TK:
|
|
+ case PERCENTAGE_TK:
|
|
+ case NUMBER_TK:
|
|
+ *((CRNum **) a_res) = token->u.num;
|
|
+ token->u.num = NULL;
|
|
+ status = CR_OK;
|
|
+ break;
|
|
+
|
|
+ case LENGTH_TK:
|
|
+ case ANGLE_TK:
|
|
+ case TIME_TK:
|
|
+ case FREQ_TK:
|
|
+ if (token->extra_type == a_et) {
|
|
+ *((CRNum **) a_res) = token->u.num;
|
|
+ token->u.num = NULL;
|
|
+ status = CR_OK;
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case DIMEN_TK:
|
|
+ *((CRNum **) a_res) = token->u.num;
|
|
+ if (a_extra_res == NULL) {
|
|
+ status = CR_BAD_PARAM_ERROR;
|
|
+ goto error;
|
|
+ }
|
|
+
|
|
+ *((CRString **) a_extra_res) = token->dimen;
|
|
+ token->u.num = NULL;
|
|
+ token->dimen = NULL;
|
|
+ status = CR_OK;
|
|
+ break;
|
|
+
|
|
+ case DELIM_TK:
|
|
+ *((guint32 *) a_res) = token->u.unichar;
|
|
+ status = CR_OK;
|
|
+ break;
|
|
+
|
|
+ case UNICODERANGE_TK:
|
|
+ default:
|
|
+ status = CR_PARSING_ERROR;
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ cr_token_destroy (token);
|
|
+ token = NULL;
|
|
+ } else {
|
|
+ cr_tknzr_unget_token (a_this, token);
|
|
+ token = NULL;
|
|
+ status = CR_PARSING_ERROR;
|
|
+ }
|
|
+
|
|
+ return status;
|
|
+
|
|
+ error:
|
|
+
|
|
+ if (token) {
|
|
+ cr_tknzr_unget_token (a_this, token);
|
|
+ token = NULL;
|
|
+ }
|
|
+
|
|
+ return status;
|
|
+}
|
|
+
|
|
+void
|
|
+cr_tknzr_destroy (CRTknzr * a_this)
|
|
+{
|
|
+ g_return_if_fail (a_this);
|
|
+
|
|
+ if (PRIVATE (a_this) && PRIVATE (a_this)->input) {
|
|
+ if (cr_input_unref (PRIVATE (a_this)->input)
|
|
+ == TRUE) {
|
|
+ PRIVATE (a_this)->input = NULL;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (PRIVATE (a_this)->token_cache) {
|
|
+ cr_token_destroy (PRIVATE (a_this)->token_cache);
|
|
+ PRIVATE (a_this)->token_cache = NULL;
|
|
+ }
|
|
+
|
|
+ if (PRIVATE (a_this)) {
|
|
+ g_free (PRIVATE (a_this));
|
|
+ PRIVATE (a_this) = NULL;
|
|
+ }
|
|
+
|
|
+ g_free (a_this);
|
|
+}
|
|
diff --git a/src/st/croco/cr-tknzr.h b/src/st/croco/cr-tknzr.h
|
|
new file mode 100644
|
|
index 000000000..13985b30e
|
|
--- /dev/null
|
|
+++ b/src/st/croco/cr-tknzr.h
|
|
@@ -0,0 +1,115 @@
|
|
+/* -*- 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 coypyright information.
|
|
+ */
|
|
+
|
|
+/**
|
|
+ *@file
|
|
+ *The declaration of the #CRTknzr (tokenizer)
|
|
+ *class.
|
|
+ */
|
|
+
|
|
+#ifndef __CR_TKNZR_H__
|
|
+#define __CR_TKNZR_H__
|
|
+
|
|
+#include "cr-utils.h"
|
|
+#include "cr-input.h"
|
|
+#include "cr-token.h"
|
|
+
|
|
+G_BEGIN_DECLS
|
|
+
|
|
+
|
|
+typedef struct _CRTknzr CRTknzr ;
|
|
+typedef struct _CRTknzrPriv CRTknzrPriv ;
|
|
+
|
|
+/**
|
|
+ *The tokenizer is the class that knows
|
|
+ *about all the css token. Its main job is
|
|
+ *to return the next token found in the character
|
|
+ *input stream.
|
|
+ */
|
|
+struct _CRTknzr
|
|
+{
|
|
+ /*the private data of the tokenizer.*/
|
|
+ CRTknzrPriv *priv ;
|
|
+} ;
|
|
+
|
|
+CRTknzr * cr_tknzr_new (CRInput *a_input) ;
|
|
+
|
|
+CRTknzr * cr_tknzr_new_from_uri (const guchar *a_file_uri,
|
|
+ enum CREncoding a_enc) ;
|
|
+
|
|
+CRTknzr * cr_tknzr_new_from_buf (guchar *a_buf, gulong a_len,
|
|
+ enum CREncoding a_enc,
|
|
+ gboolean a_free_at_destroy) ;
|
|
+
|
|
+gboolean cr_tknzr_unref (CRTknzr *a_this) ;
|
|
+
|
|
+void cr_tknzr_ref (CRTknzr *a_this) ;
|
|
+
|
|
+enum CRStatus cr_tknzr_read_byte (CRTknzr *a_this, guchar *a_byte) ;
|
|
+
|
|
+enum CRStatus cr_tknzr_read_char (CRTknzr *a_this, guint32 *a_char);
|
|
+
|
|
+enum CRStatus cr_tknzr_peek_char (CRTknzr *a_this, guint32 *a_char) ;
|
|
+
|
|
+enum CRStatus cr_tknzr_peek_byte (CRTknzr *a_this, gulong a_offset,
|
|
+ guchar *a_byte) ;
|
|
+
|
|
+guchar cr_tknzr_peek_byte2 (CRTknzr *a_this, gulong a_offset,
|
|
+ gboolean *a_eof) ;
|
|
+
|
|
+enum CRStatus cr_tknzr_set_cur_pos (CRTknzr *a_this, CRInputPos *a_pos) ;
|
|
+
|
|
+glong cr_tknzr_get_nb_bytes_left (CRTknzr *a_this) ;
|
|
+
|
|
+enum CRStatus cr_tknzr_get_cur_pos (CRTknzr *a_this, CRInputPos *a_pos) ;
|
|
+
|
|
+enum CRStatus cr_tknzr_get_parsing_location (CRTknzr *a_this,
|
|
+ CRParsingLocation *a_loc) ;
|
|
+
|
|
+enum CRStatus cr_tknzr_seek_index (CRTknzr *a_this,
|
|
+ enum CRSeekPos a_origin,
|
|
+ gint a_pos) ;
|
|
+
|
|
+enum CRStatus cr_tknzr_get_cur_byte_addr (CRTknzr *a_this, guchar **a_addr) ;
|
|
+
|
|
+
|
|
+enum CRStatus cr_tknzr_consume_chars (CRTknzr *a_this, guint32 a_char,
|
|
+ glong *a_nb_char) ;
|
|
+
|
|
+enum CRStatus cr_tknzr_get_next_token (CRTknzr *a_this, CRToken ** a_tk) ;
|
|
+
|
|
+enum CRStatus cr_tknzr_unget_token (CRTknzr *a_this, CRToken *a_token) ;
|
|
+
|
|
+
|
|
+enum CRStatus cr_tknzr_parse_token (CRTknzr *a_this, enum CRTokenType a_type,
|
|
+ enum CRTokenExtraType a_et, gpointer a_res,
|
|
+ gpointer a_extra_res) ;
|
|
+enum CRStatus cr_tknzr_set_input (CRTknzr *a_this, CRInput *a_input) ;
|
|
+
|
|
+enum CRStatus cr_tknzr_get_input (CRTknzr *a_this, CRInput **a_input) ;
|
|
+
|
|
+void cr_tknzr_destroy (CRTknzr *a_this) ;
|
|
+
|
|
+G_END_DECLS
|
|
+
|
|
+#endif /*__CR_TKZNR_H__*/
|
|
diff --git a/src/st/croco/cr-token.c b/src/st/croco/cr-token.c
|
|
new file mode 100644
|
|
index 000000000..e240ab8f1
|
|
--- /dev/null
|
|
+++ b/src/st/croco/cr-token.c
|
|
@@ -0,0 +1,636 @@
|
|
+/* -*- 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.
|
|
+ */
|
|
+
|
|
+/**
|
|
+ *@file
|
|
+ *The definition of the #CRToken class.
|
|
+ *Abstracts a css2 token.
|
|
+ */
|
|
+#include <string.h>
|
|
+#include "cr-token.h"
|
|
+
|
|
+/*
|
|
+ *TODO: write a CRToken::to_string() method.
|
|
+ */
|
|
+
|
|
+/**
|
|
+ *Frees the attributes of the current instance
|
|
+ *of #CRtoken.
|
|
+ *@param a_this the current instance of #CRToken.
|
|
+ */
|
|
+static void
|
|
+cr_token_clear (CRToken * a_this)
|
|
+{
|
|
+ g_return_if_fail (a_this);
|
|
+
|
|
+ switch (a_this->type) {
|
|
+ case S_TK:
|
|
+ case CDO_TK:
|
|
+ case CDC_TK:
|
|
+ case INCLUDES_TK:
|
|
+ case DASHMATCH_TK:
|
|
+ case PAGE_SYM_TK:
|
|
+ case MEDIA_SYM_TK:
|
|
+ case FONT_FACE_SYM_TK:
|
|
+ case CHARSET_SYM_TK:
|
|
+ case IMPORT_SYM_TK:
|
|
+ case IMPORTANT_SYM_TK:
|
|
+ case SEMICOLON_TK:
|
|
+ case NO_TK:
|
|
+ case DELIM_TK:
|
|
+ case CBO_TK:
|
|
+ case CBC_TK:
|
|
+ case BO_TK:
|
|
+ case BC_TK:
|
|
+ break;
|
|
+
|
|
+ case STRING_TK:
|
|
+ case IDENT_TK:
|
|
+ case HASH_TK:
|
|
+ case URI_TK:
|
|
+ case FUNCTION_TK:
|
|
+ case COMMENT_TK:
|
|
+ case ATKEYWORD_TK:
|
|
+ if (a_this->u.str) {
|
|
+ cr_string_destroy (a_this->u.str);
|
|
+ a_this->u.str = NULL;
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case EMS_TK:
|
|
+ case EXS_TK:
|
|
+ case LENGTH_TK:
|
|
+ case ANGLE_TK:
|
|
+ case TIME_TK:
|
|
+ case FREQ_TK:
|
|
+ case PERCENTAGE_TK:
|
|
+ case NUMBER_TK:
|
|
+ case PO_TK:
|
|
+ case PC_TK:
|
|
+ if (a_this->u.num) {
|
|
+ cr_num_destroy (a_this->u.num);
|
|
+ a_this->u.num = NULL;
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case DIMEN_TK:
|
|
+ if (a_this->u.num) {
|
|
+ cr_num_destroy (a_this->u.num);
|
|
+ a_this->u.num = NULL;
|
|
+ }
|
|
+
|
|
+ if (a_this->dimen) {
|
|
+ cr_string_destroy (a_this->dimen);
|
|
+ a_this->dimen = NULL;
|
|
+ }
|
|
+
|
|
+ break;
|
|
+
|
|
+ case RGB_TK:
|
|
+ if (a_this->u.rgb) {
|
|
+ cr_rgb_destroy (a_this->u.rgb) ;
|
|
+ a_this->u.rgb = NULL ;
|
|
+ }
|
|
+ break ;
|
|
+
|
|
+ case UNICODERANGE_TK:
|
|
+ /*not supported yet. */
|
|
+ break;
|
|
+
|
|
+ default:
|
|
+ cr_utils_trace_info ("I don't know how to clear this token\n") ;
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ a_this->type = NO_TK;
|
|
+}
|
|
+
|
|
+/**
|
|
+ *Default constructor of
|
|
+ *the #CRToken class.
|
|
+ *@return the newly built instance of #CRToken.
|
|
+ */
|
|
+CRToken *
|
|
+cr_token_new (void)
|
|
+{
|
|
+ CRToken *result = NULL;
|
|
+
|
|
+ result = g_try_malloc (sizeof (CRToken));
|
|
+
|
|
+ if (result == NULL) {
|
|
+ cr_utils_trace_info ("Out of memory");
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
+ memset (result, 0, sizeof (CRToken));
|
|
+
|
|
+ return result;
|
|
+}
|
|
+
|
|
+/**
|
|
+ *Sets the type of curren instance of
|
|
+ *#CRToken to 'S_TK' (S in the css2 spec)
|
|
+ *@param a_this the current instance of #CRToken.
|
|
+ *@return CR_OK upon successfull completion, an error
|
|
+ *code otherwise.
|
|
+ */
|
|
+enum CRStatus
|
|
+cr_token_set_s (CRToken * a_this)
|
|
+{
|
|
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ cr_token_clear (a_this);
|
|
+
|
|
+ a_this->type = S_TK;
|
|
+
|
|
+ return CR_OK;
|
|
+}
|
|
+
|
|
+/**
|
|
+ *Sets the type of the current instance of
|
|
+ *#CRToken to 'CDO_TK' (CDO as said by the css2 spec)
|
|
+ *@param a_this the current instance of #CRToken.
|
|
+ *@return CR_OK upon successfull completion, an error
|
|
+ *code otherwise.
|
|
+ */
|
|
+enum CRStatus
|
|
+cr_token_set_cdo (CRToken * a_this)
|
|
+{
|
|
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ cr_token_clear (a_this);
|
|
+
|
|
+ a_this->type = CDO_TK;
|
|
+
|
|
+ return CR_OK;
|
|
+}
|
|
+
|
|
+/**
|
|
+ *Sets the type of the current token to
|
|
+ *CDC_TK (CDC as said by the css2 spec).
|
|
+ *@param a_this the current instance of #CRToken.
|
|
+ *@return CR_OK upon successfull completion, an error
|
|
+ *code otherwise.
|
|
+ */
|
|
+enum CRStatus
|
|
+cr_token_set_cdc (CRToken * a_this)
|
|
+{
|
|
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ cr_token_clear (a_this);
|
|
+
|
|
+ a_this->type = CDC_TK;
|
|
+
|
|
+ return CR_OK;
|
|
+}
|
|
+
|
|
+/**
|
|
+ *Sets the type of the current instance of
|
|
+ *#CRToken to INCLUDES_TK (INCLUDES as said by the css2 spec).
|
|
+ *@param a_this the current instance of #CRToken.
|
|
+ *@return CR_OK upon successfull completion, an error
|
|
+ *code otherwise.
|
|
+ */
|
|
+enum CRStatus
|
|
+cr_token_set_includes (CRToken * a_this)
|
|
+{
|
|
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ cr_token_clear (a_this);
|
|
+
|
|
+ a_this->type = INCLUDES_TK;
|
|
+
|
|
+ return CR_OK;
|
|
+}
|
|
+
|
|
+/**
|
|
+ *Sets the type of the current instance of
|
|
+ *#CRToken to DASHMATCH_TK (DASHMATCH as said by the css2 spec).
|
|
+ *@param a_this the current instance of #CRToken.
|
|
+ *@return CR_OK upon successfull completion, an error
|
|
+ *code otherwise.
|
|
+ */
|
|
+enum CRStatus
|
|
+cr_token_set_dashmatch (CRToken * a_this)
|
|
+{
|
|
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ cr_token_clear (a_this);
|
|
+
|
|
+ a_this->type = DASHMATCH_TK;
|
|
+
|
|
+ return CR_OK;
|
|
+}
|
|
+
|
|
+enum CRStatus
|
|
+cr_token_set_comment (CRToken * a_this, CRString * a_str)
|
|
+{
|
|
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ cr_token_clear (a_this);
|
|
+ a_this->type = COMMENT_TK;
|
|
+ a_this->u.str = a_str ;
|
|
+ return CR_OK;
|
|
+}
|
|
+
|
|
+enum CRStatus
|
|
+cr_token_set_string (CRToken * a_this, CRString * a_str)
|
|
+{
|
|
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ cr_token_clear (a_this);
|
|
+
|
|
+ a_this->type = STRING_TK;
|
|
+
|
|
+ a_this->u.str = a_str ;
|
|
+
|
|
+ return CR_OK;
|
|
+}
|
|
+
|
|
+enum CRStatus
|
|
+cr_token_set_ident (CRToken * a_this, CRString * a_ident)
|
|
+{
|
|
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ cr_token_clear (a_this);
|
|
+ a_this->type = IDENT_TK;
|
|
+ a_this->u.str = a_ident;
|
|
+ return CR_OK;
|
|
+}
|
|
+
|
|
+
|
|
+enum CRStatus
|
|
+cr_token_set_function (CRToken * a_this, CRString * a_fun_name)
|
|
+{
|
|
+ g_return_val_if_fail (a_this,
|
|
+ CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ cr_token_clear (a_this);
|
|
+ a_this->type = FUNCTION_TK;
|
|
+ a_this->u.str = a_fun_name;
|
|
+ return CR_OK;
|
|
+}
|
|
+
|
|
+enum CRStatus
|
|
+cr_token_set_hash (CRToken * a_this, CRString * a_hash)
|
|
+{
|
|
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ cr_token_clear (a_this);
|
|
+ a_this->type = HASH_TK;
|
|
+ a_this->u.str = a_hash;
|
|
+
|
|
+ return CR_OK;
|
|
+}
|
|
+
|
|
+enum CRStatus
|
|
+cr_token_set_rgb (CRToken * a_this, CRRgb * a_rgb)
|
|
+{
|
|
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ cr_token_clear (a_this);
|
|
+ a_this->type = RGB_TK;
|
|
+ a_this->u.rgb = a_rgb;
|
|
+
|
|
+ return CR_OK;
|
|
+}
|
|
+
|
|
+enum CRStatus
|
|
+cr_token_set_import_sym (CRToken * a_this)
|
|
+{
|
|
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ cr_token_clear (a_this);
|
|
+
|
|
+ a_this->type = IMPORT_SYM_TK;
|
|
+
|
|
+ return CR_OK;
|
|
+}
|
|
+
|
|
+enum CRStatus
|
|
+cr_token_set_page_sym (CRToken * a_this)
|
|
+{
|
|
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ cr_token_clear (a_this);
|
|
+
|
|
+ a_this->type = PAGE_SYM_TK;
|
|
+
|
|
+ return CR_OK;
|
|
+}
|
|
+
|
|
+enum CRStatus
|
|
+cr_token_set_media_sym (CRToken * a_this)
|
|
+{
|
|
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ cr_token_clear (a_this);
|
|
+
|
|
+ a_this->type = MEDIA_SYM_TK;
|
|
+
|
|
+ return CR_OK;
|
|
+}
|
|
+
|
|
+enum CRStatus
|
|
+cr_token_set_font_face_sym (CRToken * a_this)
|
|
+{
|
|
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ cr_token_clear (a_this);
|
|
+ a_this->type = FONT_FACE_SYM_TK;
|
|
+
|
|
+ return CR_OK;
|
|
+}
|
|
+
|
|
+enum CRStatus
|
|
+cr_token_set_charset_sym (CRToken * a_this)
|
|
+{
|
|
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ cr_token_clear (a_this);
|
|
+ a_this->type = CHARSET_SYM_TK;
|
|
+
|
|
+ return CR_OK;
|
|
+}
|
|
+
|
|
+enum CRStatus
|
|
+cr_token_set_atkeyword (CRToken * a_this, CRString * a_atname)
|
|
+{
|
|
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ cr_token_clear (a_this);
|
|
+ a_this->type = ATKEYWORD_TK;
|
|
+ a_this->u.str = a_atname;
|
|
+ return CR_OK;
|
|
+}
|
|
+
|
|
+enum CRStatus
|
|
+cr_token_set_important_sym (CRToken * a_this)
|
|
+{
|
|
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
|
|
+ cr_token_clear (a_this);
|
|
+ a_this->type = IMPORTANT_SYM_TK;
|
|
+ return CR_OK;
|
|
+}
|
|
+
|
|
+enum CRStatus
|
|
+cr_token_set_ems (CRToken * a_this, CRNum * a_num)
|
|
+{
|
|
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
|
|
+ cr_token_clear (a_this);
|
|
+ a_this->type = EMS_TK;
|
|
+ a_this->u.num = a_num;
|
|
+ return CR_OK;
|
|
+}
|
|
+
|
|
+enum CRStatus
|
|
+cr_token_set_exs (CRToken * a_this, CRNum * a_num)
|
|
+{
|
|
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
|
|
+ cr_token_clear (a_this);
|
|
+ a_this->type = EXS_TK;
|
|
+ a_this->u.num = a_num;
|
|
+ return CR_OK;
|
|
+}
|
|
+
|
|
+enum CRStatus
|
|
+cr_token_set_length (CRToken * a_this, CRNum * a_num,
|
|
+ enum CRTokenExtraType a_et)
|
|
+{
|
|
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ cr_token_clear (a_this);
|
|
+
|
|
+ a_this->type = LENGTH_TK;
|
|
+ a_this->extra_type = a_et;
|
|
+ a_this->u.num = a_num;
|
|
+
|
|
+ return CR_OK;
|
|
+}
|
|
+
|
|
+enum CRStatus
|
|
+cr_token_set_angle (CRToken * a_this, CRNum * a_num,
|
|
+ enum CRTokenExtraType a_et)
|
|
+{
|
|
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ cr_token_clear (a_this);
|
|
+
|
|
+ a_this->type = ANGLE_TK;
|
|
+ a_this->extra_type = a_et;
|
|
+ a_this->u.num = a_num;
|
|
+
|
|
+ return CR_OK;
|
|
+}
|
|
+
|
|
+enum CRStatus
|
|
+cr_token_set_time (CRToken * a_this, CRNum * a_num,
|
|
+ enum CRTokenExtraType a_et)
|
|
+{
|
|
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ cr_token_clear (a_this);
|
|
+
|
|
+ a_this->type = TIME_TK;
|
|
+ a_this->extra_type = a_et;
|
|
+ a_this->u.num = a_num;
|
|
+
|
|
+ return CR_OK;
|
|
+}
|
|
+
|
|
+enum CRStatus
|
|
+cr_token_set_freq (CRToken * a_this, CRNum * a_num,
|
|
+ enum CRTokenExtraType a_et)
|
|
+{
|
|
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ cr_token_clear (a_this);
|
|
+
|
|
+ a_this->type = FREQ_TK;
|
|
+ a_this->extra_type = a_et;
|
|
+ a_this->u.num = a_num;
|
|
+
|
|
+ return CR_OK;
|
|
+}
|
|
+
|
|
+enum CRStatus
|
|
+cr_token_set_dimen (CRToken * a_this, CRNum * a_num,
|
|
+ CRString * a_dim)
|
|
+{
|
|
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
|
|
+ cr_token_clear (a_this);
|
|
+ a_this->type = DIMEN_TK;
|
|
+ a_this->u.num = a_num;
|
|
+ a_this->dimen = a_dim;
|
|
+ return CR_OK;
|
|
+
|
|
+}
|
|
+
|
|
+enum CRStatus
|
|
+cr_token_set_percentage (CRToken * a_this, CRNum * a_num)
|
|
+{
|
|
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ cr_token_clear (a_this);
|
|
+
|
|
+ a_this->type = PERCENTAGE_TK;
|
|
+ a_this->u.num = a_num;
|
|
+
|
|
+ return CR_OK;
|
|
+}
|
|
+
|
|
+enum CRStatus
|
|
+cr_token_set_number (CRToken * a_this, CRNum * a_num)
|
|
+{
|
|
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ cr_token_clear (a_this);
|
|
+
|
|
+ a_this->type = NUMBER_TK;
|
|
+ a_this->u.num = a_num;
|
|
+ return CR_OK;
|
|
+}
|
|
+
|
|
+enum CRStatus
|
|
+cr_token_set_uri (CRToken * a_this, CRString * a_uri)
|
|
+{
|
|
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ cr_token_clear (a_this);
|
|
+
|
|
+ a_this->type = URI_TK;
|
|
+ a_this->u.str = a_uri;
|
|
+
|
|
+ return CR_OK;
|
|
+}
|
|
+
|
|
+enum CRStatus
|
|
+cr_token_set_delim (CRToken * a_this, guint32 a_char)
|
|
+{
|
|
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ cr_token_clear (a_this);
|
|
+
|
|
+ a_this->type = DELIM_TK;
|
|
+ a_this->u.unichar = a_char;
|
|
+
|
|
+ return CR_OK;
|
|
+}
|
|
+
|
|
+enum CRStatus
|
|
+cr_token_set_semicolon (CRToken * a_this)
|
|
+{
|
|
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ cr_token_clear (a_this);
|
|
+
|
|
+ a_this->type = SEMICOLON_TK;
|
|
+
|
|
+ return CR_OK;
|
|
+}
|
|
+
|
|
+enum CRStatus
|
|
+cr_token_set_cbo (CRToken * a_this)
|
|
+{
|
|
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ cr_token_clear (a_this);
|
|
+
|
|
+ a_this->type = CBO_TK;
|
|
+
|
|
+ return CR_OK;
|
|
+}
|
|
+
|
|
+enum CRStatus
|
|
+cr_token_set_cbc (CRToken * a_this)
|
|
+{
|
|
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ cr_token_clear (a_this);
|
|
+
|
|
+ a_this->type = CBC_TK;
|
|
+
|
|
+ return CR_OK;
|
|
+}
|
|
+
|
|
+enum CRStatus
|
|
+cr_token_set_po (CRToken * a_this)
|
|
+{
|
|
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ cr_token_clear (a_this);
|
|
+
|
|
+ a_this->type = PO_TK;
|
|
+
|
|
+ return CR_OK;
|
|
+}
|
|
+
|
|
+enum CRStatus
|
|
+cr_token_set_pc (CRToken * a_this)
|
|
+{
|
|
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ cr_token_clear (a_this);
|
|
+
|
|
+ a_this->type = PC_TK;
|
|
+
|
|
+ return CR_OK;
|
|
+}
|
|
+
|
|
+enum CRStatus
|
|
+cr_token_set_bo (CRToken * a_this)
|
|
+{
|
|
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ cr_token_clear (a_this);
|
|
+
|
|
+ a_this->type = BO_TK;
|
|
+
|
|
+ return CR_OK;
|
|
+}
|
|
+
|
|
+enum CRStatus
|
|
+cr_token_set_bc (CRToken * a_this)
|
|
+{
|
|
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ cr_token_clear (a_this);
|
|
+
|
|
+ a_this->type = BC_TK;
|
|
+
|
|
+ return CR_OK;
|
|
+}
|
|
+
|
|
+/**
|
|
+ *The destructor of the #CRToken class.
|
|
+ *@param a_this the current instance of #CRToken.
|
|
+ */
|
|
+void
|
|
+cr_token_destroy (CRToken * a_this)
|
|
+{
|
|
+ g_return_if_fail (a_this);
|
|
+
|
|
+ cr_token_clear (a_this);
|
|
+
|
|
+ g_free (a_this);
|
|
+}
|
|
diff --git a/src/st/croco/cr-token.h b/src/st/croco/cr-token.h
|
|
new file mode 100644
|
|
index 000000000..f1257b7a8
|
|
--- /dev/null
|
|
+++ b/src/st/croco/cr-token.h
|
|
@@ -0,0 +1,212 @@
|
|
+/* -*- 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.
|
|
+ */
|
|
+
|
|
+#ifndef __CR_TOKEN_H__
|
|
+#define __CR_TOKEN_H__
|
|
+
|
|
+#include "cr-utils.h"
|
|
+#include "cr-input.h"
|
|
+#include "cr-num.h"
|
|
+#include "cr-rgb.h"
|
|
+#include "cr-string.h"
|
|
+#include "cr-parsing-location.h"
|
|
+
|
|
+G_BEGIN_DECLS
|
|
+
|
|
+enum CRTokenType
|
|
+{
|
|
+ NO_TK,
|
|
+ S_TK,
|
|
+ CDO_TK,
|
|
+ CDC_TK,
|
|
+ INCLUDES_TK,
|
|
+ DASHMATCH_TK,
|
|
+ COMMENT_TK,
|
|
+ STRING_TK,
|
|
+ IDENT_TK,
|
|
+ HASH_TK,
|
|
+ IMPORT_SYM_TK,
|
|
+ PAGE_SYM_TK,
|
|
+ MEDIA_SYM_TK,
|
|
+ FONT_FACE_SYM_TK,
|
|
+ CHARSET_SYM_TK,
|
|
+ ATKEYWORD_TK,
|
|
+ IMPORTANT_SYM_TK,
|
|
+ EMS_TK,
|
|
+ EXS_TK,
|
|
+ LENGTH_TK,
|
|
+ ANGLE_TK,
|
|
+ TIME_TK,
|
|
+ FREQ_TK,
|
|
+ DIMEN_TK,
|
|
+ PERCENTAGE_TK,
|
|
+ NUMBER_TK,
|
|
+ RGB_TK,
|
|
+ URI_TK,
|
|
+ FUNCTION_TK,
|
|
+ UNICODERANGE_TK,
|
|
+ SEMICOLON_TK,
|
|
+ CBO_TK, /*opening curly bracket*/
|
|
+ CBC_TK, /*closing curly bracket*/
|
|
+ PO_TK, /*opening parenthesis*/
|
|
+ PC_TK, /*closing parenthesis*/
|
|
+ BO_TK, /*opening bracket*/
|
|
+ BC_TK, /*closing bracket*/
|
|
+ DELIM_TK
|
|
+} ;
|
|
+
|
|
+enum CRTokenExtraType
|
|
+{
|
|
+ NO_ET = 0,
|
|
+ LENGTH_PX_ET,
|
|
+ LENGTH_CM_ET,
|
|
+ LENGTH_MM_ET,
|
|
+ LENGTH_IN_ET,
|
|
+ LENGTH_PT_ET,
|
|
+ LENGTH_PC_ET,
|
|
+ ANGLE_DEG_ET,
|
|
+ ANGLE_RAD_ET,
|
|
+ ANGLE_GRAD_ET,
|
|
+ TIME_MS_ET,
|
|
+ TIME_S_ET,
|
|
+ FREQ_HZ_ET,
|
|
+ FREQ_KHZ_ET
|
|
+} ;
|
|
+
|
|
+typedef struct _CRToken CRToken ;
|
|
+
|
|
+/**
|
|
+ *This class abstracts a css2 token.
|
|
+ */
|
|
+struct _CRToken
|
|
+{
|
|
+ enum CRTokenType type ;
|
|
+ enum CRTokenExtraType extra_type ;
|
|
+ CRInputPos pos ;
|
|
+
|
|
+ union
|
|
+ {
|
|
+ CRString *str ;
|
|
+ CRRgb *rgb ;
|
|
+ CRNum *num ;
|
|
+ guint32 unichar ;
|
|
+ } u ;
|
|
+
|
|
+ CRString * dimen ;
|
|
+ CRParsingLocation location ;
|
|
+} ;
|
|
+
|
|
+CRToken* cr_token_new (void) ;
|
|
+
|
|
+enum CRStatus cr_token_set_s (CRToken *a_this) ;
|
|
+
|
|
+enum CRStatus cr_token_set_cdo (CRToken *a_this) ;
|
|
+
|
|
+enum CRStatus cr_token_set_cdc (CRToken *a_this) ;
|
|
+
|
|
+enum CRStatus cr_token_set_includes (CRToken *a_this) ;
|
|
+
|
|
+enum CRStatus cr_token_set_dashmatch (CRToken *a_this) ;
|
|
+
|
|
+enum CRStatus cr_token_set_comment (CRToken *a_this, CRString *a_str) ;
|
|
+
|
|
+enum CRStatus cr_token_set_string (CRToken *a_this, CRString *a_str) ;
|
|
+
|
|
+enum CRStatus cr_token_set_ident (CRToken *a_this, CRString * a_ident) ;
|
|
+
|
|
+enum CRStatus cr_token_set_hash (CRToken *a_this, CRString *a_hash) ;
|
|
+
|
|
+enum CRStatus cr_token_set_rgb (CRToken *a_this, CRRgb *a_rgb) ;
|
|
+
|
|
+enum CRStatus cr_token_set_import_sym (CRToken *a_this) ;
|
|
+
|
|
+enum CRStatus cr_token_set_page_sym (CRToken *a_this) ;
|
|
+
|
|
+enum CRStatus cr_token_set_media_sym (CRToken *a_this) ;
|
|
+
|
|
+enum CRStatus cr_token_set_font_face_sym (CRToken *a_this) ;
|
|
+
|
|
+enum CRStatus cr_token_set_charset_sym (CRToken *a_this) ;
|
|
+
|
|
+enum CRStatus cr_token_set_atkeyword (CRToken *a_this, CRString *a_atname) ;
|
|
+
|
|
+enum CRStatus cr_token_set_important_sym (CRToken *a_this) ;
|
|
+
|
|
+enum CRStatus cr_token_set_ems (CRToken *a_this, CRNum *a_num) ;
|
|
+
|
|
+enum CRStatus cr_token_set_exs (CRToken *a_this, CRNum *a_num) ;
|
|
+
|
|
+enum CRStatus cr_token_set_length (CRToken *a_this, CRNum *a_num,
|
|
+ enum CRTokenExtraType a_et) ;
|
|
+
|
|
+enum CRStatus cr_token_set_angle (CRToken *a_this, CRNum *a_num,
|
|
+ enum CRTokenExtraType a_et) ;
|
|
+
|
|
+enum CRStatus cr_token_set_time (CRToken *a_this, CRNum *a_num,
|
|
+ enum CRTokenExtraType a_et) ;
|
|
+
|
|
+enum CRStatus cr_token_set_freq (CRToken *a_this, CRNum *a_num,
|
|
+ enum CRTokenExtraType a_et) ;
|
|
+
|
|
+enum CRStatus cr_token_set_dimen (CRToken *a_this, CRNum *a_num,
|
|
+ CRString *a_dim) ;
|
|
+
|
|
+enum CRStatus cr_token_set_percentage (CRToken *a_this, CRNum *a_num) ;
|
|
+
|
|
+enum CRStatus cr_token_set_number (CRToken *a_this, CRNum *a_num) ;
|
|
+
|
|
+enum CRStatus cr_token_set_uri (CRToken *a_this, CRString *a_uri) ;
|
|
+
|
|
+enum CRStatus cr_token_set_function (CRToken *a_this,
|
|
+ CRString *a_fun_name) ;
|
|
+
|
|
+enum CRStatus cr_token_set_bc (CRToken *a_this) ;
|
|
+
|
|
+enum CRStatus cr_token_set_bo (CRToken *a_this) ;
|
|
+
|
|
+enum CRStatus cr_token_set_po (CRToken *a_this) ;
|
|
+
|
|
+enum CRStatus cr_token_set_pc (CRToken *a_this) ;
|
|
+
|
|
+enum CRStatus cr_token_set_cbc (CRToken *a_this) ;
|
|
+
|
|
+enum CRStatus cr_token_set_cbo (CRToken *a_this) ;
|
|
+
|
|
+enum CRStatus cr_token_set_semicolon (CRToken *a_this) ;
|
|
+
|
|
+enum CRStatus cr_token_set_delim (CRToken *a_this, guint32 a_char) ;
|
|
+
|
|
+
|
|
+/*
|
|
+ enum CRStatus
|
|
+ cr_token_set_unicoderange (CRToken *a_this,
|
|
+ CRUnicodeRange *a_range) ;
|
|
+*/
|
|
+
|
|
+void
|
|
+cr_token_destroy (CRToken *a_this) ;
|
|
+
|
|
+
|
|
+G_END_DECLS
|
|
+
|
|
+#endif /*__CR_TOKEN_H__*/
|
|
diff --git a/src/st/croco/cr-utils.c b/src/st/croco/cr-utils.c
|
|
new file mode 100644
|
|
index 000000000..2420cec7c
|
|
--- /dev/null
|
|
+++ b/src/st/croco/cr-utils.c
|
|
@@ -0,0 +1,1330 @@
|
|
+/* -*- 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 "cr-utils.h"
|
|
+#include "cr-string.h"
|
|
+
|
|
+/**
|
|
+ *@file:
|
|
+ *Some misc utility functions used
|
|
+ *in the libcroco.
|
|
+ *Note that troughout this file I will
|
|
+ *refer to the CSS SPECIFICATIONS DOCUMENTATION
|
|
+ *written by the w3c guys. You can find that document
|
|
+ *at http://www.w3.org/TR/REC-CSS2/ .
|
|
+ */
|
|
+
|
|
+/****************************
|
|
+ *Encoding transformations and
|
|
+ *encoding helpers
|
|
+ ****************************/
|
|
+
|
|
+/*
|
|
+ *Here is the correspondance between the ucs-4 charactere codes
|
|
+ *and there matching utf-8 encoding pattern as dscribed by RFC 2279:
|
|
+ *
|
|
+ *UCS-4 range (hex.) UTF-8 octet sequence (binary)
|
|
+ *------------------ -----------------------------
|
|
+ *0000 0000-0000 007F 0xxxxxxx
|
|
+ *0000 0080-0000 07FF 110xxxxx 10xxxxxx
|
|
+ *0000 0800-0000 FFFF 1110xxxx 10xxxxxx 10xxxxxx
|
|
+ *0001 0000-001F FFFF 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
|
|
+ *0020 0000-03FF FFFF 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
|
|
+ *0400 0000-7FFF FFFF 1111110x 10xxxxxx ... 10xxxxxx
|
|
+ */
|
|
+
|
|
+/**
|
|
+ *Given an utf8 string buffer, calculates
|
|
+ *the length of this string if it was encoded
|
|
+ *in ucs4.
|
|
+ *@param a_in_start a pointer to the begining of
|
|
+ *the input utf8 string.
|
|
+ *@param a_in_end a pointre to the end of the input
|
|
+ *utf8 string (points to the last byte of the buffer)
|
|
+ *@param a_len out parameter the calculated length.
|
|
+ *@return CR_OK upon succesfull completion, an error code
|
|
+ *otherwise.
|
|
+ */
|
|
+enum CRStatus
|
|
+cr_utils_utf8_str_len_as_ucs4 (const guchar * a_in_start,
|
|
+ const guchar * a_in_end, gulong * a_len)
|
|
+{
|
|
+ guchar *byte_ptr = NULL;
|
|
+ gint len = 0;
|
|
+
|
|
+ /*
|
|
+ *to store the final decoded
|
|
+ *unicode char
|
|
+ */
|
|
+ guint c = 0;
|
|
+
|
|
+ g_return_val_if_fail (a_in_start && a_in_end && a_len,
|
|
+ CR_BAD_PARAM_ERROR);
|
|
+ *a_len = 0;
|
|
+
|
|
+ for (byte_ptr = (guchar *) a_in_start;
|
|
+ byte_ptr <= a_in_end; byte_ptr++) {
|
|
+ gint nb_bytes_2_decode = 0;
|
|
+
|
|
+ if (*byte_ptr <= 0x7F) {
|
|
+ /*
|
|
+ *7 bits long char
|
|
+ *encoded over 1 byte:
|
|
+ * 0xxx xxxx
|
|
+ */
|
|
+ c = *byte_ptr;
|
|
+ nb_bytes_2_decode = 1;
|
|
+
|
|
+ } else if ((*byte_ptr & 0xE0) == 0xC0) {
|
|
+ /*
|
|
+ *up to 11 bits long char.
|
|
+ *encoded over 2 bytes:
|
|
+ *110x xxxx 10xx xxxx
|
|
+ */
|
|
+ c = *byte_ptr & 0x1F;
|
|
+ nb_bytes_2_decode = 2;
|
|
+
|
|
+ } else if ((*byte_ptr & 0xF0) == 0xE0) {
|
|
+ /*
|
|
+ *up to 16 bit long char
|
|
+ *encoded over 3 bytes:
|
|
+ *1110 xxxx 10xx xxxx 10xx xxxx
|
|
+ */
|
|
+ c = *byte_ptr & 0x0F;
|
|
+ nb_bytes_2_decode = 3;
|
|
+
|
|
+ } else if ((*byte_ptr & 0xF8) == 0xF0) {
|
|
+ /*
|
|
+ *up to 21 bits long char
|
|
+ *encoded over 4 bytes:
|
|
+ *1111 0xxx 10xx xxxx 10xx xxxx 10xx xxxx
|
|
+ */
|
|
+ c = *byte_ptr & 0x7;
|
|
+ nb_bytes_2_decode = 4;
|
|
+
|
|
+ } else if ((*byte_ptr & 0xFC) == 0xF8) {
|
|
+ /*
|
|
+ *up to 26 bits long char
|
|
+ *encoded over 5 bytes.
|
|
+ *1111 10xx 10xx xxxx 10xx xxxx
|
|
+ *10xx xxxx 10xx xxxx
|
|
+ */
|
|
+ c = *byte_ptr & 3;
|
|
+ nb_bytes_2_decode = 5;
|
|
+
|
|
+ } else if ((*byte_ptr & 0xFE) == 0xFC) {
|
|
+ /*
|
|
+ *up to 31 bits long char
|
|
+ *encoded over 6 bytes:
|
|
+ *1111 110x 10xx xxxx 10xx xxxx
|
|
+ *10xx xxxx 10xx xxxx 10xx xxxx
|
|
+ */
|
|
+ c = *byte_ptr & 1;
|
|
+ nb_bytes_2_decode = 6;
|
|
+
|
|
+ } else {
|
|
+ /*
|
|
+ *BAD ENCODING
|
|
+ */
|
|
+ return CR_ENCODING_ERROR;
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ *Go and decode the remaining byte(s)
|
|
+ *(if any) to get the current character.
|
|
+ */
|
|
+ for (; nb_bytes_2_decode > 1; nb_bytes_2_decode--) {
|
|
+ /*decode the next byte */
|
|
+ byte_ptr++;
|
|
+
|
|
+ /*byte pattern must be: 10xx xxxx */
|
|
+ if ((*byte_ptr & 0xC0) != 0x80) {
|
|
+ return CR_ENCODING_ERROR;
|
|
+ }
|
|
+
|
|
+ c = (c << 6) | (*byte_ptr & 0x3F);
|
|
+ }
|
|
+
|
|
+ len++;
|
|
+ }
|
|
+
|
|
+ *a_len = len;
|
|
+
|
|
+ return CR_OK;
|
|
+}
|
|
+
|
|
+/**
|
|
+ *Given an ucs4 string, this function
|
|
+ *returns the size (in bytes) this string
|
|
+ *would have occupied if it was encoded in utf-8.
|
|
+ *@param a_in_start a pointer to the beginning of the input
|
|
+ *buffer.
|
|
+ *@param a_in_end a pointer to the end of the input buffer.
|
|
+ *@param a_len out parameter. The computed length.
|
|
+ *@return CR_OK upon successfull completion, an error code otherwise.
|
|
+ */
|
|
+enum CRStatus
|
|
+cr_utils_ucs4_str_len_as_utf8 (const guint32 * a_in_start,
|
|
+ const guint32 * a_in_end, gulong * a_len)
|
|
+{
|
|
+ gint len = 0;
|
|
+ guint32 *char_ptr = NULL;
|
|
+
|
|
+ g_return_val_if_fail (a_in_start && a_in_end && a_len,
|
|
+ CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ for (char_ptr = (guint32 *) a_in_start;
|
|
+ char_ptr <= a_in_end; char_ptr++) {
|
|
+ if (*char_ptr <= 0x7F) {
|
|
+ /*the utf-8 char would take 1 byte */
|
|
+ len += 1;
|
|
+ } else if (*char_ptr <= 0x7FF) {
|
|
+ /*the utf-8 char would take 2 bytes */
|
|
+ len += 2;
|
|
+ } else if (*char_ptr <= 0xFFFF) {
|
|
+ len += 3;
|
|
+ } else if (*char_ptr <= 0x1FFFFF) {
|
|
+ len += 4;
|
|
+ } else if (*char_ptr <= 0x3FFFFFF) {
|
|
+ len += 5;
|
|
+ } else if (*char_ptr <= 0x7FFFFFFF) {
|
|
+ len += 6;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ *a_len = len;
|
|
+ return CR_OK;
|
|
+}
|
|
+
|
|
+/**
|
|
+ *Given an ucsA string, this function
|
|
+ *returns the size (in bytes) this string
|
|
+ *would have occupied if it was encoded in utf-8.
|
|
+ *@param a_in_start a pointer to the beginning of the input
|
|
+ *buffer.
|
|
+ *@param a_in_end a pointer to the end of the input buffer.
|
|
+ *@param a_len out parameter. The computed length.
|
|
+ *@return CR_OK upon successfull completion, an error code otherwise.
|
|
+ */
|
|
+enum CRStatus
|
|
+cr_utils_ucs1_str_len_as_utf8 (const guchar * a_in_start,
|
|
+ const guchar * a_in_end, gulong * a_len)
|
|
+{
|
|
+ gint len = 0;
|
|
+ guchar *char_ptr = NULL;
|
|
+
|
|
+ g_return_val_if_fail (a_in_start && a_in_end && a_len,
|
|
+ CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ for (char_ptr = (guchar *) a_in_start;
|
|
+ char_ptr <= a_in_end; char_ptr++) {
|
|
+ if (*char_ptr <= 0x7F) {
|
|
+ /*the utf-8 char would take 1 byte */
|
|
+ len += 1;
|
|
+ } else {
|
|
+ /*the utf-8 char would take 2 bytes */
|
|
+ len += 2;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ *a_len = len;
|
|
+ return CR_OK;
|
|
+}
|
|
+
|
|
+/**
|
|
+ *Converts an utf8 buffer into an ucs4 buffer.
|
|
+ *
|
|
+ *@param a_in the input utf8 buffer to convert.
|
|
+ *@param a_in_len in/out parameter. The size of the
|
|
+ *input buffer to convert. After return, this parameter contains
|
|
+ *the actual number of bytes consumed.
|
|
+ *@param a_out the output converted ucs4 buffer. Must be allocated by
|
|
+ *the caller.
|
|
+ *@param a_out_len in/out parameter. The size of the output buffer.
|
|
+ *If this size is actually smaller than the real needed size, the function
|
|
+ *just converts what it can and returns a success status. After return,
|
|
+ *this param points to the actual number of characters decoded.
|
|
+ *@return CR_OK upon successfull completion, an error code otherwise.
|
|
+ */
|
|
+enum CRStatus
|
|
+cr_utils_utf8_to_ucs4 (const guchar * a_in,
|
|
+ gulong * a_in_len, guint32 * a_out, gulong * a_out_len)
|
|
+{
|
|
+ gulong in_len = 0,
|
|
+ out_len = 0,
|
|
+ in_index = 0,
|
|
+ out_index = 0;
|
|
+ enum CRStatus status = CR_OK;
|
|
+
|
|
+ /*
|
|
+ *to store the final decoded
|
|
+ *unicode char
|
|
+ */
|
|
+ guint c = 0;
|
|
+
|
|
+ g_return_val_if_fail (a_in && a_in_len
|
|
+ && a_out && a_out_len, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ if (*a_in_len < 1) {
|
|
+ status = CR_OK;
|
|
+ goto end;
|
|
+ }
|
|
+
|
|
+ in_len = *a_in_len;
|
|
+ out_len = *a_out_len;
|
|
+
|
|
+ for (in_index = 0, out_index = 0;
|
|
+ (in_index < in_len) && (out_index < out_len);
|
|
+ in_index++, out_index++) {
|
|
+ gint nb_bytes_2_decode = 0;
|
|
+
|
|
+ if (a_in[in_index] <= 0x7F) {
|
|
+ /*
|
|
+ *7 bits long char
|
|
+ *encoded over 1 byte:
|
|
+ * 0xxx xxxx
|
|
+ */
|
|
+ c = a_in[in_index];
|
|
+ nb_bytes_2_decode = 1;
|
|
+
|
|
+ } else if ((a_in[in_index] & 0xE0) == 0xC0) {
|
|
+ /*
|
|
+ *up to 11 bits long char.
|
|
+ *encoded over 2 bytes:
|
|
+ *110x xxxx 10xx xxxx
|
|
+ */
|
|
+ c = a_in[in_index] & 0x1F;
|
|
+ nb_bytes_2_decode = 2;
|
|
+
|
|
+ } else if ((a_in[in_index] & 0xF0) == 0xE0) {
|
|
+ /*
|
|
+ *up to 16 bit long char
|
|
+ *encoded over 3 bytes:
|
|
+ *1110 xxxx 10xx xxxx 10xx xxxx
|
|
+ */
|
|
+ c = a_in[in_index] & 0x0F;
|
|
+ nb_bytes_2_decode = 3;
|
|
+
|
|
+ } else if ((a_in[in_index] & 0xF8) == 0xF0) {
|
|
+ /*
|
|
+ *up to 21 bits long char
|
|
+ *encoded over 4 bytes:
|
|
+ *1111 0xxx 10xx xxxx 10xx xxxx 10xx xxxx
|
|
+ */
|
|
+ c = a_in[in_index] & 0x7;
|
|
+ nb_bytes_2_decode = 4;
|
|
+
|
|
+ } else if ((a_in[in_index] & 0xFC) == 0xF8) {
|
|
+ /*
|
|
+ *up to 26 bits long char
|
|
+ *encoded over 5 bytes.
|
|
+ *1111 10xx 10xx xxxx 10xx xxxx
|
|
+ *10xx xxxx 10xx xxxx
|
|
+ */
|
|
+ c = a_in[in_index] & 3;
|
|
+ nb_bytes_2_decode = 5;
|
|
+
|
|
+ } else if ((a_in[in_index] & 0xFE) == 0xFC) {
|
|
+ /*
|
|
+ *up to 31 bits long char
|
|
+ *encoded over 6 bytes:
|
|
+ *1111 110x 10xx xxxx 10xx xxxx
|
|
+ *10xx xxxx 10xx xxxx 10xx xxxx
|
|
+ */
|
|
+ c = a_in[in_index] & 1;
|
|
+ nb_bytes_2_decode = 6;
|
|
+
|
|
+ } else {
|
|
+ /*BAD ENCODING */
|
|
+ goto end;
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ *Go and decode the remaining byte(s)
|
|
+ *(if any) to get the current character.
|
|
+ */
|
|
+ for (; nb_bytes_2_decode > 1; nb_bytes_2_decode--) {
|
|
+ /*decode the next byte */
|
|
+ in_index++;
|
|
+
|
|
+ /*byte pattern must be: 10xx xxxx */
|
|
+ if ((a_in[in_index] & 0xC0) != 0x80) {
|
|
+ goto end;
|
|
+ }
|
|
+
|
|
+ c = (c << 6) | (a_in[in_index] & 0x3F);
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ *The decoded ucs4 char is now
|
|
+ *in c.
|
|
+ */
|
|
+
|
|
+ /************************
|
|
+ *Some security tests
|
|
+ ***********************/
|
|
+
|
|
+ /*be sure c is a char */
|
|
+ if (c == 0xFFFF || c == 0xFFFE)
|
|
+ goto end;
|
|
+
|
|
+ /*be sure c is inferior to the max ucs4 char value */
|
|
+ if (c > 0x10FFFF)
|
|
+ goto end;
|
|
+
|
|
+ /*
|
|
+ *c must be less than UTF16 "lower surrogate begin"
|
|
+ *or higher than UTF16 "High surrogate end"
|
|
+ */
|
|
+ if (c >= 0xD800 && c <= 0xDFFF)
|
|
+ goto end;
|
|
+
|
|
+ /*Avoid characters that equals zero */
|
|
+ if (c == 0)
|
|
+ goto end;
|
|
+
|
|
+ a_out[out_index] = c;
|
|
+ }
|
|
+
|
|
+ end:
|
|
+ *a_out_len = out_index + 1;
|
|
+ *a_in_len = in_index + 1;
|
|
+
|
|
+ return status;
|
|
+}
|
|
+
|
|
+/**
|
|
+ *Reads a character from an utf8 buffer.
|
|
+ *Actually decode the next character code (unicode character code)
|
|
+ *and returns it.
|
|
+ *@param a_in the starting address of the utf8 buffer.
|
|
+ *@param a_in_len the length of the utf8 buffer.
|
|
+ *@param a_out output parameter. The resulting read char.
|
|
+ *@param a_consumed the number of the bytes consumed to
|
|
+ *decode the returned character code.
|
|
+ *@return CR_OK upon successfull completion, an error code otherwise.
|
|
+ */
|
|
+enum CRStatus
|
|
+cr_utils_read_char_from_utf8_buf (const guchar * a_in,
|
|
+ gulong a_in_len,
|
|
+ guint32 * a_out, gulong * a_consumed)
|
|
+{
|
|
+ gulong in_index = 0,
|
|
+ nb_bytes_2_decode = 0;
|
|
+ enum CRStatus status = CR_OK;
|
|
+
|
|
+ /*
|
|
+ *to store the final decoded
|
|
+ *unicode char
|
|
+ */
|
|
+ guint32 c = 0;
|
|
+
|
|
+ g_return_val_if_fail (a_in && a_out && a_out
|
|
+ && a_consumed, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ if (a_in_len < 1) {
|
|
+ status = CR_OK;
|
|
+ goto end;
|
|
+ }
|
|
+
|
|
+ if (*a_in <= 0x7F) {
|
|
+ /*
|
|
+ *7 bits long char
|
|
+ *encoded over 1 byte:
|
|
+ * 0xxx xxxx
|
|
+ */
|
|
+ c = *a_in;
|
|
+ nb_bytes_2_decode = 1;
|
|
+
|
|
+ } else if ((*a_in & 0xE0) == 0xC0) {
|
|
+ /*
|
|
+ *up to 11 bits long char.
|
|
+ *encoded over 2 bytes:
|
|
+ *110x xxxx 10xx xxxx
|
|
+ */
|
|
+ c = *a_in & 0x1F;
|
|
+ nb_bytes_2_decode = 2;
|
|
+
|
|
+ } else if ((*a_in & 0xF0) == 0xE0) {
|
|
+ /*
|
|
+ *up to 16 bit long char
|
|
+ *encoded over 3 bytes:
|
|
+ *1110 xxxx 10xx xxxx 10xx xxxx
|
|
+ */
|
|
+ c = *a_in & 0x0F;
|
|
+ nb_bytes_2_decode = 3;
|
|
+
|
|
+ } else if ((*a_in & 0xF8) == 0xF0) {
|
|
+ /*
|
|
+ *up to 21 bits long char
|
|
+ *encoded over 4 bytes:
|
|
+ *1111 0xxx 10xx xxxx 10xx xxxx 10xx xxxx
|
|
+ */
|
|
+ c = *a_in & 0x7;
|
|
+ nb_bytes_2_decode = 4;
|
|
+
|
|
+ } else if ((*a_in & 0xFC) == 0xF8) {
|
|
+ /*
|
|
+ *up to 26 bits long char
|
|
+ *encoded over 5 bytes.
|
|
+ *1111 10xx 10xx xxxx 10xx xxxx
|
|
+ *10xx xxxx 10xx xxxx
|
|
+ */
|
|
+ c = *a_in & 3;
|
|
+ nb_bytes_2_decode = 5;
|
|
+
|
|
+ } else if ((*a_in & 0xFE) == 0xFC) {
|
|
+ /*
|
|
+ *up to 31 bits long char
|
|
+ *encoded over 6 bytes:
|
|
+ *1111 110x 10xx xxxx 10xx xxxx
|
|
+ *10xx xxxx 10xx xxxx 10xx xxxx
|
|
+ */
|
|
+ c = *a_in & 1;
|
|
+ nb_bytes_2_decode = 6;
|
|
+
|
|
+ } else {
|
|
+ /*BAD ENCODING */
|
|
+ goto end;
|
|
+ }
|
|
+
|
|
+ if (nb_bytes_2_decode > a_in_len) {
|
|
+ status = CR_END_OF_INPUT_ERROR;
|
|
+ goto end;
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ *Go and decode the remaining byte(s)
|
|
+ *(if any) to get the current character.
|
|
+ */
|
|
+ for (in_index = 1; in_index < nb_bytes_2_decode; in_index++) {
|
|
+ /*byte pattern must be: 10xx xxxx */
|
|
+ if ((a_in[in_index] & 0xC0) != 0x80) {
|
|
+ goto end;
|
|
+ }
|
|
+
|
|
+ c = (c << 6) | (a_in[in_index] & 0x3F);
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ *The decoded ucs4 char is now
|
|
+ *in c.
|
|
+ */
|
|
+
|
|
+ /************************
|
|
+ *Some security tests
|
|
+ ***********************/
|
|
+
|
|
+ /*be sure c is a char */
|
|
+ if (c == 0xFFFF || c == 0xFFFE)
|
|
+ goto end;
|
|
+
|
|
+ /*be sure c is inferior to the max ucs4 char value */
|
|
+ if (c > 0x10FFFF)
|
|
+ goto end;
|
|
+
|
|
+ /*
|
|
+ *c must be less than UTF16 "lower surrogate begin"
|
|
+ *or higher than UTF16 "High surrogate end"
|
|
+ */
|
|
+ if (c >= 0xD800 && c <= 0xDFFF)
|
|
+ goto end;
|
|
+
|
|
+ /*Avoid characters that equals zero */
|
|
+ if (c == 0)
|
|
+ goto end;
|
|
+
|
|
+ *a_out = c;
|
|
+
|
|
+ end:
|
|
+ *a_consumed = nb_bytes_2_decode;
|
|
+
|
|
+ return status;
|
|
+}
|
|
+
|
|
+/**
|
|
+ *
|
|
+ */
|
|
+enum CRStatus
|
|
+cr_utils_utf8_str_len_as_ucs1 (const guchar * a_in_start,
|
|
+ const guchar * a_in_end, gulong * a_len)
|
|
+{
|
|
+ /*
|
|
+ *Note: this function can be made shorter
|
|
+ *but it considers all the cases of the utf8 encoding
|
|
+ *to ease further extensions ...
|
|
+ */
|
|
+
|
|
+ guchar *byte_ptr = NULL;
|
|
+ gint len = 0;
|
|
+
|
|
+ /*
|
|
+ *to store the final decoded
|
|
+ *unicode char
|
|
+ */
|
|
+ guint c = 0;
|
|
+
|
|
+ g_return_val_if_fail (a_in_start && a_in_end && a_len,
|
|
+ CR_BAD_PARAM_ERROR);
|
|
+ *a_len = 0;
|
|
+
|
|
+ for (byte_ptr = (guchar *) a_in_start;
|
|
+ byte_ptr <= a_in_end; byte_ptr++) {
|
|
+ gint nb_bytes_2_decode = 0;
|
|
+
|
|
+ if (*byte_ptr <= 0x7F) {
|
|
+ /*
|
|
+ *7 bits long char
|
|
+ *encoded over 1 byte:
|
|
+ * 0xxx xxxx
|
|
+ */
|
|
+ c = *byte_ptr;
|
|
+ nb_bytes_2_decode = 1;
|
|
+
|
|
+ } else if ((*byte_ptr & 0xE0) == 0xC0) {
|
|
+ /*
|
|
+ *up to 11 bits long char.
|
|
+ *encoded over 2 bytes:
|
|
+ *110x xxxx 10xx xxxx
|
|
+ */
|
|
+ c = *byte_ptr & 0x1F;
|
|
+ nb_bytes_2_decode = 2;
|
|
+
|
|
+ } else if ((*byte_ptr & 0xF0) == 0xE0) {
|
|
+ /*
|
|
+ *up to 16 bit long char
|
|
+ *encoded over 3 bytes:
|
|
+ *1110 xxxx 10xx xxxx 10xx xxxx
|
|
+ */
|
|
+ c = *byte_ptr & 0x0F;
|
|
+ nb_bytes_2_decode = 3;
|
|
+
|
|
+ } else if ((*byte_ptr & 0xF8) == 0xF0) {
|
|
+ /*
|
|
+ *up to 21 bits long char
|
|
+ *encoded over 4 bytes:
|
|
+ *1111 0xxx 10xx xxxx 10xx xxxx 10xx xxxx
|
|
+ */
|
|
+ c = *byte_ptr & 0x7;
|
|
+ nb_bytes_2_decode = 4;
|
|
+
|
|
+ } else if ((*byte_ptr & 0xFC) == 0xF8) {
|
|
+ /*
|
|
+ *up to 26 bits long char
|
|
+ *encoded over 5 bytes.
|
|
+ *1111 10xx 10xx xxxx 10xx xxxx
|
|
+ *10xx xxxx 10xx xxxx
|
|
+ */
|
|
+ c = *byte_ptr & 3;
|
|
+ nb_bytes_2_decode = 5;
|
|
+
|
|
+ } else if ((*byte_ptr & 0xFE) == 0xFC) {
|
|
+ /*
|
|
+ *up to 31 bits long char
|
|
+ *encoded over 6 bytes:
|
|
+ *1111 110x 10xx xxxx 10xx xxxx
|
|
+ *10xx xxxx 10xx xxxx 10xx xxxx
|
|
+ */
|
|
+ c = *byte_ptr & 1;
|
|
+ nb_bytes_2_decode = 6;
|
|
+
|
|
+ } else {
|
|
+ /*
|
|
+ *BAD ENCODING
|
|
+ */
|
|
+ return CR_ENCODING_ERROR;
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ *Go and decode the remaining byte(s)
|
|
+ *(if any) to get the current character.
|
|
+ */
|
|
+ for (; nb_bytes_2_decode > 1; nb_bytes_2_decode--) {
|
|
+ /*decode the next byte */
|
|
+ byte_ptr++;
|
|
+
|
|
+ /*byte pattern must be: 10xx xxxx */
|
|
+ if ((*byte_ptr & 0xC0) != 0x80) {
|
|
+ return CR_ENCODING_ERROR;
|
|
+ }
|
|
+
|
|
+ c = (c << 6) | (*byte_ptr & 0x3F);
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ *The decoded ucs4 char is now
|
|
+ *in c.
|
|
+ */
|
|
+
|
|
+ if (c <= 0xFF) { /*Add other conditions to support
|
|
+ *other char sets (ucs2, ucs3, ucs4).
|
|
+ */
|
|
+ len++;
|
|
+ } else {
|
|
+ /*the char is too long to fit
|
|
+ *into the supposed charset len.
|
|
+ */
|
|
+ return CR_ENCODING_ERROR;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ *a_len = len;
|
|
+
|
|
+ return CR_OK;
|
|
+}
|
|
+
|
|
+/**
|
|
+ *Converts an utf8 string into an ucs4 string.
|
|
+ *@param a_in the input string to convert.
|
|
+ *@param a_in_len in/out parameter. The length of the input
|
|
+ *string. After return, points to the actual number of bytes
|
|
+ *consumed. This can be usefull to debug the input stream in case
|
|
+ *of encoding error.
|
|
+ *@param a_out out parameter. Points to the output string. It is allocated
|
|
+ *by this function and must be freed by the caller.
|
|
+ *@param a_out_len out parameter. The length of the output string.
|
|
+ *@return CR_OK upon successfull completion, an error code otherwise.
|
|
+ *
|
|
+ */
|
|
+enum CRStatus
|
|
+cr_utils_utf8_str_to_ucs4 (const guchar * a_in,
|
|
+ gulong * a_in_len,
|
|
+ guint32 ** a_out, gulong * a_out_len)
|
|
+{
|
|
+ enum CRStatus status = CR_OK;
|
|
+
|
|
+ g_return_val_if_fail (a_in && a_in_len
|
|
+ && a_out && a_out_len, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ status = cr_utils_utf8_str_len_as_ucs4 (a_in,
|
|
+ &a_in[*a_in_len - 1],
|
|
+ a_out_len);
|
|
+
|
|
+ g_return_val_if_fail (status == CR_OK, status);
|
|
+
|
|
+ *a_out = g_malloc0 (*a_out_len * sizeof (guint32));
|
|
+
|
|
+ status = cr_utils_utf8_to_ucs4 (a_in, a_in_len, *a_out, a_out_len);
|
|
+
|
|
+ return status;
|
|
+}
|
|
+
|
|
+/**
|
|
+ *Converts an ucs4 buffer into an utf8 buffer.
|
|
+ *
|
|
+ *@param a_in the input ucs4 buffer to convert.
|
|
+ *@param a_in_len in/out parameter. The size of the
|
|
+ *input buffer to convert. After return, this parameter contains
|
|
+ *the actual number of characters consumed.
|
|
+ *@param a_out the output converted utf8 buffer. Must be allocated by
|
|
+ *the caller.
|
|
+ *@param a_out_len in/out parameter. The size of the output buffer.
|
|
+ *If this size is actually smaller than the real needed size, the function
|
|
+ *just converts what it can and returns a success status. After return,
|
|
+ *this param points to the actual number of bytes in the buffer.
|
|
+ *@return CR_OK upon successfull completion, an error code otherwise.
|
|
+ */
|
|
+enum CRStatus
|
|
+cr_utils_ucs4_to_utf8 (const guint32 * a_in,
|
|
+ gulong * a_in_len, guchar * a_out, gulong * a_out_len)
|
|
+{
|
|
+ gulong in_len = 0,
|
|
+ in_index = 0,
|
|
+ out_index = 0;
|
|
+ enum CRStatus status = CR_OK;
|
|
+
|
|
+ g_return_val_if_fail (a_in && a_in_len && a_out && a_out_len,
|
|
+ CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ if (*a_in_len < 1) {
|
|
+ status = CR_OK;
|
|
+ goto end;
|
|
+ }
|
|
+
|
|
+ in_len = *a_in_len;
|
|
+
|
|
+ for (in_index = 0; in_index < in_len; in_index++) {
|
|
+ /*
|
|
+ *FIXME: return whenever we encounter forbidden char values.
|
|
+ */
|
|
+
|
|
+ if (a_in[in_index] <= 0x7F) {
|
|
+ a_out[out_index] = a_in[in_index];
|
|
+ out_index++;
|
|
+ } else if (a_in[in_index] <= 0x7FF) {
|
|
+ a_out[out_index] = (0xC0 | (a_in[in_index] >> 6));
|
|
+ a_out[out_index + 1] =
|
|
+ (0x80 | (a_in[in_index] & 0x3F));
|
|
+ out_index += 2;
|
|
+ } else if (a_in[in_index] <= 0xFFFF) {
|
|
+ a_out[out_index] = (0xE0 | (a_in[in_index] >> 12));
|
|
+ a_out[out_index + 1] =
|
|
+ (0x80 | ((a_in[in_index] >> 6) & 0x3F));
|
|
+ a_out[out_index + 2] =
|
|
+ (0x80 | (a_in[in_index] & 0x3F));
|
|
+ out_index += 3;
|
|
+ } else if (a_in[in_index] <= 0x1FFFFF) {
|
|
+ a_out[out_index] = (0xF0 | (a_in[in_index] >> 18));
|
|
+ a_out[out_index + 1]
|
|
+ = (0x80 | ((a_in[in_index] >> 12) & 0x3F));
|
|
+ a_out[out_index + 2]
|
|
+ = (0x80 | ((a_in[in_index] >> 6) & 0x3F));
|
|
+ a_out[out_index + 3]
|
|
+ = (0x80 | (a_in[in_index] & 0x3F));
|
|
+ out_index += 4;
|
|
+ } else if (a_in[in_index] <= 0x3FFFFFF) {
|
|
+ a_out[out_index] = (0xF8 | (a_in[in_index] >> 24));
|
|
+ a_out[out_index + 1] =
|
|
+ (0x80 | (a_in[in_index] >> 18));
|
|
+ a_out[out_index + 2]
|
|
+ = (0x80 | ((a_in[in_index] >> 12) & 0x3F));
|
|
+ a_out[out_index + 3]
|
|
+ = (0x80 | ((a_in[in_index] >> 6) & 0x3F));
|
|
+ a_out[out_index + 4]
|
|
+ = (0x80 | (a_in[in_index] & 0x3F));
|
|
+ out_index += 5;
|
|
+ } else if (a_in[in_index] <= 0x7FFFFFFF) {
|
|
+ a_out[out_index] = (0xFC | (a_in[in_index] >> 30));
|
|
+ a_out[out_index + 1] =
|
|
+ (0x80 | (a_in[in_index] >> 24));
|
|
+ a_out[out_index + 2]
|
|
+ = (0x80 | ((a_in[in_index] >> 18) & 0x3F));
|
|
+ a_out[out_index + 3]
|
|
+ = (0x80 | ((a_in[in_index] >> 12) & 0x3F));
|
|
+ a_out[out_index + 4]
|
|
+ = (0x80 | ((a_in[in_index] >> 6) & 0x3F));
|
|
+ a_out[out_index + 4]
|
|
+ = (0x80 | (a_in[in_index] & 0x3F));
|
|
+ out_index += 6;
|
|
+ } else {
|
|
+ status = CR_ENCODING_ERROR;
|
|
+ goto end;
|
|
+ }
|
|
+ } /*end for */
|
|
+
|
|
+ end:
|
|
+ *a_in_len = in_index + 1;
|
|
+ *a_out_len = out_index + 1;
|
|
+
|
|
+ return status;
|
|
+}
|
|
+
|
|
+/**
|
|
+ *Converts an ucs4 string into an utf8 string.
|
|
+ *@param a_in the input string to convert.
|
|
+ *@param a_in_len in/out parameter. The length of the input
|
|
+ *string. After return, points to the actual number of characters
|
|
+ *consumed. This can be usefull to debug the input string in case
|
|
+ *of encoding error.
|
|
+ *@param a_out out parameter. Points to the output string. It is allocated
|
|
+ *by this function and must be freed by the caller.
|
|
+ *@param a_out_len out parameter. The length (in bytes) of the output string.
|
|
+ *@return CR_OK upon successfull completion, an error code otherwise.
|
|
+ */
|
|
+enum CRStatus
|
|
+cr_utils_ucs4_str_to_utf8 (const guint32 * a_in,
|
|
+ gulong * a_in_len,
|
|
+ guchar ** a_out, gulong * a_out_len)
|
|
+{
|
|
+ enum CRStatus status = CR_OK;
|
|
+
|
|
+ g_return_val_if_fail (a_in && a_in_len && a_out
|
|
+ && a_out_len, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ status = cr_utils_ucs4_str_len_as_utf8 (a_in,
|
|
+ &a_in[*a_out_len - 1],
|
|
+ a_out_len);
|
|
+
|
|
+ g_return_val_if_fail (status == CR_OK, status);
|
|
+
|
|
+ status = cr_utils_ucs4_to_utf8 (a_in, a_in_len, *a_out, a_out_len);
|
|
+
|
|
+ return status;
|
|
+}
|
|
+
|
|
+/**
|
|
+ *Converts an ucs1 buffer into an utf8 buffer.
|
|
+ *The caller must know the size of the resulting buffer and
|
|
+ *allocate it prior to calling this function.
|
|
+ *
|
|
+ *@param a_in the input ucs1 buffer.
|
|
+ *
|
|
+ *@param a_in_len in/out parameter. The length of the input buffer.
|
|
+ *After return, points to the number of bytes actually consumed even
|
|
+ *in case of encoding error.
|
|
+ *
|
|
+ *@param a_out out parameter. The output utf8 converted buffer.
|
|
+ *
|
|
+ *@param a_out_len in/out parameter. The size of the output buffer.
|
|
+ *If the output buffer size is shorter than the actual needed size,
|
|
+ *this function just convert what it can.
|
|
+ *
|
|
+ *@return CR_OK upon successfull completion, an error code otherwise.
|
|
+ *
|
|
+ */
|
|
+enum CRStatus
|
|
+cr_utils_ucs1_to_utf8 (const guchar * a_in,
|
|
+ gulong * a_in_len, guchar * a_out, gulong * a_out_len)
|
|
+{
|
|
+ gulong out_index = 0,
|
|
+ in_index = 0,
|
|
+ in_len = 0,
|
|
+ out_len = 0;
|
|
+ enum CRStatus status = CR_OK;
|
|
+
|
|
+ g_return_val_if_fail (a_in && a_in_len
|
|
+ && a_out_len,
|
|
+ CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ if (*a_in_len == 0) {
|
|
+ *a_out_len = 0 ;
|
|
+ return status;
|
|
+ }
|
|
+ g_return_val_if_fail (a_out, CR_BAD_PARAM_ERROR) ;
|
|
+
|
|
+ in_len = *a_in_len;
|
|
+ out_len = *a_out_len;
|
|
+
|
|
+ for (in_index = 0, out_index = 0;
|
|
+ (in_index < in_len) && (out_index < out_len); in_index++) {
|
|
+ /*
|
|
+ *FIXME: return whenever we encounter forbidden char values.
|
|
+ */
|
|
+
|
|
+ if (a_in[in_index] <= 0x7F) {
|
|
+ a_out[out_index] = a_in[in_index];
|
|
+ out_index++;
|
|
+ } else {
|
|
+ a_out[out_index] = (0xC0 | (a_in[in_index] >> 6));
|
|
+ a_out[out_index + 1] =
|
|
+ (0x80 | (a_in[in_index] & 0x3F));
|
|
+ out_index += 2;
|
|
+ }
|
|
+ } /*end for */
|
|
+
|
|
+ *a_in_len = in_index;
|
|
+ *a_out_len = out_index;
|
|
+
|
|
+ return status;
|
|
+}
|
|
+
|
|
+/**
|
|
+ *Converts an ucs1 string into an utf8 string.
|
|
+ *@param a_in_start the beginning of the input string to convert.
|
|
+ *@param a_in_end the end of the input string to convert.
|
|
+ *@param a_out out parameter. The converted string.
|
|
+ *@param a_out out parameter. The length of the converted string.
|
|
+ *@return CR_OK upon successfull completion, an error code otherwise.
|
|
+ *
|
|
+ */
|
|
+enum CRStatus
|
|
+cr_utils_ucs1_str_to_utf8 (const guchar * a_in,
|
|
+ gulong * a_in_len,
|
|
+ guchar ** a_out, gulong * a_out_len)
|
|
+{
|
|
+ gulong out_len = 0;
|
|
+ enum CRStatus status = CR_OK;
|
|
+
|
|
+ g_return_val_if_fail (a_in && a_in_len && a_out
|
|
+ && a_out_len, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ if (*a_in_len < 1) {
|
|
+ *a_out_len = 0;
|
|
+ *a_out = NULL;
|
|
+ return CR_OK;
|
|
+ }
|
|
+
|
|
+ status = cr_utils_ucs1_str_len_as_utf8 (a_in, &a_in[*a_in_len - 1],
|
|
+ &out_len);
|
|
+
|
|
+ g_return_val_if_fail (status == CR_OK, status);
|
|
+
|
|
+ *a_out = g_malloc0 (out_len);
|
|
+
|
|
+ status = cr_utils_ucs1_to_utf8 (a_in, a_in_len, *a_out, &out_len);
|
|
+
|
|
+ *a_out_len = out_len;
|
|
+
|
|
+ return status;
|
|
+}
|
|
+
|
|
+/**
|
|
+ *Converts an utf8 buffer into an ucs1 buffer.
|
|
+ *The caller must know the size of the resulting
|
|
+ *converted buffer, and allocated it prior to calling this
|
|
+ *function.
|
|
+ *
|
|
+ *@param a_in the input utf8 buffer to convert.
|
|
+ *
|
|
+ *@param a_in_len in/out parameter. The size of the input utf8 buffer.
|
|
+ *After return, points to the number of bytes consumed
|
|
+ *by the function even in case of encoding error.
|
|
+ *
|
|
+ *@param a_out out parameter. Points to the resulting buffer.
|
|
+ *Must be allocated by the caller. If the size of a_out is shorter
|
|
+ *than its required size, this function converts what it can and return
|
|
+ *a successfull status.
|
|
+ *
|
|
+ *@param a_out_len in/out parameter. The size of the output buffer.
|
|
+ *After return, points to the number of bytes consumed even in case of
|
|
+ *encoding error.
|
|
+ *
|
|
+ *@return CR_OK upon successfull completion, an error code otherwise.
|
|
+ */
|
|
+enum CRStatus
|
|
+cr_utils_utf8_to_ucs1 (const guchar * a_in,
|
|
+ gulong * a_in_len, guchar * a_out, gulong * a_out_len)
|
|
+{
|
|
+ gulong in_index = 0,
|
|
+ out_index = 0,
|
|
+ in_len = 0,
|
|
+ out_len = 0;
|
|
+ enum CRStatus status = CR_OK;
|
|
+
|
|
+ /*
|
|
+ *to store the final decoded
|
|
+ *unicode char
|
|
+ */
|
|
+ guint32 c = 0;
|
|
+
|
|
+ g_return_val_if_fail (a_in && a_in_len
|
|
+ && a_out && a_out_len, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ if (*a_in_len < 1) {
|
|
+ goto end;
|
|
+ }
|
|
+
|
|
+ in_len = *a_in_len;
|
|
+ out_len = *a_out_len;
|
|
+
|
|
+ for (in_index = 0, out_index = 0;
|
|
+ (in_index < in_len) && (out_index < out_len);
|
|
+ in_index++, out_index++) {
|
|
+ gint nb_bytes_2_decode = 0;
|
|
+
|
|
+ if (a_in[in_index] <= 0x7F) {
|
|
+ /*
|
|
+ *7 bits long char
|
|
+ *encoded over 1 byte:
|
|
+ * 0xxx xxxx
|
|
+ */
|
|
+ c = a_in[in_index];
|
|
+ nb_bytes_2_decode = 1;
|
|
+
|
|
+ } else if ((a_in[in_index] & 0xE0) == 0xC0) {
|
|
+ /*
|
|
+ *up to 11 bits long char.
|
|
+ *encoded over 2 bytes:
|
|
+ *110x xxxx 10xx xxxx
|
|
+ */
|
|
+ c = a_in[in_index] & 0x1F;
|
|
+ nb_bytes_2_decode = 2;
|
|
+
|
|
+ } else if ((a_in[in_index] & 0xF0) == 0xE0) {
|
|
+ /*
|
|
+ *up to 16 bit long char
|
|
+ *encoded over 3 bytes:
|
|
+ *1110 xxxx 10xx xxxx 10xx xxxx
|
|
+ */
|
|
+ c = a_in[in_index] & 0x0F;
|
|
+ nb_bytes_2_decode = 3;
|
|
+
|
|
+ } else if ((a_in[in_index] & 0xF8) == 0xF0) {
|
|
+ /*
|
|
+ *up to 21 bits long char
|
|
+ *encoded over 4 bytes:
|
|
+ *1111 0xxx 10xx xxxx 10xx xxxx 10xx xxxx
|
|
+ */
|
|
+ c = a_in[in_index] & 0x7;
|
|
+ nb_bytes_2_decode = 4;
|
|
+
|
|
+ } else if ((a_in[in_index] & 0xFC) == 0xF8) {
|
|
+ /*
|
|
+ *up to 26 bits long char
|
|
+ *encoded over 5 bytes.
|
|
+ *1111 10xx 10xx xxxx 10xx xxxx
|
|
+ *10xx xxxx 10xx xxxx
|
|
+ */
|
|
+ c = a_in[in_index] & 3;
|
|
+ nb_bytes_2_decode = 5;
|
|
+
|
|
+ } else if ((a_in[in_index] & 0xFE) == 0xFC) {
|
|
+ /*
|
|
+ *up to 31 bits long char
|
|
+ *encoded over 6 bytes:
|
|
+ *1111 110x 10xx xxxx 10xx xxxx
|
|
+ *10xx xxxx 10xx xxxx 10xx xxxx
|
|
+ */
|
|
+ c = a_in[in_index] & 1;
|
|
+ nb_bytes_2_decode = 6;
|
|
+
|
|
+ } else {
|
|
+ /*BAD ENCODING */
|
|
+ status = CR_ENCODING_ERROR;
|
|
+ goto end;
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ *Go and decode the remaining byte(s)
|
|
+ *(if any) to get the current character.
|
|
+ */
|
|
+ if (in_index + nb_bytes_2_decode - 1 >= in_len) {
|
|
+ goto end;
|
|
+ }
|
|
+
|
|
+ for (; nb_bytes_2_decode > 1; nb_bytes_2_decode--) {
|
|
+ /*decode the next byte */
|
|
+ in_index++;
|
|
+
|
|
+ /*byte pattern must be: 10xx xxxx */
|
|
+ if ((a_in[in_index] & 0xC0) != 0x80) {
|
|
+ status = CR_ENCODING_ERROR;
|
|
+ goto end;
|
|
+ }
|
|
+
|
|
+ c = (c << 6) | (a_in[in_index] & 0x3F);
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ *The decoded ucs4 char is now
|
|
+ *in c.
|
|
+ */
|
|
+
|
|
+ if (c > 0xFF) {
|
|
+ status = CR_ENCODING_ERROR;
|
|
+ goto end;
|
|
+ }
|
|
+
|
|
+ a_out[out_index] = c;
|
|
+ }
|
|
+
|
|
+ end:
|
|
+ *a_out_len = out_index;
|
|
+ *a_in_len = in_index;
|
|
+
|
|
+ return status;
|
|
+}
|
|
+
|
|
+/**
|
|
+ *Converts an utf8 buffer into an
|
|
+ *ucs1 buffer.
|
|
+ *@param a_in_start the start of the input buffer.
|
|
+ *@param a_in_end the end of the input buffer.
|
|
+ *@param a_out out parameter. The resulting converted ucs4 buffer.
|
|
+ *Must be freed by the caller.
|
|
+ *@param a_out_len out parameter. The length of the converted buffer.
|
|
+ *@return CR_OK upon successfull completion, an error code otherwise.
|
|
+ *Note that out parameters are valid if and only if this function
|
|
+ *returns CR_OK.
|
|
+ */
|
|
+enum CRStatus
|
|
+cr_utils_utf8_str_to_ucs1 (const guchar * a_in,
|
|
+ gulong * a_in_len,
|
|
+ guchar ** a_out, gulong * a_out_len)
|
|
+{
|
|
+ enum CRStatus status = CR_OK;
|
|
+
|
|
+ g_return_val_if_fail (a_in && a_in_len
|
|
+ && a_out && a_out_len, CR_BAD_PARAM_ERROR);
|
|
+
|
|
+ if (*a_in_len < 1) {
|
|
+ *a_out_len = 0;
|
|
+ *a_out = NULL;
|
|
+ return CR_OK;
|
|
+ }
|
|
+
|
|
+ status = cr_utils_utf8_str_len_as_ucs4 (a_in, &a_in[*a_in_len - 1],
|
|
+ a_out_len);
|
|
+
|
|
+ g_return_val_if_fail (status == CR_OK, status);
|
|
+
|
|
+ *a_out = g_malloc0 (*a_out_len * sizeof (guint32));
|
|
+
|
|
+ status = cr_utils_utf8_to_ucs1 (a_in, a_in_len, *a_out, a_out_len);
|
|
+ return status;
|
|
+}
|
|
+
|
|
+/*****************************************
|
|
+ *CSS basic types identification utilities
|
|
+ *****************************************/
|
|
+
|
|
+/**
|
|
+ *Returns TRUE if a_char is a white space as
|
|
+ *defined in the css spec in chap 4.1.1.
|
|
+ *
|
|
+ *white-space ::= ' '| \t|\r|\n|\f
|
|
+ *
|
|
+ *@param a_char the character to test.
|
|
+ *return TRUE if is a white space, false otherwise.
|
|
+ */
|
|
+gboolean
|
|
+cr_utils_is_white_space (guint32 a_char)
|
|
+{
|
|
+ switch (a_char) {
|
|
+ case ' ':
|
|
+ case '\t':
|
|
+ case '\r':
|
|
+ case '\n':
|
|
+ case '\f':
|
|
+ return TRUE;
|
|
+ break;
|
|
+ default:
|
|
+ return FALSE;
|
|
+ }
|
|
+}
|
|
+
|
|
+/**
|
|
+ *Returns true if the character is a newline
|
|
+ *as defined in the css spec in the chap 4.1.1.
|
|
+ *
|
|
+ *nl ::= \n|\r\n|\r|\f
|
|
+ *
|
|
+ *@param a_char the character to test.
|
|
+ *@return TRUE if the character is a newline, FALSE otherwise.
|
|
+ */
|
|
+gboolean
|
|
+cr_utils_is_newline (guint32 a_char)
|
|
+{
|
|
+ switch (a_char) {
|
|
+ case '\n':
|
|
+ case '\r':
|
|
+ case '\f':
|
|
+ return TRUE;
|
|
+ break;
|
|
+ default:
|
|
+ return FALSE;
|
|
+ }
|
|
+}
|
|
+
|
|
+/**
|
|
+ *returns TRUE if the char is part of an hexa num char:
|
|
+ *i.e hexa_char ::= [0-9A-F]
|
|
+ */
|
|
+gboolean
|
|
+cr_utils_is_hexa_char (guint32 a_char)
|
|
+{
|
|
+ if ((a_char >= '0' && a_char <= '9')
|
|
+ || (a_char >= 'A' && a_char <= 'F')) {
|
|
+ return TRUE;
|
|
+ }
|
|
+ return FALSE;
|
|
+}
|
|
+
|
|
+/**
|
|
+ *Returns true if the character is a nonascii
|
|
+ *character (as defined in the css spec chap 4.1.1):
|
|
+ *
|
|
+ *nonascii ::= [^\0-\177]
|
|
+ *
|
|
+ *@param a_char the character to test.
|
|
+ *@return TRUE if the character is a nonascii char,
|
|
+ *FALSE otherwise.
|
|
+ */
|
|
+gboolean
|
|
+cr_utils_is_nonascii (guint32 a_char)
|
|
+{
|
|
+ if (a_char <= 177) {
|
|
+ return FALSE;
|
|
+ }
|
|
+
|
|
+ return TRUE;
|
|
+}
|
|
+
|
|
+/**
|
|
+ *Dumps a character a_nb times on a file.
|
|
+ *@param a_char the char to dump
|
|
+ *@param a_fp the destination file pointer
|
|
+ *@param a_nb the number of times a_char is to be dumped.
|
|
+ */
|
|
+void
|
|
+cr_utils_dump_n_chars (guchar a_char, FILE * a_fp, glong a_nb)
|
|
+{
|
|
+ glong i = 0;
|
|
+
|
|
+ for (i = 0; i < a_nb; i++) {
|
|
+ fprintf (a_fp, "%c", a_char);
|
|
+ }
|
|
+}
|
|
+
|
|
+void
|
|
+cr_utils_dump_n_chars2 (guchar a_char, GString * a_string, glong a_nb)
|
|
+{
|
|
+ glong i = 0;
|
|
+
|
|
+ g_return_if_fail (a_string);
|
|
+
|
|
+ for (i = 0; i < a_nb; i++) {
|
|
+ g_string_append_printf (a_string, "%c", a_char);
|
|
+ }
|
|
+}
|
|
+
|
|
+/**
|
|
+ *Duplicates a list of GString instances.
|
|
+ *@return the duplicated list of GString instances or NULL if
|
|
+ *something bad happened.
|
|
+ *@param a_list_of_strings the list of strings to be duplicated.
|
|
+ */
|
|
+GList *
|
|
+cr_utils_dup_glist_of_string (GList const * a_list_of_strings)
|
|
+{
|
|
+ GList const *cur = NULL;
|
|
+ GList *result = NULL;
|
|
+
|
|
+ g_return_val_if_fail (a_list_of_strings, NULL);
|
|
+
|
|
+ for (cur = a_list_of_strings; cur; cur = cur->next) {
|
|
+ GString *str = NULL;
|
|
+
|
|
+ str = g_string_new_len (((GString *) cur->data)->str,
|
|
+ ((GString *) cur->data)->len);
|
|
+ if (str)
|
|
+ result = g_list_append (result, str);
|
|
+ }
|
|
+
|
|
+ return result;
|
|
+}
|
|
+
|
|
+/**
|
|
+ *Duplicate a GList where the GList::data is a CRString.
|
|
+ *@param a_list_of_strings the list to duplicate
|
|
+ *@return the duplicated list, or NULL if something bad
|
|
+ *happened.
|
|
+ */
|
|
+GList *
|
|
+cr_utils_dup_glist_of_cr_string (GList const * a_list_of_strings)
|
|
+{
|
|
+ GList const *cur = NULL;
|
|
+ GList *result = NULL;
|
|
+
|
|
+ g_return_val_if_fail (a_list_of_strings, NULL);
|
|
+
|
|
+ for (cur = a_list_of_strings; cur; cur = cur->next) {
|
|
+ CRString *str = NULL;
|
|
+
|
|
+ str = cr_string_dup ((CRString const *) cur->data) ;
|
|
+ if (str)
|
|
+ result = g_list_append (result, str);
|
|
+ }
|
|
+
|
|
+ return result;
|
|
+}
|
|
diff --git a/src/st/croco/cr-utils.h b/src/st/croco/cr-utils.h
|
|
new file mode 100644
|
|
index 000000000..54aa24973
|
|
--- /dev/null
|
|
+++ b/src/st/croco/cr-utils.h
|
|
@@ -0,0 +1,246 @@
|
|
+/* -*- 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
|
|
+ * Look at file COPYRIGHTS for copyright information
|
|
+ */
|
|
+
|
|
+#ifndef __CR_DEFS_H__
|
|
+#define __CR_DEFS_H__
|
|
+
|
|
+#include <stdio.h>
|
|
+#include <glib.h>
|
|
+#include "libcroco-config.h"
|
|
+
|
|
+G_BEGIN_DECLS
|
|
+
|
|
+/**
|
|
+ *@file
|
|
+ *The Croco library basic types definitions
|
|
+ *And global definitions.
|
|
+ */
|
|
+
|
|
+/**
|
|
+ *The status type returned
|
|
+ *by the methods of the croco library.
|
|
+ */
|
|
+enum CRStatus {
|
|
+ CR_OK,
|
|
+ CR_BAD_PARAM_ERROR,
|
|
+ CR_INSTANCIATION_FAILED_ERROR,
|
|
+ CR_UNKNOWN_TYPE_ERROR,
|
|
+ CR_UNKNOWN_PROP_ERROR,
|
|
+ CR_UNKNOWN_PROP_VAL_ERROR,
|
|
+ CR_UNEXPECTED_POSITION_SCHEME,
|
|
+ CR_START_OF_INPUT_ERROR,
|
|
+ CR_END_OF_INPUT_ERROR,
|
|
+ CR_OUTPUT_TOO_SHORT_ERROR,
|
|
+ CR_INPUT_TOO_SHORT_ERROR,
|
|
+ CR_OUT_OF_BOUNDS_ERROR,
|
|
+ CR_EMPTY_PARSER_INPUT_ERROR,
|
|
+ CR_ENCODING_ERROR,
|
|
+ CR_ENCODING_NOT_FOUND_ERROR,
|
|
+ CR_PARSING_ERROR,
|
|
+ CR_SYNTAX_ERROR,
|
|
+ CR_NO_ROOT_NODE_ERROR,
|
|
+ CR_NO_TOKEN,
|
|
+ CR_OUT_OF_MEMORY_ERROR,
|
|
+ CR_PSEUDO_CLASS_SEL_HANDLER_NOT_FOUND_ERROR,
|
|
+ CR_BAD_PSEUDO_CLASS_SEL_HANDLER_ERROR,
|
|
+ CR_ERROR,
|
|
+ CR_FILE_NOT_FOUND_ERROR,
|
|
+ CR_VALUE_NOT_FOUND_ERROR
|
|
+} ;
|
|
+
|
|
+/**
|
|
+ *Values used by
|
|
+ *cr_input_seek_position() ;
|
|
+ */
|
|
+enum CRSeekPos {
|
|
+ CR_SEEK_CUR,
|
|
+ CR_SEEK_BEGIN,
|
|
+ CR_SEEK_END
|
|
+} ;
|
|
+
|
|
+/**
|
|
+ *Encoding values.
|
|
+ */
|
|
+enum CREncoding
|
|
+{
|
|
+ CR_UCS_4 = 1/*Must be not NULL*/,
|
|
+ CR_UCS_1,
|
|
+ CR_ISO_8859_1,
|
|
+ CR_ASCII,
|
|
+ CR_UTF_8,
|
|
+ CR_UTF_16,
|
|
+ CR_AUTO/*should be the last one*/
|
|
+} ;
|
|
+
|
|
+
|
|
+
|
|
+
|
|
+#define CROCO_LOG_DOMAIN "LIBCROCO"
|
|
+
|
|
+#ifdef __GNUC__
|
|
+#define cr_utils_trace(a_log_level, a_msg) \
|
|
+g_log (CROCO_LOG_DOMAIN, \
|
|
+ G_LOG_LEVEL_CRITICAL, \
|
|
+ "file %s: line %d (%s): %s\n", \
|
|
+ __FILE__, \
|
|
+ __LINE__, \
|
|
+ __PRETTY_FUNCTION__, \
|
|
+ a_msg)
|
|
+#else /*__GNUC__*/
|
|
+
|
|
+#define cr_utils_trace(a_log_level, a_msg) \
|
|
+g_log (CROCO_LOG_DOMAIN, \
|
|
+ G_LOG_LEVEL_CRITICAL, \
|
|
+ "file %s: line %d: %s\n", \
|
|
+ __FILE__, \
|
|
+ __LINE__, \
|
|
+ a_msg)
|
|
+#endif
|
|
+
|
|
+/**
|
|
+ *Traces an info message.
|
|
+ *The file, line and enclosing function
|
|
+ *of the message will be automatically
|
|
+ *added to the message.
|
|
+ *@param a_msg the msg to trace.
|
|
+ */
|
|
+#define cr_utils_trace_info(a_msg) \
|
|
+cr_utils_trace (G_LOG_LEVEL_INFO, a_msg)
|
|
+
|
|
+/**
|
|
+ *Trace a debug message.
|
|
+ *The file, line and enclosing function
|
|
+ *of the message will be automatically
|
|
+ *added to the message.
|
|
+ *@param a_msg the msg to trace.
|
|
+ */
|
|
+#define cr_utils_trace_debug(a_msg) \
|
|
+cr_utils_trace (G_LOG_LEVEL_DEBUG, a_msg) ;
|
|
+
|
|
+
|
|
+/****************************
|
|
+ *Encoding transformations and
|
|
+ *encoding helpers
|
|
+ ****************************/
|
|
+
|
|
+enum CRStatus
|
|
+cr_utils_read_char_from_utf8_buf (const guchar * a_in, gulong a_in_len,
|
|
+ guint32 *a_out, gulong *a_consumed) ;
|
|
+
|
|
+enum CRStatus
|
|
+cr_utils_ucs1_to_utf8 (const guchar *a_in, gulong *a_in_len,
|
|
+ guchar *a_out, gulong *a_out_len) ;
|
|
+
|
|
+enum CRStatus
|
|
+cr_utils_utf8_to_ucs1 (const guchar * a_in, gulong * a_in_len,
|
|
+ guchar *a_out, gulong *a_out_len) ;
|
|
+
|
|
+enum CRStatus
|
|
+cr_utils_ucs4_to_utf8 (const guint32 *a_in, gulong *a_in_len,
|
|
+ guchar *a_out, gulong *a_out_len) ;
|
|
+
|
|
+enum CRStatus
|
|
+cr_utils_utf8_str_len_as_ucs4 (const guchar *a_in_start,
|
|
+ const guchar *a_in_end,
|
|
+ gulong *a_len) ;
|
|
+enum CRStatus
|
|
+cr_utils_ucs1_str_len_as_utf8 (const guchar *a_in_start,
|
|
+ const guchar *a_in_end,
|
|
+ gulong *a_len) ;
|
|
+enum CRStatus
|
|
+cr_utils_utf8_str_len_as_ucs1 (const guchar *a_in_start,
|
|
+ const guchar *a_in_end,
|
|
+ gulong *a_len) ;
|
|
+enum CRStatus
|
|
+cr_utils_ucs4_str_len_as_utf8 (const guint32 *a_in_start,
|
|
+ const guint32 *a_in_end,
|
|
+ gulong *a_len) ;
|
|
+
|
|
+enum CRStatus
|
|
+cr_utils_ucs1_str_to_utf8 (const guchar *a_in_start,
|
|
+ gulong *a_in_len,
|
|
+ guchar **a_out,
|
|
+ gulong *a_len) ;
|
|
+
|
|
+enum CRStatus
|
|
+cr_utils_utf8_str_to_ucs1 (const guchar * a_in_start,
|
|
+ gulong * a_in_len,
|
|
+ guchar **a_out,
|
|
+ gulong *a_out_len) ;
|
|
+
|
|
+enum CRStatus
|
|
+cr_utils_utf8_to_ucs4 (const guchar * a_in,
|
|
+ gulong * a_in_len,
|
|
+ guint32 *a_out, gulong *a_out_len) ;
|
|
+
|
|
+enum CRStatus
|
|
+cr_utils_ucs4_str_to_utf8 (const guint32 *a_in,
|
|
+ gulong *a_in_len,
|
|
+ guchar **a_out, gulong *a_out_len) ;
|
|
+
|
|
+enum CRStatus
|
|
+cr_utils_utf8_str_to_ucs4 (const guchar * a_in,
|
|
+ gulong *a_in_len,
|
|
+ guint32 **a_out,
|
|
+ gulong *a_out_len) ;
|
|
+
|
|
+
|
|
+/*****************************************
|
|
+ *CSS basic types identification utilities
|
|
+ *****************************************/
|
|
+
|
|
+gboolean
|
|
+cr_utils_is_newline (guint32 a_char) ;
|
|
+
|
|
+gboolean
|
|
+cr_utils_is_white_space (guint32 a_char) ;
|
|
+
|
|
+gboolean
|
|
+cr_utils_is_nonascii (guint32 a_char) ;
|
|
+
|
|
+gboolean
|
|
+cr_utils_is_hexa_char (guint32 a_char) ;
|
|
+
|
|
+
|
|
+/**********************************
|
|
+ *Miscellaneous utility functions
|
|
+ ***********************************/
|
|
+
|
|
+void
|
|
+cr_utils_dump_n_chars (guchar a_char,
|
|
+ FILE *a_fp,
|
|
+ glong a_nb) ;
|
|
+
|
|
+void
|
|
+cr_utils_dump_n_chars2 (guchar a_char,
|
|
+ GString *a_string,
|
|
+ glong a_nb) ;
|
|
+GList *
|
|
+cr_utils_dup_glist_of_string (GList const *a_list) ;
|
|
+
|
|
+GList *
|
|
+cr_utils_dup_glist_of_cr_string (GList const * a_list_of_strings) ;
|
|
+
|
|
+G_END_DECLS
|
|
+
|
|
+#endif /*__CR_DEFS_H__*/
|
|
diff --git a/src/st/croco/libcroco-config.h b/src/st/croco/libcroco-config.h
|
|
new file mode 100644
|
|
index 000000000..1ffb758ea
|
|
--- /dev/null
|
|
+++ b/src/st/croco/libcroco-config.h
|
|
@@ -0,0 +1,13 @@
|
|
+#ifndef LIBCROCO_VERSION_NUMBER
|
|
+#define LIBCROCO_VERSION_NUMBER 612
|
|
+#endif
|
|
+
|
|
+#ifndef LIBCROCO_VERSION
|
|
+#define LIBCROCO_VERSION "0.6.12"
|
|
+#endif
|
|
+
|
|
+#ifndef G_DISABLE_CHECKS
|
|
+#if 0
|
|
+#define G_DISABLE_CHECKS 0
|
|
+#endif
|
|
+#endif
|
|
diff --git a/src/st/croco/libcroco.h b/src/st/croco/libcroco.h
|
|
new file mode 100644
|
|
index 000000000..6187a7cb9
|
|
--- /dev/null
|
|
+++ b/src/st/croco/libcroco.h
|
|
@@ -0,0 +1,42 @@
|
|
+/*
|
|
+ * This file is part of The Croco Library
|
|
+ *
|
|
+ * Copyright (C) 2002-2003 Dodji Seketeli <dodji@seketeli.org>
|
|
+ *
|
|
+ * 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
|
|
+ */
|
|
+
|
|
+#ifndef __LIBCROCO_H__
|
|
+#define __LIBCROCO_H__
|
|
+
|
|
+#include "libcroco-config.h"
|
|
+
|
|
+#include "cr-utils.h"
|
|
+#include "cr-pseudo.h"
|
|
+#include "cr-term.h"
|
|
+#include "cr-attr-sel.h"
|
|
+#include "cr-simple-sel.h"
|
|
+#include "cr-selector.h"
|
|
+#include "cr-enc-handler.h"
|
|
+#include "cr-doc-handler.h"
|
|
+#include "cr-input.h"
|
|
+#include "cr-parser.h"
|
|
+#include "cr-statement.h"
|
|
+#include "cr-stylesheet.h"
|
|
+#include "cr-om-parser.h"
|
|
+#include "cr-prop-list.h"
|
|
+#include "cr-string.h"
|
|
+
|
|
+#endif /*__LIBCROCO_H__*/
|
|
diff --git a/src/st/meson.build b/src/st/meson.build
|
|
index 97ce6134d..c1994755b 100644
|
|
--- a/src/st/meson.build
|
|
+++ b/src/st/meson.build
|
|
@@ -1,3 +1,4 @@
|
|
+# please, keep this sorted alphabetically
|
|
st_headers = [
|
|
'st-adjustment.h',
|
|
'st-bin.h',
|
|
@@ -43,13 +44,68 @@ st_h = configure_file(
|
|
|
|
st_inc = include_directories('.', '..')
|
|
|
|
+# please, keep this sorted alphabetically
|
|
st_private_headers = [
|
|
+ 'croco/cr-additional-sel.h',
|
|
+ 'croco/cr-attr-sel.h',
|
|
+ 'croco/cr-cascade.h',
|
|
+ 'croco/cr-declaration.h',
|
|
+ 'croco/cr-doc-handler.h',
|
|
+ 'croco/cr-enc-handler.h',
|
|
+ 'croco/cr-fonts.h',
|
|
+ 'croco/cr-input.h',
|
|
+ 'croco/cr-num.h',
|
|
+ 'croco/cr-om-parser.h',
|
|
+ 'croco/cr-parser.h',
|
|
+ 'croco/cr-parsing-location.h',
|
|
+ 'croco/cr-prop-list.h',
|
|
+ 'croco/cr-pseudo.h',
|
|
+ 'croco/cr-rgb.h',
|
|
+ 'croco/cr-selector.h',
|
|
+ 'croco/cr-simple-sel.h',
|
|
+ 'croco/cr-statement.h',
|
|
+ 'croco/cr-string.h',
|
|
+ 'croco/cr-stylesheet.h',
|
|
+ 'croco/cr-term.h',
|
|
+ 'croco/cr-tknzr.h',
|
|
+ 'croco/cr-token.h',
|
|
+ 'croco/cr-utils.h',
|
|
+ 'croco/libcroco-config.h',
|
|
+ 'croco/libcroco.h',
|
|
'st-private.h',
|
|
'st-theme-private.h',
|
|
'st-theme-node-private.h',
|
|
'st-theme-node-transition.h'
|
|
]
|
|
|
|
+# please, keep this sorted alphabetically
|
|
+croco_sources = [
|
|
+ 'croco/cr-additional-sel.c',
|
|
+ 'croco/cr-attr-sel.c',
|
|
+ 'croco/cr-cascade.c',
|
|
+ 'croco/cr-declaration.c',
|
|
+ 'croco/cr-doc-handler.c',
|
|
+ 'croco/cr-enc-handler.c',
|
|
+ 'croco/cr-fonts.c',
|
|
+ 'croco/cr-input.c',
|
|
+ 'croco/cr-num.c',
|
|
+ 'croco/cr-om-parser.c',
|
|
+ 'croco/cr-parser.c',
|
|
+ 'croco/cr-parsing-location.c',
|
|
+ 'croco/cr-prop-list.c',
|
|
+ 'croco/cr-pseudo.c',
|
|
+ 'croco/cr-rgb.c',
|
|
+ 'croco/cr-selector.c',
|
|
+ 'croco/cr-simple-sel.c',
|
|
+ 'croco/cr-statement.c',
|
|
+ 'croco/cr-string.c',
|
|
+ 'croco/cr-stylesheet.c',
|
|
+ 'croco/cr-term.c',
|
|
+ 'croco/cr-tknzr.c',
|
|
+ 'croco/cr-token.c',
|
|
+ 'croco/cr-utils.c',
|
|
+]
|
|
+
|
|
# please, keep this sorted alphabetically
|
|
st_sources = [
|
|
'st-adjustment.c',
|
|
@@ -119,9 +175,9 @@ st_cflags = [
|
|
|
|
# Currently meson requires a shared library for building girs
|
|
libst = shared_library('st-1.0',
|
|
- sources: st_gir_sources + st_non_gir_sources,
|
|
+ sources: st_gir_sources + st_non_gir_sources + croco_sources,
|
|
c_args: st_cflags,
|
|
- dependencies: [clutter_dep, gtk_dep, croco_dep, x11_dep, m_dep],
|
|
+ dependencies: [clutter_dep, gtk_dep, x11_dep, m_dep],
|
|
install_rpath: mutter_typelibdir,
|
|
install_dir: pkglibdir,
|
|
install: true
|
|
@@ -134,7 +190,7 @@ libst_dep = declare_dependency(link_with: libst,
|
|
test_theme = executable('test-theme',
|
|
sources: 'test-theme.c',
|
|
c_args: st_cflags,
|
|
- dependencies: [clutter_dep, gtk_dep],
|
|
+ dependencies: [clutter_dep, gtk_dep, libxml_dep],
|
|
link_with: libst
|
|
)
|
|
|
|
diff --git a/src/st/st-theme-node-private.h b/src/st/st-theme-node-private.h
|
|
index 2e6b232f6..659bc37ba 100644
|
|
--- a/src/st/st-theme-node-private.h
|
|
+++ b/src/st/st-theme-node-private.h
|
|
@@ -25,7 +25,7 @@
|
|
#include <gdk/gdk.h>
|
|
|
|
#include "st-theme-node.h"
|
|
-#include <libcroco/libcroco.h>
|
|
+#include "croco/libcroco.h"
|
|
#include "st-types.h"
|
|
|
|
G_BEGIN_DECLS
|
|
diff --git a/src/st/st-theme-private.h b/src/st/st-theme-private.h
|
|
index 08f3a1864..2083a7c84 100644
|
|
--- a/src/st/st-theme-private.h
|
|
+++ b/src/st/st-theme-private.h
|
|
@@ -21,7 +21,7 @@
|
|
#ifndef __ST_THEME_PRIVATE_H__
|
|
#define __ST_THEME_PRIVATE_H__
|
|
|
|
-#include <libcroco/libcroco.h>
|
|
+#include "croco/libcroco.h"
|
|
#include "st-theme.h"
|
|
|
|
G_BEGIN_DECLS
|
|
--
|
|
2.23.0
|
|
|