diff --git a/0001-Include-the-libcroco-sources-directly-under-src-st-c.patch b/0001-Include-the-libcroco-sources-directly-under-src-st-c.patch deleted file mode 100644 index 2c7e2cf794f9292f52a5d19321f51db42fa98e40..0000000000000000000000000000000000000000 --- a/0001-Include-the-libcroco-sources-directly-under-src-st-c.patch +++ /dev/null @@ -1,25201 +0,0 @@ -From 47758d16ff0acd9edbd8ff6eb3922e59fb14f8bb Mon Sep 17 00:00:00 2001 -From: Federico Mena Quintero -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 -+#include -+#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 -+#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 -+#include -+#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 -+ * -+ * 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 -+#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 -+#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 -+#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 -+#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 -+#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 -+ * -+ * 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 -+ -+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 -+ * -+ * 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 -+ -+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 -+#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 -+#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 -+#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 -+#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 -+ * -+ * 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_ (...) ; -+ *where 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_ (...) ; -+ *Then css core grammar related parsing function will be called: -+ *cr_parser_parse__core (...) ; -+ * -+ *If a production is defined only by the css core grammar, then -+ *it will be named: -+ *cr_parser_parse__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 -+#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 -+#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 -+#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 -+#include -+#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 -+#include -+#include -+#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 -+#include -+#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 -+#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 -+#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 -+#include -+#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 -+#include -+#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 -+#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 -+#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 -+#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 -+#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 -+#include -+#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 -+#include -+#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 -+#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 -+#include -+#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 -+ * -+ * 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 - - #include "st-theme-node.h" --#include -+#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 -+#include "croco/libcroco.h" - #include "st-theme.h" - - G_BEGIN_DECLS --- -2.23.0 - diff --git a/0001-endSessionDialog-Immediately-add-buttons-to-the-dial.patch b/0001-endSessionDialog-Immediately-add-buttons-to-the-dial.patch deleted file mode 100644 index 3d00b4058fd3f2857035f09a8517e809c59edbcd..0000000000000000000000000000000000000000 --- a/0001-endSessionDialog-Immediately-add-buttons-to-the-dial.patch +++ /dev/null @@ -1,56 +0,0 @@ -From 68b038ba1ee10cb957eec56fec435e3cfeffd20d Mon Sep 17 00:00:00 2001 -From: Hans de Goede -Date: Wed, 15 Aug 2018 14:26:19 +0200 -Subject: [PATCH 1/2] endSessionDialog: Immediately add buttons to the dialog - -Immediately add buttons to the dialog instead of first building an -array of button-info structs. - -This is a preparation patch for adding support changing the "Reboot" -button into a "Boot Options" button when Alt is pressed. ---- - js/ui/endSessionDialog.js | 17 +++++++++-------- - 1 file changed, 9 insertions(+), 8 deletions(-) - -diff --git a/js/ui/endSessionDialog.js b/js/ui/endSessionDialog.js -index 4804333d4..5657cbffd 100644 ---- a/js/ui/endSessionDialog.js -+++ b/js/ui/endSessionDialog.js -@@ -437,25 +437,26 @@ var EndSessionDialog = new Lang.Class({ - }, - - _updateButtons() { -- let dialogContent = DialogContent[this._type]; -- let buttons = [{ action: this.cancel.bind(this), -+ this.clearButtons(); -+ -+ this.addButton({ action: this.cancel.bind(this), - label: _("Cancel"), -- key: Clutter.Escape }]; -+ key: Clutter.Escape }); - -+ let dialogContent = DialogContent[this._type]; - for (let i = 0; i < dialogContent.confirmButtons.length; i++) { - let signal = dialogContent.confirmButtons[i].signal; - let label = dialogContent.confirmButtons[i].label; -- buttons.push({ action: () => { -+ let button = this.addButton( -+ { action: () => { - this.close(true); - let signalId = this.connect('closed', () => { - this.disconnect(signalId); - this._confirm(signal); - }); -- }, -- label: label }); -+ }, -+ label: label }); - } -- -- this.setButtons(buttons); - }, - - close(skipSignal) { --- -2.19.0 - diff --git a/0001-keyboardManager-Avoid-idempotent-calls-to-meta_backe.patch b/0001-keyboardManager-Avoid-idempotent-calls-to-meta_backe.patch deleted file mode 100644 index 16d6306d8fd7f11991dc50db726377eb05a7e294..0000000000000000000000000000000000000000 --- a/0001-keyboardManager-Avoid-idempotent-calls-to-meta_backe.patch +++ /dev/null @@ -1,68 +0,0 @@ -From ccc59673827f9e36b7374fcf03de94d1b1513550 Mon Sep 17 00:00:00 2001 -From: Carlos Garnacho -Date: Mon, 22 Oct 2018 22:06:36 +0000 -Subject: [PATCH] keyboardManager: Avoid idempotent calls to - meta_backend_set_keymap() - -But still try to apply the keymap whenever the input sources changed. This -is a different approach to gnome-shell#240 that still avoid redundant -changes to the current keymap, but actually trigger one when input sources -are added. - -https://bugzilla.redhat.com/show_bug.cgi?id=1637418 - -Closes: https://gitlab.gnome.org/GNOME/gnome-shell/issues/691 - - -(cherry picked from commit b405ed64427a9d518d1714df678d04ad11267e15) ---- - js/misc/keyboardManager.js | 14 +++++++++----- - 1 file changed, 9 insertions(+), 5 deletions(-) - -diff --git a/js/misc/keyboardManager.js b/js/misc/keyboardManager.js -index ae59f0014..f4001f130 100644 ---- a/js/misc/keyboardManager.js -+++ b/js/misc/keyboardManager.js -@@ -52,11 +52,20 @@ var KeyboardManager = new Lang.Class({ - this._current = null; - this._localeLayoutInfo = this._getLocaleLayout(); - this._layoutInfos = {}; -+ this._currentKeymap = null; - }, - - _applyLayoutGroup(group) { - let options = this._buildOptionsString(); - let [layouts, variants] = this._buildGroupStrings(group); -+ -+ if (this._currentKeymap && -+ this._currentKeymap.layouts == layouts && -+ this._currentKeymap.variants == variants && -+ this._currentKeymap.options == options) -+ return; -+ -+ this._currentKeymap = {layouts, variants, options}; - Meta.get_backend().set_keymap(layouts, variants, options); - }, - -@@ -89,8 +98,6 @@ var KeyboardManager = new Lang.Class({ - }, - - setUserLayouts(ids) { -- let currentId = this._current ? this._current.id : null; -- let currentGroupIndex = this._current ? this._current.groupIndex : null; - this._current = null; - this._layoutInfos = {}; - -@@ -117,9 +124,6 @@ var KeyboardManager = new Lang.Class({ - info.group = group; - info.groupIndex = groupIndex; - -- if (currentId == id && currentGroupIndex == groupIndex) -- this._current = info; -- - i += 1; - } - }, --- -2.19.1 - diff --git a/0002-endSessionDialog-Support-rebooting-into-the-bootload.patch b/0002-endSessionDialog-Support-rebooting-into-the-bootload.patch deleted file mode 100644 index 4634ea916d50bcbf589ddd0a3f30ad55d0ea29bd..0000000000000000000000000000000000000000 --- a/0002-endSessionDialog-Support-rebooting-into-the-bootload.patch +++ /dev/null @@ -1,115 +0,0 @@ -From 345278af9b7139d12e393d6b18abfe055172dedd Mon Sep 17 00:00:00 2001 -From: Hans de Goede -Date: Wed, 15 Aug 2018 15:03:56 +0200 -Subject: [PATCH 2/2] endSessionDialog: Support rebooting into the bootloader - menu aka ("Boot Options") - -This implements the "Alt" behavior for the "Reboot" button as outlined in -the design here: https://wiki.gnome.org/Design/OS/BootOptions - -This causes the endSessionDialog to send a ConfirmedRebootToBootOptions signal -to gnome-session instead of the normal ConfirmedReboot signal, actually -telling the boot-loader that it should show its menu the next boot is left -up to gnome-session. - -Note I've tried implementing this with the AltSwitcher class from -js/ui/status/system.js first, but that puts the button in a St.Bin() -which causes the button to think it is the only button on the dialog -and makes it have rounded corners on both of its bottom corners. ---- - js/ui/endSessionDialog.js | 50 +++++++++++++++++++++++++++++++++++++++ - 1 file changed, 50 insertions(+) - -diff --git a/js/ui/endSessionDialog.js b/js/ui/endSessionDialog.js -index 5657cbffd..bfc64a7d6 100644 ---- a/js/ui/endSessionDialog.js -+++ b/js/ui/endSessionDialog.js -@@ -271,6 +271,9 @@ var EndSessionDialog = new Lang.Class({ - this._totalSecondsToStayOpen = 0; - this._applications = []; - this._sessions = []; -+ this._capturedEventId = 0; -+ this._rebootButton = null; -+ this._rebootButtonAlt = null; - - this.connect('destroy', - this._onDestroy.bind(this)); -@@ -436,6 +439,26 @@ var EndSessionDialog = new Lang.Class({ - this._sessionHeader.visible = hasSessions; - }, - -+ _onCapturedEvent(actor, event) { -+ let altEnabled = false; -+ -+ let type = event.type(); -+ if (type != Clutter.EventType.KEY_PRESS && type != Clutter.EventType.KEY_RELEASE) -+ return Clutter.EVENT_PROPAGATE; -+ -+ let key = event.get_key_symbol(); -+ if (key != Clutter.KEY_Alt_L && key != Clutter.KEY_Alt_R) -+ return Clutter.EVENT_PROPAGATE; -+ -+ if (type == Clutter.EventType.KEY_PRESS) -+ altEnabled = true; -+ -+ this._rebootButton.visible = !altEnabled; -+ this._rebootButtonAlt.visible = altEnabled; -+ -+ return Clutter.EVENT_PROPAGATE; -+ }, -+ - _updateButtons() { - this.clearButtons(); - -@@ -456,7 +479,32 @@ var EndSessionDialog = new Lang.Class({ - }); - }, - label: label }); -+ -+ // Add Alt "Boot Options" option to the Reboot button -+ if (signal == 'ConfirmedReboot') { -+ this._rebootButton = button; -+ this._rebootButtonAlt = this.addButton( -+ { action: () => { -+ this.close(true); -+ let signalId = this.connect('closed', () => { -+ this.disconnect(signalId); -+ this._confirm('ConfirmedRebootToBootOptions'); -+ }); -+ }, -+ label: C_("button", "Boot Options") }); -+ this._rebootButtonAlt.visible = false; -+ this._capturedEventId = global.stage.connect('captured-event', this._onCapturedEvent.bind(this)); -+ } -+ } -+ }, -+ -+ _stopAltCapture() { -+ if (this._capturedEventId > 0) { -+ global.stage.disconnect(this._capturedEventId); -+ this._capturedEventId = 0; - } -+ this._rebootButton = null; -+ this._rebootButtonAlt = null; - }, - - close(skipSignal) { -@@ -468,6 +516,7 @@ var EndSessionDialog = new Lang.Class({ - - cancel() { - this._stopTimer(); -+ this._stopAltCapture(); - this._dbusImpl.emit_signal('Canceled', null); - this.close(); - }, -@@ -476,6 +525,7 @@ var EndSessionDialog = new Lang.Class({ - let callback = () => { - this._fadeOutDialog(); - this._stopTimer(); -+ this._stopAltCapture(); - this._dbusImpl.emit_signal(signal, null); - }; - --- -2.19.0 - diff --git a/CVE-2020-17489-pre1.patch b/CVE-2020-17489-pre1.patch deleted file mode 100644 index 1dc76b90695480e86fb830008cb9d8d9da0ff13e..0000000000000000000000000000000000000000 --- a/CVE-2020-17489-pre1.patch +++ /dev/null @@ -1,265 +0,0 @@ -From e2f0647091b2475f78c0a52c0acef5f1be4d52d9 Mon Sep 17 00:00:00 2001 -From: rpm-build -Date: Tue, 30 Mar 2021 14:42:11 +0800 -Subject: [PATCH] cleanup: Use arrow functions for tweener callbacks - -While it is legal to use method syntax for the function properties -here, arrow notation is less unexpected and allows us to drop the -separate scope properties. - -https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/608 - ---- - js/gdm/authPrompt.js | 3 +-- - js/gdm/loginDialog.js | 16 ++++++---------- - js/ui/dnd.js | 5 ++--- - js/ui/messageList.js | 3 +-- - js/ui/panel.js | 8 +++----- - js/ui/popupMenu.js | 12 ++++-------- - js/ui/screenShield.js | 15 ++++++--------- - js/ui/workspaceSwitcherPopup.js | 3 +-- - js/ui/workspaceThumbnail.js | 5 ++--- - 9 files changed, 26 insertions(+), 44 deletions(-) - -diff --git a/js/gdm/authPrompt.js b/js/gdm/authPrompt.js -index a0a4a21..a6a0374 100644 ---- a/js/gdm/authPrompt.js -+++ b/js/gdm/authPrompt.js -@@ -302,8 +302,7 @@ var AuthPrompt = new Lang.Class({ - time: DEFAULT_BUTTON_WELL_ANIMATION_TIME, - delay: DEFAULT_BUTTON_WELL_ANIMATION_DELAY, - transition: 'linear', -- onCompleteScope: this, -- onComplete() { -+ onComplete: () => { - if (wasSpinner) { - if (this._spinner) - this._spinner.stop(); -diff --git a/js/gdm/loginDialog.js b/js/gdm/loginDialog.js -index bf79677..0e0001f 100644 ---- a/js/gdm/loginDialog.js -+++ b/js/gdm/loginDialog.js -@@ -926,7 +926,7 @@ var LoginDialog = new Lang.Class({ - { opacity: 255, - time: _FADE_ANIMATION_TIME, - transition: 'easeOutQuad', -- onUpdate() { -+ onUpdate: () => { - let children = Main.layoutManager.uiGroup.get_children(); - - for (let i = 0; i < children.length; i++) { -@@ -934,12 +934,10 @@ var LoginDialog = new Lang.Class({ - children[i].opacity = this.actor.opacity; - } - }, -- onUpdateScope: this, -- onComplete() { -+ onComplete: () => { - if (this._authPrompt.verificationStatus != AuthPrompt.AuthPromptStatus.NOT_VERIFYING) - this._authPrompt.reset(); -- }, -- onCompleteScope: this }); -+ } }); - }, - - _gotGreeterSessionProxy(proxy) { -@@ -956,7 +954,7 @@ var LoginDialog = new Lang.Class({ - { opacity: 0, - time: _FADE_ANIMATION_TIME, - transition: 'easeOutQuad', -- onUpdate() { -+ onUpdate: () => { - let children = Main.layoutManager.uiGroup.get_children(); - - for (let i = 0; i < children.length; i++) { -@@ -964,11 +962,9 @@ var LoginDialog = new Lang.Class({ - children[i].opacity = this.actor.opacity; - } - }, -- onUpdateScope: this, -- onComplete() { -+ onComplete: () => { - this._greeter.call_start_session_when_ready_sync(serviceName, true, null); -- }, -- onCompleteScope: this }); -+ } }); - }, - - _onSessionOpened(client, serviceName) { -diff --git a/js/ui/dnd.js b/js/ui/dnd.js -index 8483e89..83778e0 100644 ---- a/js/ui/dnd.js -+++ b/js/ui/dnd.js -@@ -385,14 +385,13 @@ var _Draggable = new Lang.Class({ - scale_y: scale * origScale, - time: SCALE_ANIMATION_TIME, - transition: 'easeOutQuad', -- onUpdate() { -+ onUpdate: () => { - let currentScale = this._dragActor.scale_x / origScale; - this._dragOffsetX = currentScale * origDragOffsetX; - this._dragOffsetY = currentScale * origDragOffsetY; - this._dragActor.set_position(this._dragX + this._dragOffsetX, - this._dragY + this._dragOffsetY); -- }, -- onUpdateScope: this }); -+ } }); - } - } - }, -diff --git a/js/ui/messageList.js b/js/ui/messageList.js -index 547135a..91670ba 100644 ---- a/js/ui/messageList.js -+++ b/js/ui/messageList.js -@@ -483,8 +483,7 @@ var Message = new Lang.Class({ - { scale_y: 0, - time: MessageTray.ANIMATION_TIME, - transition: 'easeOutQuad', -- onCompleteScope: this, -- onComplete() { -+ onComplete: () => { - this._actionBin.hide(); - this.expanded = false; - }}); -diff --git a/js/ui/panel.js b/js/ui/panel.js -index 3726b84..318ca52 100644 ---- a/js/ui/panel.js -+++ b/js/ui/panel.js -@@ -174,10 +174,9 @@ var AppMenuButton = new Lang.Class({ - { opacity: 0, - time: Overview.ANIMATION_TIME, - transition: 'easeOutQuad', -- onComplete() { -+ onComplete: () => { - this.actor.hide(); -- }, -- onCompleteScope: this }); -+ } }); - }, - - _onStyleChanged(actor) { -@@ -219,8 +218,7 @@ var AppMenuButton = new Lang.Class({ - { opacity: 0, - time: SPINNER_ANIMATION_TIME, - transition: "easeOutQuad", -- onCompleteScope: this, -- onComplete() { -+ onComplete: () => { - this._spinner.stop(); - this._spinner.actor.opacity = 255; - this._spinner.actor.hide(); -diff --git a/js/ui/popupMenu.js b/js/ui/popupMenu.js -index f449d6e..3d92a1a 100644 ---- a/js/ui/popupMenu.js -+++ b/js/ui/popupMenu.js -@@ -1004,12 +1004,10 @@ var PopupSubMenu = new Lang.Class({ - { _arrowRotation: targetAngle, - height: naturalHeight, - time: 0.25, -- onUpdateScope: this, -- onUpdate() { -+ onUpdate: () => { - this._arrow.rotation_angle_z = this.actor._arrowRotation; - }, -- onCompleteScope: this, -- onComplete() { -+ onComplete: () => { - this.actor.set_height(-1); - } - }); -@@ -1037,12 +1035,10 @@ var PopupSubMenu = new Lang.Class({ - { _arrowRotation: 0, - height: 0, - time: 0.25, -- onUpdateScope: this, -- onUpdate() { -+ onUpdate: () => { - this._arrow.rotation_angle_z = this.actor._arrowRotation; - }, -- onCompleteScope: this, -- onComplete() { -+ onComplete: () => { - this.actor.hide(); - this.actor.set_height(-1); - }, -diff --git a/js/ui/screenShield.js b/js/ui/screenShield.js -index dee290b..72d1317 100644 ---- a/js/ui/screenShield.js -+++ b/js/ui/screenShield.js -@@ -265,11 +265,10 @@ var NotificationsBox = new Lang.Class({ - { height: natHeight, - transition: 'easeOutQuad', - time: 0.25, -- onComplete() { -+ onComplete: () => { - this._scrollView.vscrollbar_policy = Gtk.PolicyType.AUTOMATIC; - widget.set_height(-1); -- }, -- onCompleteScope: this -+ } - }); - - this._updateVisibility(); -@@ -795,11 +794,10 @@ var ScreenShield = new Lang.Class({ - { y: 0, - time: time, - transition: 'easeInQuad', -- onComplete() { -+ onComplete: () => { - this._lockScreenGroup.fixed_position_set = false; - this._lockScreenState = MessageTray.State.SHOWN; -- }, -- onCompleteScope: this, -+ } - }); - - this._maybeCancelDialog(); -@@ -1020,11 +1018,10 @@ var ScreenShield = new Lang.Class({ - { y: 0, - time: MANUAL_FADE_TIME, - transition: 'easeOutQuad', -- onComplete() { -+ onComplete: () => { - this._lockScreenShown({ fadeToBlack: fadeToBlack, - animateFade: true }); -- }, -- onCompleteScope: this -+ } - }); - } else { - this._lockScreenGroup.fixed_position_set = false; -diff --git a/js/ui/workspaceSwitcherPopup.js b/js/ui/workspaceSwitcherPopup.js -index 351a907..49caabc 100644 ---- a/js/ui/workspaceSwitcherPopup.js -+++ b/js/ui/workspaceSwitcherPopup.js -@@ -159,8 +159,7 @@ var WorkspaceSwitcherPopup = new Lang.Class({ - Tweener.addTween(this._container, { opacity: 0.0, - time: ANIMATION_TIME, - transition: 'easeOutQuad', -- onComplete() { this.destroy(); }, -- onCompleteScope: this -+ onComplete: () => this.destroy() - }); - return GLib.SOURCE_REMOVE; - }, -diff --git a/js/ui/workspaceThumbnail.js b/js/ui/workspaceThumbnail.js -index 76a7416..dc1a749 100644 ---- a/js/ui/workspaceThumbnail.js -+++ b/js/ui/workspaceThumbnail.js -@@ -1347,11 +1347,10 @@ var ThumbnailsBox = new Lang.Class({ - { indicatorY: thumbnail.actor.allocation.y1, - time: WorkspacesView.WORKSPACE_SWITCH_TIME, - transition: 'easeOutQuad', -- onComplete() { -+ onComplete: () => { - this._animatingIndicator = false; - this._queueUpdateStates(); -- }, -- onCompleteScope: this -+ } - }); - } - }); --- -2.23.0 - diff --git a/CVE-2020-17489-pre2.patch b/CVE-2020-17489-pre2.patch deleted file mode 100644 index 96688a6dc943d49e4c76967f113c1b1d94dce6dc..0000000000000000000000000000000000000000 --- a/CVE-2020-17489-pre2.patch +++ /dev/null @@ -1,81 +0,0 @@ -From 7e4e3c19d010b8204f89703706c605a97153a60a Mon Sep 17 00:00:00 2001 -From: rpm-build -Date: Tue, 30 Mar 2021 14:56:46 +0800 -Subject: [PATCH] loginDialog: Use GObject bindings over onUpdate handler - -Instead of iterating over all actors each frame and sync'ing their -opacities, we can set up bindings once before the animation. - -https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/654 ---- - js/gdm/loginDialog.js | 30 ++++++++++++++---------------- - 1 file changed, 14 insertions(+), 16 deletions(-) - -diff --git a/js/gdm/loginDialog.js b/js/gdm/loginDialog.js -index faecff8..29954f7 100644 ---- a/js/gdm/loginDialog.js -+++ b/js/gdm/loginDialog.js -@@ -918,25 +918,29 @@ var LoginDialog = new Lang.Class({ - this._showPrompt(); - }, - -+ _bindOpacity() { -+ this._bindings = Main.layoutManager.uiGroup.get_children() -+ .filter(c => c != Main.layoutManager.screenShieldGroup) -+ .map(c => this.bind_property('opacity', c, 'opacity', 0)); -+ }, -+ -+ _unbindOpacity() { -+ this._bindings.forEach(b => b.unbind()); -+ }, -+ - _loginScreenSessionActivated() { - if (this.actor.opacity == 255 && this._authPrompt.verificationStatus == AuthPrompt.AuthPromptStatus.NOT_VERIFYING) - return; - -+ this._bindOpacity(); - Tweener.addTween(this.actor, - { opacity: 255, - time: _FADE_ANIMATION_TIME, - transition: 'easeOutQuad', -- onUpdate: () => { -- let children = Main.layoutManager.uiGroup.get_children(); -- -- for (let i = 0; i < children.length; i++) { -- if (children[i] != Main.layoutManager.screenShieldGroup) -- children[i].opacity = this.actor.opacity; -- } -- }, - onComplete: () => { - if (this._authPrompt.verificationStatus != AuthPrompt.AuthPromptStatus.NOT_VERIFYING) - this._authPrompt.reset(); -+ this._unbindOpacity(); - } }); - }, - -@@ -950,20 +954,14 @@ var LoginDialog = new Lang.Class({ - }, - - _startSession(serviceName) { -+ this._bindOpacity(); - Tweener.addTween(this.actor, - { opacity: 0, - time: _FADE_ANIMATION_TIME, - transition: 'easeOutQuad', -- onUpdate: () => { -- let children = Main.layoutManager.uiGroup.get_children(); -- -- for (let i = 0; i < children.length; i++) { -- if (children[i] != Main.layoutManager.screenShieldGroup) -- children[i].opacity = this.actor.opacity; -- } -- }, - onComplete: () => { - this._greeter.call_start_session_when_ready_sync(serviceName, true, null); -+ this._unbindOpacity(); - } }); - }, - --- -2.23.0 - diff --git a/CVE-2020-17489.patch b/CVE-2020-17489.patch deleted file mode 100644 index 4239128283a94a50ef1ce10967d5188e310fcbe8..0000000000000000000000000000000000000000 --- a/CVE-2020-17489.patch +++ /dev/null @@ -1,44 +0,0 @@ -From b0d6742bcdba59991fbf0b31c6c670db7939cfa7 Mon Sep 17 00:00:00 2001 -From: rpm-build -Date: Tue, 30 Mar 2021 15:35:52 +0800 -Subject: [PATCH] cleanup: Port GObject classes to JS6 classes - -GJS added API for defining GObject classes with ES6 class syntax -last cycle, use it to port the remaining Lang.Class classes to -the new syntax. - -https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/361 - ---- - js/gdm/loginDialog.js | 9 ++++----- - 1 file changed, 4 insertions(+), 5 deletions(-) - -diff --git a/js/gdm/loginDialog.js b/js/gdm/loginDialog.js -index 29954f7..2f89140 100644 ---- a/js/gdm/loginDialog.js -+++ b/js/gdm/loginDialog.js -@@ -931,17 +931,16 @@ var LoginDialog = new Lang.Class({ - _loginScreenSessionActivated() { - if (this.actor.opacity == 255 && this._authPrompt.verificationStatus == AuthPrompt.AuthPromptStatus.NOT_VERIFYING) - return; -+ if (this._authPrompt.verificationStatus !== AuthPrompt.AuthPromptStatus.NOT_VERIFYING) -+ this._authPrompt.reset(); - - this._bindOpacity(); - Tweener.addTween(this.actor, - { opacity: 255, - time: _FADE_ANIMATION_TIME, - transition: 'easeOutQuad', -- onComplete: () => { -- if (this._authPrompt.verificationStatus != AuthPrompt.AuthPromptStatus.NOT_VERIFYING) -- this._authPrompt.reset(); -- this._unbindOpacity(); -- } }); -+ onComplete: () => this._unbindOpacity(), -+ }); - }, - - _gotGreeterSessionProxy(proxy) { --- -2.23.0 - diff --git a/gnome-shell-3.30.1.tar.xz b/gnome-shell-3.30.1.tar.xz deleted file mode 100644 index 39c159ea2ce923073962f961754ff7ada654c491..0000000000000000000000000000000000000000 Binary files a/gnome-shell-3.30.1.tar.xz and /dev/null differ diff --git a/gnome-shell-3.38.4.tar.xz b/gnome-shell-3.38.4.tar.xz new file mode 100644 index 0000000000000000000000000000000000000000..7239a262b3ca5036b4b7cb7b392ff215243e5497 Binary files /dev/null and b/gnome-shell-3.38.4.tar.xz differ diff --git a/gnome-shell-favourite-apps-firefox.patch b/gnome-shell-favourite-apps-firefox.patch index 56c498b8a84169616e8be429e06c1b69942ec792..6ce8d90a1c8b67d29de1c1265a3bfe40a9029338 100644 --- a/gnome-shell-favourite-apps-firefox.patch +++ b/gnome-shell-favourite-apps-firefox.patch @@ -1,21 +1,38 @@ ---- gnome-shell-3.13.90/data/org.gnome.shell.gschema.xml.in.firefox 2014-08-20 20:28:07.601133033 +0200 -+++ gnome-shell-3.13.90/data/org.gnome.shell.gschema.xml.in 2014-08-20 20:28:41.741503518 +0200 -@@ -31,7 +31,7 @@ +From ecbdc8596190dd0b2686cbe75790ed01708bd2a2 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Wed, 17 Sep 2014 07:11:12 +0200 +Subject: [PATCH] Replace Web with Firefox in default favorites + +--- + data/org.gnome.shell.gschema.xml.in | 2 +- + js/ui/appFavorites.js | 1 + + 2 files changed, 2 insertions(+), 1 deletion(-) + +diff --git a/data/org.gnome.shell.gschema.xml.in b/data/org.gnome.shell.gschema.xml.in +index 49d38d766..1433292e4 100644 +--- a/data/org.gnome.shell.gschema.xml.in ++++ b/data/org.gnome.shell.gschema.xml.in +@@ -50,7 +50,7 @@ -- [ 'epiphany.desktop', 'evolution.desktop', 'rhythmbox.desktop', 'shotwell.desktop', 'org.gnome.Nautilus.desktop', 'org.gnome.Software.desktop' ] -+ [ 'firefox.desktop', 'evolution.desktop', 'rhythmbox.desktop', 'shotwell.desktop', 'org.gnome.Nautilus.desktop', 'org.gnome.Software.desktop' ] +- [ 'org.gnome.Epiphany.desktop', 'org.gnome.Geary.desktop', 'org.gnome.Calendar.desktop', 'org.gnome.Music.desktop', 'org.gnome.Photos.desktop', 'org.gnome.Nautilus.desktop', 'org.gnome.Software.desktop' ] ++ [ 'firefox.desktop', 'org.gnome.Calendar.desktop', 'rhythmbox.desktop', 'org.gnome.Photos.desktop', 'org.gnome.Nautilus.desktop', 'org.gnome.Software.desktop' ] List of desktop file IDs for favorite applications The applications corresponding to these identifiers +diff --git a/js/ui/appFavorites.js b/js/ui/appFavorites.js +index 3308dd6b3..87c008704 100644 --- a/js/ui/appFavorites.js +++ b/js/ui/appFavorites.js -@@ -31,6 +31,7 @@ const RENAMED_DESKTOP_IDS = { - 'gnotravex.desktop': 'gnome-tetravex.desktop', - 'gnotski.desktop': 'gnome-klotski.desktop', - 'gtali.desktop': 'tali.desktop', +@@ -50,6 +50,7 @@ const RENAMED_DESKTOP_IDS = { + 'gnotski.desktop': 'org.gnome.Klotski.desktop', + 'gtali.desktop': 'org.gnome.Tali.desktop', + 'iagno.desktop': 'org.gnome.Reversi.desktop', + 'mozilla-firefox.desktop': 'firefox.desktop', 'nautilus.desktop': 'org.gnome.Nautilus.desktop', - 'polari.desktop': 'org.gnome.Polari.desktop', - 'totem.desktop': 'org.gnome.Totem.desktop', + 'org.gnome.gnome-2048.desktop': 'org.gnome.TwentyFortyEight.desktop', + 'org.gnome.taquin.desktop': 'org.gnome.Taquin.desktop', +-- +2.24.1 + diff --git a/gnome-shell.spec b/gnome-shell.spec index 59adb52b2a8acf789d67dbb319e23d51a3fadabb..fa1b5f8c01c9111c973339e9afd36eda00fbaafc 100644 --- a/gnome-shell.spec +++ b/gnome-shell.spec @@ -1,36 +1,33 @@ Name: gnome-shell -Version: 3.30.1 -Release: 7 +Version: 3.38.4 +Release: 1 Summary: Core user interface functions for the GNOME 3 desktop Group: User Interface/Desktops License: GPLv2+ URL: https://wiki.gnome.org/Projects/GnomeShell -Source0: http://download.gnome.org/sources/gnome-shell/3.30/%{name}-%{version}.tar.xz +Source0: http://download.gnome.org/sources/gnome-shell/3.38/%{name}-%{version}.tar.xz Patch1: gnome-shell-favourite-apps-firefox.patch -Patch2: 0001-endSessionDialog-Immediately-add-buttons-to-the-dial.patch -Patch3: 0002-endSessionDialog-Support-rebooting-into-the-bootload.patch -Patch4: 0001-keyboardManager-Avoid-idempotent-calls-to-meta_backe.patch -Patch5: 0001-Include-the-libcroco-sources-directly-under-src-st-c.patch -Patch6: CVE-2020-17489-pre1.patch -Patch7: CVE-2020-17489-pre2.patch -Patch8: CVE-2020-17489.patch BuildRequires: meson git ibus-devel chrpath dbus-glib-devel desktop-file-utils BuildRequires: evolution-data-server-devel gcr-devel gjs-devel glib2-devel BuildRequires: gobject-introspection json-glib-devel upower-devel mesa-libGL-devel BuildRequires: NetworkManager-libnm-devel polkit-devel startup-notification-devel BuildRequires: sassc gstreamer1-devel gtk3-devel gettext libcanberra-devel -BuildRequires: python3-devel libXfixes-devel librsvg2-devel +BuildRequires: python3-devel libXfixes-devel librsvg2-devel asciidoc BuildRequires: mutter-devel pulseaudio-libs-devel control-center gtk-doc +BuildRequires: bash-completion gnome-autoar-devel gnome-desktop3-devel +BuildRequires: mesa-libEGL-devel systemd-devel python3 +BuildRequires: pkgconfig(libpipewire-0.3) >= 0.3.0 gnome-bluetooth-libs-devel Requires: gnome-desktop3 gobject-introspection gjs gtk3 libnma librsvg2 -Requires: json-glib mozilla-filesystem mutter upower polkit glib2 -Requires: gsettings-desktop-schemas gstreamer1 at-spi2-atk -Requires: ibus accountsservice-libs gdm control-center python3 -Requires: switcheroo-control geoclue2 libgweather bolt +Requires: json-glib mozilla-filesystem mutter upower polkit glib2 gdm-libs +Requires: gsettings-desktop-schemas gstreamer1 at-spi2-atk gnome-bluetooth +Requires: ibus accountsservice-libs gdm control-center python3 gnome-settings-daemon +Requires: switcheroo-control geoclue2 libgweather bolt gnome-session-xsession +Requires: geoclue2-libs pipewire-gstreamer -Provides: desktop-notification-daemon +Provides: desktop-notification-daemon PolicyKit-authentication-agent %description The GNOME Shell redefines user interactions with the GNOME desktop. In particular, @@ -55,7 +52,7 @@ Help files for %{name} %build -%meson +%meson -Dextensions_app=false %meson_build @@ -67,7 +64,6 @@ Help files for %{name} %check desktop-file-validate %{buildroot}%{_datadir}/applications/org.gnome.Shell.desktop -desktop-file-validate %{buildroot}%{_datadir}/applications/gnome-shell-extension-prefs.desktop desktop-file-validate %{buildroot}%{_datadir}/applications/evolution-calendar.desktop @@ -82,48 +78,60 @@ glib-compile-schemas --allow-any-name %{_datadir}/glib-2.0/schemas &> /dev/null %files -f %{name}.lang %license COPYING %doc README.md -%{_bindir}/gnome-shell -%{_bindir}/gnome-shell-extension-tool -%{_bindir}/gnome-shell-perf-tool -%{_bindir}/gnome-shell-extension-prefs +%{_bindir}/gnome-* %{_datadir}/glib-2.0/schemas/*.xml %{_datadir}/glib-2.0/schemas/00_org.gnome.shell.gschema.override +%{_datadir}/applications/org.gnome.Shell.Extensions.desktop %{_datadir}/applications/org.gnome.Shell.desktop -%{_datadir}/applications/gnome-shell-extension-prefs.desktop %{_datadir}/applications/evolution-calendar.desktop %{_datadir}/applications/org.gnome.Shell.PortalHelper.desktop %{_datadir}/gnome-control-center/keybindings/50-gnome-shell-system.xml %{_datadir}/gnome-shell/ + %{_datadir}/dbus-1/services/org.gnome.Shell.CalendarServer.service +%{_datadir}/dbus-1/services/org.gnome.Shell.Extensions.service %{_datadir}/dbus-1/services/org.gnome.Shell.HotplugSniffer.service +%{_datadir}/dbus-1/services/org.gnome.Shell.Notifications.service %{_datadir}/dbus-1/services/org.gnome.Shell.PortalHelper.service +%{_datadir}/dbus-1/services/org.gnome.Shell.Screencast.service %{_datadir}/dbus-1/interfaces/org.gnome.Shell.Extensions.xml +%{_datadir}/dbus-1/interfaces/org.gnome.Shell.Introspect.xml %{_datadir}/dbus-1/interfaces/org.gnome.Shell.PadOsd.xml %{_datadir}/dbus-1/interfaces/org.gnome.Shell.Screencast.xml %{_datadir}/dbus-1/interfaces/org.gnome.Shell.Screenshot.xml %{_datadir}/dbus-1/interfaces/org.gnome.ShellSearchProvider.xml %{_datadir}/dbus-1/interfaces/org.gnome.ShellSearchProvider2.xml -%{_userunitdir}/gnome-shell.service -%{_userunitdir}/gnome-shell-wayland.target -%{_userunitdir}/gnome-shell-x11.target + +%{_userunitdir}/org.gnome.Shell-disable-extensions.service +%{_userunitdir}/org.gnome.Shell.target +%{_userunitdir}/org.gnome.Shell@wayland.service +%{_userunitdir}/org.gnome.Shell@x11.service %{_sysconfdir}/xdg/autostart/gnome-shell-overrides-migration.desktop + %dir %{_datadir}/xdg-desktop-portal/portals/ %{_datadir}/xdg-desktop-portal/portals/gnome-shell.portal +%{_datadir}/bash-completion/completions/gnome-extensions +%{_datadir}/icons/hicolor/scalable/apps/org.gnome.Shell.Extensions.svg +%{_datadir}/icons/hicolor/symbolic/apps/org.gnome.Shell.Extensions-symbolic.svg %{_libdir}/gnome-shell/ -%{_libdir}/mozilla/plugins/*.so %{_libexecdir}/gnome-shell-calendar-server %{_libexecdir}/gnome-shell-perf-helper %{_libexecdir}/gnome-shell-hotplug-sniffer %{_libexecdir}/gnome-shell-portal-helper %{_libexecdir}/gnome-shell-overrides-migration.sh -%dir %{_datadir}/GConf -%dir %{_datadir}/GConf/gsettings -%{_datadir}/GConf/gsettings/gnome-shell-overrides.convert +%{_datadir}/GConf/* %files help %{_mandir}/man1/%{name}.1.gz +%{_mandir}/man1/gnome-extensions.1.gz %changelog +* Mon May 31 2021 weijin deng - 3.38.4-1 +- Upgrade to 3.38.4 +- Update Version, Release, Source0, BuildRequires, Requires +- Delete patches which existed in current version, modify one patch +- Update stage 'build', 'check', 'files' + * Tue Mar 30 2021 wangyue - 3.30.1-7 - fix CVE-2020-17489