ff4ff35918
Red Bear OS is a full fork. All sources must be available from git clone with zero network access. Removed gitignore rules that excluded fetched source trees under recipes/*/source/, local/recipes/kde/*/source/, local/recipes/qt/*/source/, and vendor source trees. Build artifacts (target/, build/, source.tar, *.o, *.so) remain excluded. 127291 files added — kernel, relibc, base, bootloader, pkgar, all KDE/Qt frameworks, mesa, wayland, DRM drivers, and every other recipe source.
317 lines
7.9 KiB
C
317 lines
7.9 KiB
C
/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
|
|
|
|
/* libcroco - Library for parsing and applying CSS
|
|
* Copyright (C) 2006-2019 Free Software Foundation, Inc.
|
|
*
|
|
* This file is not part of the GNU gettext program, but is used with
|
|
* GNU gettext.
|
|
*
|
|
* The original copyright notice is as follows:
|
|
*/
|
|
|
|
/*
|
|
* This file is part of The Croco Library
|
|
*
|
|
* Copyright (C) 2003-2004 Dodji Seketeli. All Rights Reserved.
|
|
*
|
|
* 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 <config.h>
|
|
#include <string.h>
|
|
#include "cr-selector.h"
|
|
#include "cr-parser.h"
|
|
|
|
/**
|
|
* cr_selector_new:
|
|
*
|
|
*@a_simple_sel: the initial simple selector list
|
|
*of the current instance of #CRSelector.
|
|
*
|
|
*Creates a new instance of #CRSelector.
|
|
*
|
|
*Returns the newly built instance of #CRSelector, or
|
|
*NULL in case of failure.
|
|
*/
|
|
CRSelector *
|
|
cr_selector_new (CRSimpleSel * a_simple_sel)
|
|
{
|
|
CRSelector *result = NULL;
|
|
|
|
result = g_try_malloc (sizeof (CRSelector));
|
|
if (!result) {
|
|
cr_utils_trace_info ("Out of memory");
|
|
return NULL;
|
|
}
|
|
memset (result, 0, sizeof (CRSelector));
|
|
result->simple_sel = a_simple_sel;
|
|
return result;
|
|
}
|
|
|
|
CRSelector *
|
|
cr_selector_parse_from_buf (const guchar * a_char_buf, enum CREncoding a_enc)
|
|
{
|
|
CRParser *parser = NULL;
|
|
|
|
g_return_val_if_fail (a_char_buf, NULL);
|
|
|
|
parser = cr_parser_new_from_buf ((guchar*)a_char_buf, strlen ((const char *) a_char_buf),
|
|
a_enc, FALSE);
|
|
g_return_val_if_fail (parser, NULL);
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/**
|
|
* cr_selector_append:
|
|
*
|
|
*@a_this: the current instance of #CRSelector.
|
|
*@a_new: the instance of #CRSelector to be appended.
|
|
*
|
|
*Appends a new instance of #CRSelector to the current selector list.
|
|
*
|
|
*Returns the new list.
|
|
*/
|
|
CRSelector *
|
|
cr_selector_append (CRSelector * a_this, CRSelector * a_new)
|
|
{
|
|
CRSelector *cur = NULL;
|
|
|
|
if (!a_this) {
|
|
return a_new;
|
|
}
|
|
|
|
/*walk forward the list headed by a_this to get the list tail */
|
|
for (cur = a_this; cur && cur->next; cur = cur->next) ;
|
|
|
|
cur->next = a_new;
|
|
a_new->prev = cur;
|
|
|
|
return a_this;
|
|
}
|
|
|
|
/**
|
|
* cr_selector_prepend:
|
|
*
|
|
*@a_this: the current instance of #CRSelector list.
|
|
*@a_new: the instance of #CRSelector.
|
|
*
|
|
*Prepends an element to the #CRSelector list.
|
|
*
|
|
*Returns the new list.
|
|
*/
|
|
CRSelector *
|
|
cr_selector_prepend (CRSelector * a_this, CRSelector * a_new)
|
|
{
|
|
CRSelector *cur = NULL;
|
|
|
|
a_new->next = a_this;
|
|
a_this->prev = a_new;
|
|
|
|
for (cur = a_new; cur && cur->prev; cur = cur->prev) ;
|
|
|
|
return cur;
|
|
}
|
|
|
|
/**
|
|
* cr_selector_append_simple_sel:
|
|
*
|
|
*@a_this: the current instance of #CRSelector.
|
|
*@a_simple_sel: the simple selector to append.
|
|
*
|
|
*append a simple selector to the current #CRSelector list.
|
|
*
|
|
*Returns the new list or NULL in case of failure.
|
|
*/
|
|
CRSelector *
|
|
cr_selector_append_simple_sel (CRSelector * a_this,
|
|
CRSimpleSel * a_simple_sel)
|
|
{
|
|
CRSelector *selector = NULL;
|
|
|
|
selector = cr_selector_new (a_simple_sel);
|
|
g_return_val_if_fail (selector, NULL);
|
|
|
|
return cr_selector_append (a_this, selector);
|
|
}
|
|
|
|
guchar *
|
|
cr_selector_to_string (CRSelector const * a_this)
|
|
{
|
|
guchar *result = NULL;
|
|
GString *str_buf = NULL;
|
|
|
|
str_buf = g_string_new (NULL);
|
|
g_return_val_if_fail (str_buf, NULL);
|
|
|
|
if (a_this) {
|
|
CRSelector const *cur = NULL;
|
|
|
|
for (cur = a_this; cur; cur = cur->next) {
|
|
if (cur->simple_sel) {
|
|
guchar *tmp_str = NULL;
|
|
|
|
tmp_str = cr_simple_sel_to_string
|
|
(cur->simple_sel);
|
|
|
|
if (tmp_str) {
|
|
if (cur->prev)
|
|
g_string_append (str_buf,
|
|
", ");
|
|
|
|
g_string_append (str_buf, (const gchar *) tmp_str);
|
|
|
|
g_free (tmp_str);
|
|
tmp_str = NULL;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (str_buf) {
|
|
result = (guchar *) str_buf->str;
|
|
g_string_free (str_buf, FALSE);
|
|
str_buf = NULL;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* cr_selector_dump:
|
|
*
|
|
*@a_this: the current instance of #CRSelector.
|
|
*@a_fp: the destination file.
|
|
*
|
|
*Serializes the current instance of #CRSelector to a file.
|
|
*/
|
|
void
|
|
cr_selector_dump (CRSelector const * a_this, FILE * a_fp)
|
|
{
|
|
guchar *tmp_buf = NULL;
|
|
|
|
if (a_this) {
|
|
tmp_buf = cr_selector_to_string (a_this);
|
|
if (tmp_buf) {
|
|
fprintf (a_fp, "%s", tmp_buf);
|
|
g_free (tmp_buf);
|
|
tmp_buf = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* cr_selector_ref:
|
|
*
|
|
*@a_this: the current instance of #CRSelector.
|
|
*
|
|
*Increments the ref count of the current instance
|
|
*of #CRSelector.
|
|
*/
|
|
void
|
|
cr_selector_ref (CRSelector * a_this)
|
|
{
|
|
g_return_if_fail (a_this);
|
|
|
|
a_this->ref_count++;
|
|
}
|
|
|
|
/**
|
|
* cr_selector_unref:
|
|
*
|
|
*@a_this: the current instance of #CRSelector.
|
|
*
|
|
*Decrements the ref count of the current instance of
|
|
*#CRSelector.
|
|
*If the ref count reaches zero, the current instance of
|
|
*#CRSelector is destroyed.
|
|
*
|
|
*Returns TRUE if this function destroyed the current instance
|
|
*of #CRSelector, FALSE otherwise.
|
|
*/
|
|
gboolean
|
|
cr_selector_unref (CRSelector * a_this)
|
|
{
|
|
g_return_val_if_fail (a_this, FALSE);
|
|
|
|
if (a_this->ref_count) {
|
|
a_this->ref_count--;
|
|
}
|
|
|
|
if (a_this->ref_count == 0) {
|
|
cr_selector_destroy (a_this);
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
/**
|
|
* cr_selector_destroy:
|
|
*
|
|
*@a_this: the current instance of #CRSelector.
|
|
*
|
|
*Destroys the selector list.
|
|
*/
|
|
void
|
|
cr_selector_destroy (CRSelector * a_this)
|
|
{
|
|
CRSelector *cur = NULL;
|
|
|
|
g_return_if_fail (a_this);
|
|
|
|
/*
|
|
*go and get the list tail. In the same time, free
|
|
*all the simple selectors contained in the list.
|
|
*/
|
|
for (cur = a_this; cur && cur->next; cur = cur->next) {
|
|
if (cur->simple_sel) {
|
|
cr_simple_sel_destroy (cur->simple_sel);
|
|
cur->simple_sel = NULL;
|
|
}
|
|
}
|
|
|
|
if (cur) {
|
|
if (cur->simple_sel) {
|
|
cr_simple_sel_destroy (cur->simple_sel);
|
|
cur->simple_sel = NULL;
|
|
}
|
|
}
|
|
|
|
/*in case the list has only one element */
|
|
if (cur && !cur->prev) {
|
|
g_free (cur);
|
|
return;
|
|
}
|
|
|
|
/*walk backward the list and free each "next element" */
|
|
for (cur = cur->prev; cur && cur->prev; cur = cur->prev) {
|
|
if (cur->next) {
|
|
g_free (cur->next);
|
|
cur->next = NULL;
|
|
}
|
|
}
|
|
|
|
if (!cur)
|
|
return;
|
|
|
|
if (cur->next) {
|
|
g_free (cur->next);
|
|
cur->next = NULL;
|
|
}
|
|
|
|
g_free (cur);
|
|
}
|