css: Rewrite the parser
Instead of relying on GScanner and its idea of syntax, code up a parser that obeys the CSS spec. This also has the great side effect of reporting correct line numbers and positions. Also included is a reorganization of the returned error values. Instead of error values describing what type of syntax error was returned, the code just returns SYNTAX_ERROR. Other messages exist for when actual values don't work or when errors shouldn't be fatal due to backwards compatibility.
This commit is contained in:
@ -386,6 +386,7 @@ gtk_private_h_sources = \
|
||||
gtkbuilderprivate.h \
|
||||
gtkbuttonprivate.h \
|
||||
gtkcellareaboxcontextprivate.h \
|
||||
gtkcssparserprivate.h \
|
||||
gtkcssproviderprivate.h \
|
||||
gtkcssstringfuncsprivate.h \
|
||||
gtkcustompaperunixdialog.h \
|
||||
@ -512,6 +513,7 @@ gtk_base_c_sources = \
|
||||
gtkcombobox.c \
|
||||
gtkcomboboxtext.c \
|
||||
gtkcontainer.c \
|
||||
gtkcssparser.c \
|
||||
gtkcssprovider.c \
|
||||
gtkcssstringfuncs.c \
|
||||
gtkdialog.c \
|
||||
|
||||
938
gtk/gtkcssparser.c
Normal file
938
gtk/gtkcssparser.c
Normal file
@ -0,0 +1,938 @@
|
||||
/* GTK - The GIMP Toolkit
|
||||
* Copyright (C) 2011 Benjamin Otte <otte@gnome.org>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "gtkcssparserprivate.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
/* just for the errors, yay! */
|
||||
#include "gtkcssprovider.h"
|
||||
|
||||
#define NEWLINE_CHARS "\r\n"
|
||||
#define WHITESPACE_CHARS "\f \t"
|
||||
#define NMSTART "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
|
||||
#define NMCHAR NMSTART "01234567890-_"
|
||||
#define URLCHAR NMCHAR "!#$%&*~"
|
||||
|
||||
#define GTK_IS_CSS_PARSER(parser) ((parser) != NULL)
|
||||
|
||||
struct _GtkCssParser
|
||||
{
|
||||
const char *data;
|
||||
GtkCssParserErrorFunc error_func;
|
||||
gpointer user_data;
|
||||
|
||||
const char *line_start;
|
||||
guint line;
|
||||
};
|
||||
|
||||
GtkCssParser *
|
||||
_gtk_css_parser_new (const char *data,
|
||||
GtkCssParserErrorFunc error_func,
|
||||
gpointer user_data)
|
||||
{
|
||||
GtkCssParser *parser;
|
||||
|
||||
g_return_val_if_fail (data != NULL, NULL);
|
||||
|
||||
parser = g_slice_new0 (GtkCssParser);
|
||||
|
||||
parser->data = data;
|
||||
parser->error_func = error_func;
|
||||
parser->user_data = user_data;
|
||||
|
||||
parser->line_start = data;
|
||||
parser->line = 1;
|
||||
|
||||
return parser;
|
||||
}
|
||||
|
||||
void
|
||||
_gtk_css_parser_free (GtkCssParser *parser)
|
||||
{
|
||||
g_return_if_fail (GTK_IS_CSS_PARSER (parser));
|
||||
|
||||
g_slice_free (GtkCssParser, parser);
|
||||
}
|
||||
|
||||
gboolean
|
||||
_gtk_css_parser_is_eof (GtkCssParser *parser)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_CSS_PARSER (parser), TRUE);
|
||||
|
||||
return *parser->data == 0;
|
||||
}
|
||||
|
||||
gboolean
|
||||
_gtk_css_parser_begins_with (GtkCssParser *parser,
|
||||
char c)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_CSS_PARSER (parser), TRUE);
|
||||
|
||||
return *parser->data == c;
|
||||
}
|
||||
|
||||
guint
|
||||
_gtk_css_parser_get_line (GtkCssParser *parser)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_CSS_PARSER (parser), 1);
|
||||
|
||||
return parser->line;
|
||||
}
|
||||
|
||||
guint
|
||||
_gtk_css_parser_get_position (GtkCssParser *parser)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_CSS_PARSER (parser), 1);
|
||||
|
||||
return parser->data - parser->line_start;
|
||||
}
|
||||
|
||||
void
|
||||
_gtk_css_parser_error (GtkCssParser *parser,
|
||||
const char *format,
|
||||
...)
|
||||
{
|
||||
GError *error;
|
||||
|
||||
va_list args;
|
||||
|
||||
va_start (args, format);
|
||||
error = g_error_new_valist (GTK_CSS_PROVIDER_ERROR,
|
||||
GTK_CSS_PROVIDER_ERROR_SYNTAX,
|
||||
format, args);
|
||||
va_end (args);
|
||||
|
||||
parser->error_func (parser, error, parser->user_data);
|
||||
|
||||
g_error_free (error);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_css_parser_new_line (GtkCssParser *parser)
|
||||
{
|
||||
gboolean result = FALSE;
|
||||
|
||||
if (*parser->data == '\r')
|
||||
{
|
||||
result = TRUE;
|
||||
parser->data++;
|
||||
}
|
||||
if (*parser->data == '\n')
|
||||
{
|
||||
result = TRUE;
|
||||
parser->data++;
|
||||
}
|
||||
|
||||
if (result)
|
||||
{
|
||||
parser->line++;
|
||||
parser->line_start = parser->data;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_css_parser_skip_comment (GtkCssParser *parser)
|
||||
{
|
||||
if (parser->data[0] != '/' ||
|
||||
parser->data[1] != '*')
|
||||
return FALSE;
|
||||
|
||||
parser->data += 2;
|
||||
|
||||
while (*parser->data)
|
||||
{
|
||||
gsize len = strcspn (parser->data, NEWLINE_CHARS "/");
|
||||
|
||||
parser->data += len;
|
||||
|
||||
if (gtk_css_parser_new_line (parser))
|
||||
continue;
|
||||
|
||||
parser->data++;
|
||||
|
||||
if (parser->data[-2] == '*')
|
||||
return TRUE;
|
||||
if (parser->data[0] == '*')
|
||||
_gtk_css_parser_error (parser, "'/*' in comment block");
|
||||
}
|
||||
|
||||
/* FIXME: position */
|
||||
_gtk_css_parser_error (parser, "Unterminated comment");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
_gtk_css_parser_skip_whitespace (GtkCssParser *parser)
|
||||
{
|
||||
size_t len;
|
||||
|
||||
while (*parser->data)
|
||||
{
|
||||
if (gtk_css_parser_new_line (parser))
|
||||
continue;
|
||||
|
||||
len = strspn (parser->data, WHITESPACE_CHARS);
|
||||
if (len)
|
||||
{
|
||||
parser->data += len;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!gtk_css_parser_skip_comment (parser))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
_gtk_css_parser_try (GtkCssParser *parser,
|
||||
const char *string,
|
||||
gboolean skip_whitespace)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_CSS_PARSER (parser), FALSE);
|
||||
g_return_val_if_fail (string != NULL, FALSE);
|
||||
|
||||
if (g_ascii_strncasecmp (parser->data, string, strlen (string)) != 0)
|
||||
return FALSE;
|
||||
|
||||
parser->data += strlen (string);
|
||||
|
||||
if (skip_whitespace)
|
||||
_gtk_css_parser_skip_whitespace (parser);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static guint
|
||||
get_xdigit (char c)
|
||||
{
|
||||
if (c >= 'a')
|
||||
return c - 'a' + 10;
|
||||
else if (c >= 'A')
|
||||
return c - 'A' + 10;
|
||||
else
|
||||
return c - '0';
|
||||
}
|
||||
|
||||
static void
|
||||
_gtk_css_parser_unescape (GtkCssParser *parser,
|
||||
GString *str)
|
||||
{
|
||||
guint i;
|
||||
gunichar result = 0;
|
||||
|
||||
g_assert (*parser->data == '\\');
|
||||
|
||||
parser->data++;
|
||||
|
||||
for (i = 0; i < 6; i++)
|
||||
{
|
||||
if (!g_ascii_isxdigit (parser->data[i]))
|
||||
break;
|
||||
|
||||
result = (result << 4) + get_xdigit (parser->data[i]);
|
||||
}
|
||||
|
||||
if (i != 0)
|
||||
{
|
||||
g_string_append_unichar (str, result);
|
||||
parser->data += i;
|
||||
|
||||
/* NB: gtk_css_parser_new_line() forward data pointer itself */
|
||||
if (!gtk_css_parser_new_line (parser) &&
|
||||
*parser->data &&
|
||||
strchr (WHITESPACE_CHARS, *parser->data))
|
||||
parser->data++;
|
||||
return;
|
||||
}
|
||||
|
||||
if (gtk_css_parser_new_line (parser))
|
||||
return;
|
||||
|
||||
g_string_append_c (str, *parser->data);
|
||||
parser->data++;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_gtk_css_parser_read_char (GtkCssParser *parser,
|
||||
GString * str,
|
||||
const char * allowed)
|
||||
{
|
||||
if (*parser->data == 0)
|
||||
return FALSE;
|
||||
|
||||
if (strchr (allowed, *parser->data))
|
||||
{
|
||||
g_string_append_c (str, *parser->data);
|
||||
parser->data++;
|
||||
return TRUE;
|
||||
}
|
||||
if (*parser->data >= 127)
|
||||
{
|
||||
gsize len = g_utf8_skip[(guint) *(guchar *) parser->data];
|
||||
|
||||
g_string_append_len (str, parser->data, len);
|
||||
parser->data += len;
|
||||
return TRUE;
|
||||
}
|
||||
if (*parser->data == '\\')
|
||||
{
|
||||
_gtk_css_parser_unescape (parser, str);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
char *
|
||||
_gtk_css_parser_try_name (GtkCssParser *parser,
|
||||
gboolean skip_whitespace)
|
||||
{
|
||||
GString *name;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_CSS_PARSER (parser), NULL);
|
||||
|
||||
name = g_string_new (NULL);
|
||||
|
||||
while (_gtk_css_parser_read_char (parser, name, NMCHAR))
|
||||
;
|
||||
|
||||
if (skip_whitespace)
|
||||
_gtk_css_parser_skip_whitespace (parser);
|
||||
|
||||
return g_string_free (name, FALSE);
|
||||
}
|
||||
|
||||
char *
|
||||
_gtk_css_parser_try_ident (GtkCssParser *parser,
|
||||
gboolean skip_whitespace)
|
||||
{
|
||||
const char *start;
|
||||
GString *ident;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_CSS_PARSER (parser), NULL);
|
||||
|
||||
start = parser->data;
|
||||
|
||||
ident = g_string_new (NULL);
|
||||
|
||||
if (*parser->data == '-')
|
||||
{
|
||||
g_string_append_c (ident, '-');
|
||||
parser->data++;
|
||||
}
|
||||
|
||||
if (!_gtk_css_parser_read_char (parser, ident, NMSTART))
|
||||
{
|
||||
parser->data = start;
|
||||
g_string_free (ident, TRUE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
while (_gtk_css_parser_read_char (parser, ident, NMCHAR))
|
||||
;
|
||||
|
||||
if (skip_whitespace)
|
||||
_gtk_css_parser_skip_whitespace (parser);
|
||||
|
||||
return g_string_free (ident, FALSE);
|
||||
}
|
||||
|
||||
gboolean
|
||||
_gtk_css_parser_is_string (GtkCssParser *parser)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_CSS_PARSER (parser), FALSE);
|
||||
|
||||
return *parser->data == '"' || *parser->data == '\'';
|
||||
}
|
||||
|
||||
char *
|
||||
_gtk_css_parser_read_string (GtkCssParser *parser)
|
||||
{
|
||||
GString *str;
|
||||
char quote;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_CSS_PARSER (parser), NULL);
|
||||
|
||||
quote = *parser->data;
|
||||
|
||||
if (quote != '"' && quote != '\'')
|
||||
return NULL;
|
||||
|
||||
parser->data++;
|
||||
str = g_string_new (NULL);
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
gsize len = strcspn (parser->data, "\\'\"\n\r\f");
|
||||
|
||||
g_string_append_len (str, parser->data, len);
|
||||
|
||||
parser->data += len;
|
||||
|
||||
switch (*parser->data)
|
||||
{
|
||||
case '\\':
|
||||
_gtk_css_parser_unescape (parser, str);
|
||||
break;
|
||||
case '"':
|
||||
case '\'':
|
||||
if (*parser->data == quote)
|
||||
{
|
||||
parser->data++;
|
||||
_gtk_css_parser_skip_whitespace (parser);
|
||||
return g_string_free (str, FALSE);
|
||||
}
|
||||
|
||||
g_string_append_c (str, *parser->data);
|
||||
parser->data++;
|
||||
break;
|
||||
case '\0':
|
||||
/* FIXME: position */
|
||||
_gtk_css_parser_error (parser, "Missing end quote in string.");
|
||||
g_string_free (str, TRUE);
|
||||
return NULL;
|
||||
default:
|
||||
_gtk_css_parser_error (parser,
|
||||
"Invalid character in string. Must be escaped.");
|
||||
g_string_free (str, TRUE);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
g_assert_not_reached ();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *
|
||||
_gtk_css_parser_read_uri (GtkCssParser *parser)
|
||||
{
|
||||
char *result;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_CSS_PARSER (parser), NULL);
|
||||
|
||||
if (!_gtk_css_parser_try (parser, "url(", TRUE))
|
||||
{
|
||||
_gtk_css_parser_error (parser, "expected 'url('");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
_gtk_css_parser_skip_whitespace (parser);
|
||||
|
||||
if (_gtk_css_parser_is_string (parser))
|
||||
{
|
||||
result = _gtk_css_parser_read_string (parser);
|
||||
}
|
||||
else
|
||||
{
|
||||
GString *str = g_string_new (NULL);
|
||||
|
||||
while (_gtk_css_parser_read_char (parser, str, URLCHAR))
|
||||
;
|
||||
result = g_string_free (str, FALSE);
|
||||
if (result == NULL)
|
||||
_gtk_css_parser_error (parser, "not a url");
|
||||
}
|
||||
|
||||
if (result == NULL)
|
||||
return NULL;
|
||||
|
||||
_gtk_css_parser_skip_whitespace (parser);
|
||||
|
||||
if (*parser->data != ')')
|
||||
{
|
||||
_gtk_css_parser_error (parser, "missing ')' for url");
|
||||
g_free (result);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
parser->data++;
|
||||
|
||||
_gtk_css_parser_skip_whitespace (parser);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
gboolean
|
||||
_gtk_css_parser_try_int (GtkCssParser *parser,
|
||||
int *value)
|
||||
{
|
||||
gint64 result;
|
||||
char *end;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_CSS_PARSER (parser), FALSE);
|
||||
g_return_val_if_fail (value != NULL, FALSE);
|
||||
|
||||
/* strtoll parses a plus, but we are not allowed to */
|
||||
if (*parser->data == '+')
|
||||
return FALSE;
|
||||
|
||||
errno = 0;
|
||||
result = g_ascii_strtoll (parser->data, &end, 10);
|
||||
if (errno)
|
||||
return FALSE;
|
||||
if (result > G_MAXINT || result < G_MININT)
|
||||
return FALSE;
|
||||
if (parser->data == end)
|
||||
return FALSE;
|
||||
|
||||
parser->data = end;
|
||||
*value = result;
|
||||
|
||||
_gtk_css_parser_skip_whitespace (parser);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
_gtk_css_parser_try_uint (GtkCssParser *parser,
|
||||
uint *value)
|
||||
{
|
||||
guint64 result;
|
||||
char *end;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_CSS_PARSER (parser), FALSE);
|
||||
g_return_val_if_fail (value != NULL, FALSE);
|
||||
|
||||
errno = 0;
|
||||
result = g_ascii_strtoull (parser->data, &end, 10);
|
||||
if (errno)
|
||||
return FALSE;
|
||||
if (result > G_MAXUINT)
|
||||
return FALSE;
|
||||
if (parser->data == end)
|
||||
return FALSE;
|
||||
|
||||
parser->data = end;
|
||||
*value = result;
|
||||
|
||||
_gtk_css_parser_skip_whitespace (parser);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
_gtk_css_parser_try_double (GtkCssParser *parser,
|
||||
gdouble *value)
|
||||
{
|
||||
gdouble result;
|
||||
char *end;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_CSS_PARSER (parser), FALSE);
|
||||
g_return_val_if_fail (value != NULL, FALSE);
|
||||
|
||||
errno = 0;
|
||||
result = g_ascii_strtod (parser->data, &end);
|
||||
if (errno)
|
||||
return FALSE;
|
||||
if (parser->data == end)
|
||||
return FALSE;
|
||||
|
||||
parser->data = end;
|
||||
*value = result;
|
||||
|
||||
_gtk_css_parser_skip_whitespace (parser);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
typedef enum {
|
||||
COLOR_RGBA,
|
||||
COLOR_RGB,
|
||||
COLOR_LIGHTER,
|
||||
COLOR_DARKER,
|
||||
COLOR_SHADE,
|
||||
COLOR_ALPHA,
|
||||
COLOR_MIX
|
||||
} ColorType;
|
||||
|
||||
static GtkSymbolicColor *
|
||||
gtk_css_parser_read_symbolic_color_function (GtkCssParser *parser,
|
||||
ColorType color)
|
||||
{
|
||||
GtkSymbolicColor *symbolic;
|
||||
GtkSymbolicColor *child1, *child2;
|
||||
double value;
|
||||
|
||||
if (!_gtk_css_parser_try (parser, "(", TRUE))
|
||||
{
|
||||
_gtk_css_parser_error (parser, "Missing opening bracket in color definition");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (color == COLOR_RGB || color == COLOR_RGBA)
|
||||
{
|
||||
GdkRGBA rgba;
|
||||
double tmp;
|
||||
guint i;
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
if (i > 0 && !_gtk_css_parser_try (parser, ",", TRUE))
|
||||
{
|
||||
_gtk_css_parser_error (parser, "Expected ',' in color definition");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!_gtk_css_parser_try_double (parser, &tmp))
|
||||
{
|
||||
_gtk_css_parser_error (parser, "Invalid number for color value");
|
||||
return NULL;
|
||||
}
|
||||
if (_gtk_css_parser_try (parser, "%", TRUE))
|
||||
tmp /= 100.0;
|
||||
else
|
||||
tmp /= 255.0;
|
||||
if (i == 0)
|
||||
rgba.red = tmp;
|
||||
else if (i == 1)
|
||||
rgba.green = tmp;
|
||||
else if (i == 2)
|
||||
rgba.blue = tmp;
|
||||
else
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
|
||||
if (color == COLOR_RGBA)
|
||||
{
|
||||
if (i > 0 && !_gtk_css_parser_try (parser, ",", TRUE))
|
||||
{
|
||||
_gtk_css_parser_error (parser, "Expected ',' in color definition");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!_gtk_css_parser_try_double (parser, &rgba.alpha))
|
||||
{
|
||||
_gtk_css_parser_error (parser, "Invalid number for alpha value");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
rgba.alpha = 1.0;
|
||||
|
||||
symbolic = gtk_symbolic_color_new_literal (&rgba);
|
||||
}
|
||||
else
|
||||
{
|
||||
child1 = _gtk_css_parser_read_symbolic_color (parser);
|
||||
if (child1 == NULL)
|
||||
return NULL;
|
||||
|
||||
if (color == COLOR_MIX)
|
||||
{
|
||||
if (!_gtk_css_parser_try (parser, ",", TRUE))
|
||||
{
|
||||
_gtk_css_parser_error (parser, "Expected ',' in color definition");
|
||||
gtk_symbolic_color_unref (child1);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
child2 = _gtk_css_parser_read_symbolic_color (parser);
|
||||
if (child2 == NULL)
|
||||
{
|
||||
g_object_unref (child1);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
child2 = NULL;
|
||||
|
||||
if (color == COLOR_LIGHTER)
|
||||
value = 1.3;
|
||||
else if (color == COLOR_DARKER)
|
||||
value = 0.7;
|
||||
else
|
||||
{
|
||||
if (!_gtk_css_parser_try (parser, ",", TRUE))
|
||||
{
|
||||
_gtk_css_parser_error (parser, "Expected ',' in color definition");
|
||||
gtk_symbolic_color_unref (child1);
|
||||
if (child2)
|
||||
gtk_symbolic_color_unref (child2);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!_gtk_css_parser_try_double (parser, &value))
|
||||
{
|
||||
_gtk_css_parser_error (parser, "Expected number in color definition");
|
||||
gtk_symbolic_color_unref (child1);
|
||||
if (child2)
|
||||
gtk_symbolic_color_unref (child2);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
switch (color)
|
||||
{
|
||||
case COLOR_LIGHTER:
|
||||
case COLOR_DARKER:
|
||||
case COLOR_SHADE:
|
||||
symbolic = gtk_symbolic_color_new_shade (child1, value);
|
||||
break;
|
||||
case COLOR_ALPHA:
|
||||
symbolic = gtk_symbolic_color_new_alpha (child1, value);
|
||||
break;
|
||||
case COLOR_MIX:
|
||||
symbolic = gtk_symbolic_color_new_mix (child1, child2, value);
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
symbolic = NULL;
|
||||
}
|
||||
|
||||
gtk_symbolic_color_unref (child1);
|
||||
if (child2)
|
||||
gtk_symbolic_color_unref (child2);
|
||||
}
|
||||
|
||||
if (!_gtk_css_parser_try (parser, ")", TRUE))
|
||||
{
|
||||
gtk_symbolic_color_unref (symbolic);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return symbolic;
|
||||
}
|
||||
|
||||
static GtkSymbolicColor *
|
||||
gtk_css_parser_try_hash_color (GtkCssParser *parser)
|
||||
{
|
||||
if (parser->data[0] == '#' &&
|
||||
g_ascii_isxdigit (parser->data[1]) &&
|
||||
g_ascii_isxdigit (parser->data[2]) &&
|
||||
g_ascii_isxdigit (parser->data[3]))
|
||||
{
|
||||
GdkRGBA rgba;
|
||||
|
||||
if (g_ascii_isxdigit (parser->data[4]) &&
|
||||
g_ascii_isxdigit (parser->data[5]) &&
|
||||
g_ascii_isxdigit (parser->data[6]))
|
||||
{
|
||||
rgba.red = ((get_xdigit (parser->data[1]) << 4) + get_xdigit (parser->data[2])) / 255.0;
|
||||
rgba.green = ((get_xdigit (parser->data[3]) << 4) + get_xdigit (parser->data[4])) / 255.0;
|
||||
rgba.blue = ((get_xdigit (parser->data[5]) << 4) + get_xdigit (parser->data[6])) / 255.0;
|
||||
rgba.alpha = 1.0;
|
||||
parser->data += 7;
|
||||
}
|
||||
else
|
||||
{
|
||||
rgba.red = get_xdigit (parser->data[1]) / 15.0;
|
||||
rgba.green = get_xdigit (parser->data[2]) / 15.0;
|
||||
rgba.blue = get_xdigit (parser->data[3]) / 15.0;
|
||||
rgba.alpha = 1.0;
|
||||
parser->data += 4;
|
||||
}
|
||||
|
||||
_gtk_css_parser_skip_whitespace (parser);
|
||||
|
||||
return gtk_symbolic_color_new_literal (&rgba);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GtkSymbolicColor *
|
||||
_gtk_css_parser_read_symbolic_color (GtkCssParser *parser)
|
||||
{
|
||||
GtkSymbolicColor *symbolic;
|
||||
guint color;
|
||||
const char *names[] = {"rgba", "rgb", "lighter", "darker", "shade", "alpha", "mix" };
|
||||
char *name;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_CSS_PARSER (parser), NULL);
|
||||
|
||||
if (_gtk_css_parser_try (parser, "@", FALSE))
|
||||
{
|
||||
name = _gtk_css_parser_try_name (parser, TRUE);
|
||||
|
||||
if (name)
|
||||
{
|
||||
symbolic = gtk_symbolic_color_new_name (name);
|
||||
}
|
||||
else
|
||||
{
|
||||
_gtk_css_parser_error (parser, "'%s' is not a valid symbolic color name", name);
|
||||
symbolic = NULL;
|
||||
}
|
||||
|
||||
g_free (name);
|
||||
return symbolic;
|
||||
}
|
||||
|
||||
for (color = 0; color < G_N_ELEMENTS (names); color++)
|
||||
{
|
||||
if (_gtk_css_parser_try (parser, names[color], TRUE))
|
||||
break;
|
||||
}
|
||||
|
||||
if (color < G_N_ELEMENTS (names))
|
||||
return gtk_css_parser_read_symbolic_color_function (parser, color);
|
||||
|
||||
symbolic = gtk_css_parser_try_hash_color (parser);
|
||||
if (symbolic)
|
||||
return symbolic;
|
||||
|
||||
name = _gtk_css_parser_try_name (parser, TRUE);
|
||||
if (name)
|
||||
{
|
||||
GdkRGBA rgba;
|
||||
|
||||
if (gdk_rgba_parse (&rgba, name))
|
||||
{
|
||||
symbolic = gtk_symbolic_color_new_literal (&rgba);
|
||||
}
|
||||
else
|
||||
{
|
||||
_gtk_css_parser_error (parser, "'%s' is not a valid color name", name);
|
||||
symbolic = NULL;
|
||||
}
|
||||
g_free (name);
|
||||
return symbolic;
|
||||
}
|
||||
|
||||
_gtk_css_parser_error (parser, "Not a color definition");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
_gtk_css_parser_resync_internal (GtkCssParser *parser,
|
||||
gboolean sync_at_semicolon,
|
||||
gboolean read_sync_token,
|
||||
char terminator)
|
||||
{
|
||||
gsize len;
|
||||
|
||||
do {
|
||||
len = strcspn (parser->data, "\\\"'/()[]{};" NEWLINE_CHARS);
|
||||
parser->data += len;
|
||||
|
||||
if (gtk_css_parser_new_line (parser))
|
||||
continue;
|
||||
|
||||
if (_gtk_css_parser_is_string (parser))
|
||||
{
|
||||
/* Hrm, this emits errors, and i suspect it shouldn't... */
|
||||
char *free_me = _gtk_css_parser_read_string (parser);
|
||||
g_free (free_me);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (gtk_css_parser_skip_comment (parser))
|
||||
continue;
|
||||
|
||||
switch (*parser->data)
|
||||
{
|
||||
case '/':
|
||||
{
|
||||
GString *ignore = g_string_new (NULL);
|
||||
_gtk_css_parser_unescape (parser, ignore);
|
||||
g_string_free (ignore, TRUE);
|
||||
}
|
||||
break;
|
||||
case ';':
|
||||
if (sync_at_semicolon && !read_sync_token)
|
||||
return;
|
||||
parser->data++;
|
||||
if (sync_at_semicolon)
|
||||
{
|
||||
_gtk_css_parser_skip_whitespace (parser);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case '(':
|
||||
parser->data++;
|
||||
_gtk_css_parser_resync (parser, FALSE, ')');
|
||||
parser->data++;
|
||||
break;
|
||||
case '[':
|
||||
parser->data++;
|
||||
_gtk_css_parser_resync (parser, FALSE, ']');
|
||||
parser->data++;
|
||||
break;
|
||||
case '{':
|
||||
parser->data++;
|
||||
_gtk_css_parser_resync (parser, FALSE, '}');
|
||||
parser->data++;
|
||||
if (sync_at_semicolon || !terminator)
|
||||
{
|
||||
_gtk_css_parser_skip_whitespace (parser);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case '}':
|
||||
case ')':
|
||||
case ']':
|
||||
if (terminator == *parser->data)
|
||||
{
|
||||
_gtk_css_parser_skip_whitespace (parser);
|
||||
return;
|
||||
}
|
||||
parser->data++;
|
||||
continue;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} while (*parser->data);
|
||||
}
|
||||
|
||||
char *
|
||||
_gtk_css_parser_read_value (GtkCssParser *parser)
|
||||
{
|
||||
const char *start;
|
||||
char *result;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_CSS_PARSER (parser), NULL);
|
||||
|
||||
start = parser->data;
|
||||
|
||||
/* This needs to be done better */
|
||||
_gtk_css_parser_resync_internal (parser, TRUE, FALSE, '}');
|
||||
|
||||
result = g_strndup (start, parser->data - start);
|
||||
if (result)
|
||||
{
|
||||
g_strchomp (result);
|
||||
if (result[0] == 0)
|
||||
{
|
||||
g_free (result);
|
||||
result = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (result == NULL)
|
||||
_gtk_css_parser_error (parser, "Expected a property value");
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
_gtk_css_parser_resync (GtkCssParser *parser,
|
||||
gboolean sync_at_semicolon,
|
||||
char terminator)
|
||||
{
|
||||
g_return_if_fail (GTK_IS_CSS_PARSER (parser));
|
||||
|
||||
_gtk_css_parser_resync_internal (parser, sync_at_semicolon, TRUE, terminator);
|
||||
}
|
||||
85
gtk/gtkcssparserprivate.h
Normal file
85
gtk/gtkcssparserprivate.h
Normal file
@ -0,0 +1,85 @@
|
||||
/* GTK - The GIMP Toolkit
|
||||
* Copyright (C) 2011 Benjamin Otte <otte@gnome.org>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __GTK_CSS_PARSER_PRIVATE_H__
|
||||
#define __GTK_CSS_PARSER_PRIVATE_H__
|
||||
|
||||
#include <gtk/gtksymboliccolor.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef struct _GtkCssParser GtkCssParser;
|
||||
|
||||
typedef void (* GtkCssParserErrorFunc) (GtkCssParser *parser,
|
||||
const GError *error,
|
||||
gpointer user_data);
|
||||
|
||||
GtkCssParser * _gtk_css_parser_new (const char *data,
|
||||
GtkCssParserErrorFunc error_func,
|
||||
gpointer user_data);
|
||||
void _gtk_css_parser_free (GtkCssParser *parser);
|
||||
|
||||
void _gtk_css_parser_error (GtkCssParser *parser,
|
||||
const char *format,
|
||||
...) G_GNUC_PRINTF (2, 3);
|
||||
|
||||
guint _gtk_css_parser_get_line (GtkCssParser *parser);
|
||||
guint _gtk_css_parser_get_position (GtkCssParser *parser);
|
||||
|
||||
gboolean _gtk_css_parser_is_eof (GtkCssParser *parser);
|
||||
gboolean _gtk_css_parser_begins_with (GtkCssParser *parser,
|
||||
char c);
|
||||
gboolean _gtk_css_parser_is_string (GtkCssParser *parser);
|
||||
|
||||
/* IMPORTANT:
|
||||
* _try_foo() functions do not modify the data pointer if they fail, nor do they
|
||||
* signal an error. _read_foo() will modify the data pointer and position it at
|
||||
* the first token that is broken and emit an error about the failure.
|
||||
* So only call _read_foo() when you know that you are reading a foo. _try_foo()
|
||||
* however is fine to call if you don't know yet if the token is a foo or a bar,
|
||||
* you can _try_bar() if try_foo() failed.
|
||||
*/
|
||||
gboolean _gtk_css_parser_try (GtkCssParser *parser,
|
||||
const char *string,
|
||||
gboolean skip_whitespace);
|
||||
char * _gtk_css_parser_try_ident (GtkCssParser *parser,
|
||||
gboolean skip_whitespace);
|
||||
char * _gtk_css_parser_try_name (GtkCssParser *parser,
|
||||
gboolean skip_whitespace);
|
||||
gboolean _gtk_css_parser_try_int (GtkCssParser *parser,
|
||||
int *value);
|
||||
gboolean _gtk_css_parser_try_uint (GtkCssParser *parser,
|
||||
uint *value);
|
||||
gboolean _gtk_css_parser_try_double (GtkCssParser *parser,
|
||||
gdouble *value);
|
||||
|
||||
void _gtk_css_parser_skip_whitespace (GtkCssParser *parser);
|
||||
char * _gtk_css_parser_read_string (GtkCssParser *parser);
|
||||
char * _gtk_css_parser_read_uri (GtkCssParser *parser);
|
||||
char * _gtk_css_parser_read_value (GtkCssParser *parser);
|
||||
GtkSymbolicColor *_gtk_css_parser_read_symbolic_color
|
||||
(GtkCssParser *parser);
|
||||
|
||||
void _gtk_css_parser_resync (GtkCssParser *parser,
|
||||
gboolean sync_at_semicolon,
|
||||
char terminator);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GTK_CSS_PARSER_PRIVATE_H__ */
|
||||
1332
gtk/gtkcssprovider.c
1332
gtk/gtkcssprovider.c
File diff suppressed because it is too large
Load Diff
@ -37,15 +37,9 @@ typedef enum
|
||||
{
|
||||
GTK_CSS_PROVIDER_ERROR_FAILED,
|
||||
GTK_CSS_PROVIDER_ERROR_SYNTAX,
|
||||
GTK_CSS_PROVIDER_ERROR_PROPERTY_NAME,
|
||||
GTK_CSS_PROVIDER_ERROR_PROPERTY_VALUE,
|
||||
GTK_CSS_PROVIDER_ERROR_SELECTOR,
|
||||
GTK_CSS_PROVIDER_ERROR_COMBINATOR,
|
||||
GTK_CSS_PROVIDER_ERROR_CLASS,
|
||||
GTK_CSS_PROVIDER_ERROR_PSEUDO_CLASS,
|
||||
GTK_CSS_PROVIDER_ERROR_AT_RULE,
|
||||
GTK_CSS_PROVIDER_ERROR_IMPORT,
|
||||
GTK_CSS_PROVIDER_ERROR_DEFINE_COLOR
|
||||
GTK_CSS_PROVIDER_ERROR_NAME,
|
||||
GTK_CSS_PROVIDER_ERROR_DEPRECATED
|
||||
} GtkCssProviderError;
|
||||
|
||||
GQuark gtk_css_provider_error_quark (void);
|
||||
|
||||
@ -29,6 +29,7 @@
|
||||
#include <cairo-gobject.h>
|
||||
|
||||
#include "gtkcssprovider.h"
|
||||
#include "gtkcssparserprivate.h"
|
||||
|
||||
/* the actual parsers we have */
|
||||
#include "gtkanimationdescription.h"
|
||||
@ -62,7 +63,7 @@ set_default_error (GError **error,
|
||||
{
|
||||
g_set_error (error,
|
||||
GTK_CSS_PROVIDER_ERROR,
|
||||
GTK_CSS_PROVIDER_ERROR_PROPERTY_VALUE,
|
||||
GTK_CSS_PROVIDER_ERROR_SYNTAX,
|
||||
"Could not convert property value to type '%s'",
|
||||
g_type_name (type));
|
||||
return FALSE;
|
||||
@ -73,257 +74,35 @@ set_default_error (GError **error,
|
||||
#define SKIP_SPACES(s) while (g_ascii_isspace (*(s))) (s)++
|
||||
#define SKIP_SPACES_BACK(s) while (g_ascii_isspace (*(s))) (s)--
|
||||
|
||||
static GtkSymbolicColor *
|
||||
symbolic_color_parse_str (const gchar *string,
|
||||
gchar **end_ptr)
|
||||
static void
|
||||
propagate_parser_error (GtkCssParser *parser,
|
||||
const GError *error,
|
||||
gpointer user_data)
|
||||
{
|
||||
GtkSymbolicColor *symbolic_color = NULL;
|
||||
gchar *str;
|
||||
GError **propagate_here = user_data;
|
||||
|
||||
str = (gchar *) string;
|
||||
*end_ptr = str;
|
||||
if (propagate_here == NULL)
|
||||
return;
|
||||
|
||||
if (str[0] == '@')
|
||||
{
|
||||
const gchar *end;
|
||||
gchar *name;
|
||||
/* only copy the first error */
|
||||
if (*propagate_here == NULL)
|
||||
*propagate_here = g_error_copy (error);
|
||||
}
|
||||
|
||||
str++;
|
||||
end = str;
|
||||
static GtkSymbolicColor *
|
||||
_gtk_css_parse_symbolic_color (const char *str,
|
||||
GError **error)
|
||||
{
|
||||
GtkSymbolicColor *symbolic;
|
||||
GtkCssParser *parser;
|
||||
|
||||
while (*end == '-' || *end == '_' || g_ascii_isalnum (*end))
|
||||
end++;
|
||||
parser = _gtk_css_parser_new (str,
|
||||
propagate_parser_error,
|
||||
error);
|
||||
symbolic = _gtk_css_parser_read_symbolic_color (parser);
|
||||
_gtk_css_parser_free (parser);
|
||||
|
||||
name = g_strndup (str, end - str);
|
||||
symbolic_color = gtk_symbolic_color_new_name (name);
|
||||
g_free (name);
|
||||
|
||||
*end_ptr = (gchar *) end;
|
||||
}
|
||||
else if (g_str_has_prefix (str, "lighter") ||
|
||||
g_str_has_prefix (str, "darker"))
|
||||
{
|
||||
GtkSymbolicColor *param_color;
|
||||
gboolean is_lighter = FALSE;
|
||||
|
||||
is_lighter = g_str_has_prefix (str, "lighter");
|
||||
|
||||
if (is_lighter)
|
||||
str += strlen ("lighter");
|
||||
else
|
||||
str += strlen ("darker");
|
||||
|
||||
SKIP_SPACES (str);
|
||||
|
||||
if (*str != '(')
|
||||
{
|
||||
*end_ptr = (gchar *) str;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
str++;
|
||||
SKIP_SPACES (str);
|
||||
param_color = symbolic_color_parse_str (str, end_ptr);
|
||||
|
||||
if (!param_color)
|
||||
return NULL;
|
||||
|
||||
str = *end_ptr;
|
||||
SKIP_SPACES (str);
|
||||
*end_ptr = (gchar *) str;
|
||||
|
||||
if (*str != ')')
|
||||
{
|
||||
gtk_symbolic_color_unref (param_color);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (is_lighter)
|
||||
symbolic_color = gtk_symbolic_color_new_shade (param_color, 1.3);
|
||||
else
|
||||
symbolic_color = gtk_symbolic_color_new_shade (param_color, 0.7);
|
||||
|
||||
gtk_symbolic_color_unref (param_color);
|
||||
(*end_ptr)++;
|
||||
}
|
||||
else if (g_str_has_prefix (str, "shade") ||
|
||||
g_str_has_prefix (str, "alpha"))
|
||||
{
|
||||
GtkSymbolicColor *param_color;
|
||||
gboolean is_shade = FALSE;
|
||||
gdouble factor;
|
||||
|
||||
is_shade = g_str_has_prefix (str, "shade");
|
||||
|
||||
if (is_shade)
|
||||
str += strlen ("shade");
|
||||
else
|
||||
str += strlen ("alpha");
|
||||
|
||||
SKIP_SPACES (str);
|
||||
|
||||
if (*str != '(')
|
||||
{
|
||||
*end_ptr = (gchar *) str;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
str++;
|
||||
SKIP_SPACES (str);
|
||||
param_color = symbolic_color_parse_str (str, end_ptr);
|
||||
|
||||
if (!param_color)
|
||||
return NULL;
|
||||
|
||||
str = *end_ptr;
|
||||
SKIP_SPACES (str);
|
||||
|
||||
if (str[0] != ',')
|
||||
{
|
||||
gtk_symbolic_color_unref (param_color);
|
||||
*end_ptr = (gchar *) str;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
str++;
|
||||
SKIP_SPACES (str);
|
||||
factor = g_ascii_strtod (str, end_ptr);
|
||||
|
||||
str = *end_ptr;
|
||||
SKIP_SPACES (str);
|
||||
*end_ptr = (gchar *) str;
|
||||
|
||||
if (str[0] != ')')
|
||||
{
|
||||
gtk_symbolic_color_unref (param_color);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (is_shade)
|
||||
symbolic_color = gtk_symbolic_color_new_shade (param_color, factor);
|
||||
else
|
||||
symbolic_color = gtk_symbolic_color_new_alpha (param_color, factor);
|
||||
|
||||
gtk_symbolic_color_unref (param_color);
|
||||
(*end_ptr)++;
|
||||
}
|
||||
else if (g_str_has_prefix (str, "mix"))
|
||||
{
|
||||
GtkSymbolicColor *color1, *color2;
|
||||
gdouble factor;
|
||||
|
||||
str += strlen ("mix");
|
||||
SKIP_SPACES (str);
|
||||
|
||||
if (*str != '(')
|
||||
{
|
||||
*end_ptr = (gchar *) str;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
str++;
|
||||
SKIP_SPACES (str);
|
||||
color1 = symbolic_color_parse_str (str, end_ptr);
|
||||
|
||||
if (!color1)
|
||||
return NULL;
|
||||
|
||||
str = *end_ptr;
|
||||
SKIP_SPACES (str);
|
||||
|
||||
if (str[0] != ',')
|
||||
{
|
||||
gtk_symbolic_color_unref (color1);
|
||||
*end_ptr = (gchar *) str;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
str++;
|
||||
SKIP_SPACES (str);
|
||||
color2 = symbolic_color_parse_str (str, end_ptr);
|
||||
|
||||
if (!color2 || *end_ptr[0] != ',')
|
||||
{
|
||||
gtk_symbolic_color_unref (color1);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
str = *end_ptr;
|
||||
SKIP_SPACES (str);
|
||||
|
||||
if (str[0] != ',')
|
||||
{
|
||||
gtk_symbolic_color_unref (color1);
|
||||
gtk_symbolic_color_unref (color2);
|
||||
*end_ptr = (gchar *) str;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
str++;
|
||||
SKIP_SPACES (str);
|
||||
factor = g_ascii_strtod (str, end_ptr);
|
||||
|
||||
str = *end_ptr;
|
||||
SKIP_SPACES (str);
|
||||
*end_ptr = (gchar *) str;
|
||||
|
||||
if (str[0] != ')')
|
||||
{
|
||||
gtk_symbolic_color_unref (color1);
|
||||
gtk_symbolic_color_unref (color2);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
symbolic_color = gtk_symbolic_color_new_mix (color1, color2, factor);
|
||||
gtk_symbolic_color_unref (color1);
|
||||
gtk_symbolic_color_unref (color2);
|
||||
(*end_ptr)++;
|
||||
}
|
||||
else
|
||||
{
|
||||
GdkRGBA color;
|
||||
gchar *color_str;
|
||||
const gchar *end;
|
||||
|
||||
end = str + 1;
|
||||
|
||||
if (str[0] == '#')
|
||||
{
|
||||
/* Color in hex format */
|
||||
while (g_ascii_isxdigit (*end))
|
||||
end++;
|
||||
}
|
||||
else if (g_str_has_prefix (str, "rgb"))
|
||||
{
|
||||
/* color in rgb/rgba format */
|
||||
while (*end != ')' && *end != '\0')
|
||||
end++;
|
||||
|
||||
if (*end == ')')
|
||||
end++;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Color name */
|
||||
while (*end != '\0' &&
|
||||
(g_ascii_isalnum (*end) || *end == ' '))
|
||||
end++;
|
||||
}
|
||||
|
||||
color_str = g_strndup (str, end - str);
|
||||
*end_ptr = (gchar *) end;
|
||||
|
||||
if (!gdk_rgba_parse (&color, color_str))
|
||||
{
|
||||
g_free (color_str);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
symbolic_color = gtk_symbolic_color_new_literal (&color);
|
||||
g_free (color_str);
|
||||
}
|
||||
|
||||
return symbolic_color;
|
||||
return symbolic;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@ -489,6 +268,9 @@ int_value_from_string (const char *str,
|
||||
gint64 i;
|
||||
char *end;
|
||||
|
||||
if (*str == '+')
|
||||
return set_default_error (error, G_VALUE_TYPE (value));
|
||||
|
||||
i = g_ascii_strtoll (str, &end, 10);
|
||||
|
||||
if (*end != '\0')
|
||||
@ -498,7 +280,7 @@ int_value_from_string (const char *str,
|
||||
{
|
||||
g_set_error_literal (error,
|
||||
GTK_CSS_PROVIDER_ERROR,
|
||||
GTK_CSS_PROVIDER_ERROR_PROPERTY_VALUE,
|
||||
GTK_CSS_PROVIDER_ERROR_SYNTAX,
|
||||
"Number too big");
|
||||
return FALSE;
|
||||
}
|
||||
@ -522,6 +304,9 @@ uint_value_from_string (const char *str,
|
||||
guint64 u;
|
||||
char *end;
|
||||
|
||||
if (*str == '+')
|
||||
return set_default_error (error, G_VALUE_TYPE (value));
|
||||
|
||||
u = g_ascii_strtoull (str, &end, 10);
|
||||
|
||||
if (*end != '\0')
|
||||
@ -531,7 +316,7 @@ uint_value_from_string (const char *str,
|
||||
{
|
||||
g_set_error_literal (error,
|
||||
GTK_CSS_PROVIDER_ERROR,
|
||||
GTK_CSS_PROVIDER_ERROR_PROPERTY_VALUE,
|
||||
GTK_CSS_PROVIDER_ERROR_SYNTAX,
|
||||
"Number too big");
|
||||
return FALSE;
|
||||
}
|
||||
@ -564,7 +349,7 @@ double_value_from_string (const char *str,
|
||||
{
|
||||
g_set_error_literal (error,
|
||||
GTK_CSS_PROVIDER_ERROR,
|
||||
GTK_CSS_PROVIDER_ERROR_PROPERTY_VALUE,
|
||||
GTK_CSS_PROVIDER_ERROR_SYNTAX,
|
||||
"Number not representable");
|
||||
return FALSE;
|
||||
}
|
||||
@ -601,7 +386,7 @@ float_value_from_string (const char *str,
|
||||
{
|
||||
g_set_error_literal (error,
|
||||
GTK_CSS_PROVIDER_ERROR,
|
||||
GTK_CSS_PROVIDER_ERROR_PROPERTY_VALUE,
|
||||
GTK_CSS_PROVIDER_ERROR_SYNTAX,
|
||||
"Number not representable");
|
||||
return FALSE;
|
||||
}
|
||||
@ -634,7 +419,7 @@ gtk_css_string_unescape (const char *string,
|
||||
{
|
||||
g_set_error_literal (error,
|
||||
GTK_CSS_PROVIDER_ERROR,
|
||||
GTK_CSS_PROVIDER_ERROR_PROPERTY_VALUE,
|
||||
GTK_CSS_PROVIDER_ERROR_SYNTAX,
|
||||
"String value not properly quoted.");
|
||||
return NULL;
|
||||
}
|
||||
@ -659,7 +444,7 @@ gtk_css_string_unescape (const char *string,
|
||||
{
|
||||
g_set_error_literal (error,
|
||||
GTK_CSS_PROVIDER_ERROR,
|
||||
GTK_CSS_PROVIDER_ERROR_PROPERTY_VALUE,
|
||||
GTK_CSS_PROVIDER_ERROR_SYNTAX,
|
||||
"FIXME: Implement unicode escape sequences.");
|
||||
g_string_free (str, TRUE);
|
||||
return NULL;
|
||||
@ -685,7 +470,7 @@ gtk_css_string_unescape (const char *string,
|
||||
{
|
||||
g_set_error_literal (error,
|
||||
GTK_CSS_PROVIDER_ERROR,
|
||||
GTK_CSS_PROVIDER_ERROR_PROPERTY_VALUE,
|
||||
GTK_CSS_PROVIDER_ERROR_SYNTAX,
|
||||
"Junk after end of string.");
|
||||
g_string_free (str, TRUE);
|
||||
return NULL;
|
||||
@ -695,14 +480,14 @@ gtk_css_string_unescape (const char *string,
|
||||
case '\0':
|
||||
g_set_error_literal (error,
|
||||
GTK_CSS_PROVIDER_ERROR,
|
||||
GTK_CSS_PROVIDER_ERROR_PROPERTY_VALUE,
|
||||
GTK_CSS_PROVIDER_ERROR_SYNTAX,
|
||||
"Missing end quote in string.");
|
||||
g_string_free (str, TRUE);
|
||||
return NULL;
|
||||
default:
|
||||
g_set_error_literal (error,
|
||||
GTK_CSS_PROVIDER_ERROR,
|
||||
GTK_CSS_PROVIDER_ERROR_PROPERTY_VALUE,
|
||||
GTK_CSS_PROVIDER_ERROR_SYNTAX,
|
||||
"Invalid character in string. Must be escaped.");
|
||||
g_string_free (str, TRUE);
|
||||
return NULL;
|
||||
@ -783,7 +568,7 @@ theming_engine_value_from_string (const char *str,
|
||||
{
|
||||
g_set_error (error,
|
||||
GTK_CSS_PROVIDER_ERROR,
|
||||
GTK_CSS_PROVIDER_ERROR_PROPERTY_VALUE,
|
||||
GTK_CSS_PROVIDER_ERROR_SYNTAX,
|
||||
"Themeing engine '%s' not found", str);
|
||||
return FALSE;
|
||||
}
|
||||
@ -850,7 +635,7 @@ parse_border_value (const char *str,
|
||||
{
|
||||
g_set_error_literal (error,
|
||||
GTK_CSS_PROVIDER_ERROR,
|
||||
GTK_CSS_PROVIDER_ERROR_PROPERTY_VALUE,
|
||||
GTK_CSS_PROVIDER_ERROR_SYNTAX,
|
||||
"Number out of range for border");
|
||||
return FALSE;
|
||||
}
|
||||
@ -859,7 +644,7 @@ parse_border_value (const char *str,
|
||||
{
|
||||
g_set_error_literal (error,
|
||||
GTK_CSS_PROVIDER_ERROR,
|
||||
GTK_CSS_PROVIDER_ERROR_PROPERTY_VALUE,
|
||||
GTK_CSS_PROVIDER_ERROR_SYNTAX,
|
||||
"No number given for border value");
|
||||
return FALSE;
|
||||
}
|
||||
@ -875,7 +660,7 @@ parse_border_value (const char *str,
|
||||
{
|
||||
g_set_error_literal (error,
|
||||
GTK_CSS_PROVIDER_ERROR,
|
||||
GTK_CSS_PROVIDER_ERROR_PROPERTY_VALUE,
|
||||
GTK_CSS_PROVIDER_ERROR_SYNTAX,
|
||||
"Junk at end of border value");
|
||||
return FALSE;
|
||||
}
|
||||
@ -921,7 +706,7 @@ border_value_from_string (const char *str,
|
||||
{
|
||||
g_set_error_literal (error,
|
||||
GTK_CSS_PROVIDER_ERROR,
|
||||
GTK_CSS_PROVIDER_ERROR_PROPERTY_VALUE,
|
||||
GTK_CSS_PROVIDER_ERROR_SYNTAX,
|
||||
"Junk at end of border value");
|
||||
return FALSE;
|
||||
}
|
||||
@ -947,143 +732,92 @@ border_value_to_string (const GValue *value)
|
||||
return g_strdup_printf ("%d", border->top);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gradient_value_from_string (const char *str,
|
||||
GFile *base,
|
||||
GValue *value,
|
||||
GError **error)
|
||||
static GtkGradient *
|
||||
_gtk_css_parse_gradient (GtkCssParser *parser)
|
||||
{
|
||||
GtkGradient *gradient;
|
||||
cairo_pattern_type_t type;
|
||||
gdouble coords[6];
|
||||
gchar *end;
|
||||
guint i;
|
||||
|
||||
str += strlen ("-gtk-gradient");
|
||||
SKIP_SPACES (str);
|
||||
|
||||
if (*str != '(')
|
||||
if (!_gtk_css_parser_try (parser, "-gtk-gradient", TRUE))
|
||||
{
|
||||
g_set_error_literal (error,
|
||||
GTK_CSS_PROVIDER_ERROR,
|
||||
GTK_CSS_PROVIDER_ERROR_PROPERTY_VALUE,
|
||||
"Expected '(' after '-gtk-gradient'");
|
||||
return FALSE;
|
||||
_gtk_css_parser_error (parser,
|
||||
"Expected '-gtk-gradient'");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
str++;
|
||||
SKIP_SPACES (str);
|
||||
if (!_gtk_css_parser_try (parser, "(", TRUE))
|
||||
{
|
||||
_gtk_css_parser_error (parser,
|
||||
"Expected '(' after '-gtk-gradient'");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Parse gradient type */
|
||||
if (g_str_has_prefix (str, "linear"))
|
||||
{
|
||||
if (_gtk_css_parser_try (parser, "linear", TRUE))
|
||||
type = CAIRO_PATTERN_TYPE_LINEAR;
|
||||
str += strlen ("linear");
|
||||
}
|
||||
else if (g_str_has_prefix (str, "radial"))
|
||||
{
|
||||
else if (_gtk_css_parser_try (parser, "radial", TRUE))
|
||||
type = CAIRO_PATTERN_TYPE_RADIAL;
|
||||
str += strlen ("radial");
|
||||
}
|
||||
else
|
||||
{
|
||||
g_set_error_literal (error,
|
||||
GTK_CSS_PROVIDER_ERROR,
|
||||
GTK_CSS_PROVIDER_ERROR_PROPERTY_VALUE,
|
||||
_gtk_css_parser_error (parser,
|
||||
"Gradient type must be 'radial' or 'linear'");
|
||||
return FALSE;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SKIP_SPACES (str);
|
||||
|
||||
/* Parse start/stop position parameters */
|
||||
for (i = 0; i < 2; i++)
|
||||
{
|
||||
if (*str != ',')
|
||||
if (! _gtk_css_parser_try (parser, ",", TRUE))
|
||||
{
|
||||
g_set_error_literal (error,
|
||||
GTK_CSS_PROVIDER_ERROR,
|
||||
GTK_CSS_PROVIDER_ERROR_PROPERTY_VALUE,
|
||||
_gtk_css_parser_error (parser,
|
||||
"Expected ','");
|
||||
return FALSE;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
str++;
|
||||
SKIP_SPACES (str);
|
||||
|
||||
if (strncmp (str, "left", 4) == 0)
|
||||
{
|
||||
if (_gtk_css_parser_try (parser, "left", TRUE))
|
||||
coords[i * 3] = 0;
|
||||
str += strlen ("left");
|
||||
}
|
||||
else if (strncmp (str, "right", 5) == 0)
|
||||
{
|
||||
else if (_gtk_css_parser_try (parser, "right", TRUE))
|
||||
coords[i * 3] = 1;
|
||||
str += strlen ("right");
|
||||
}
|
||||
else if (strncmp (str, "center", 6) == 0)
|
||||
{
|
||||
else if (_gtk_css_parser_try (parser, "center", TRUE))
|
||||
coords[i * 3] = 0.5;
|
||||
str += strlen ("center");
|
||||
}
|
||||
else
|
||||
else if (!_gtk_css_parser_try_double (parser, &coords[i * 3]))
|
||||
{
|
||||
coords[i * 3] = g_ascii_strtod (str, &end);
|
||||
|
||||
if (str == end)
|
||||
return set_default_error (error, G_VALUE_TYPE (value));
|
||||
|
||||
str = end;
|
||||
_gtk_css_parser_error (parser,
|
||||
"Expected a valid X coordinate");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SKIP_SPACES (str);
|
||||
|
||||
if (strncmp (str, "top", 3) == 0)
|
||||
if (_gtk_css_parser_try (parser, "top", TRUE))
|
||||
coords[i * 3 + 1] = 0;
|
||||
else if (_gtk_css_parser_try (parser, "bottom", TRUE))
|
||||
coords[i * 3 + 1] = 1;
|
||||
else if (_gtk_css_parser_try (parser, "center", TRUE))
|
||||
coords[i * 3 + 1] = 0.5;
|
||||
else if (!_gtk_css_parser_try_double (parser, &coords[i * 3 + 1]))
|
||||
{
|
||||
coords[(i * 3) + 1] = 0;
|
||||
str += strlen ("top");
|
||||
_gtk_css_parser_error (parser,
|
||||
"Expected a valid Y coordinate");
|
||||
return NULL;
|
||||
}
|
||||
else if (strncmp (str, "bottom", 6) == 0)
|
||||
{
|
||||
coords[(i * 3) + 1] = 1;
|
||||
str += strlen ("bottom");
|
||||
}
|
||||
else if (strncmp (str, "center", 6) == 0)
|
||||
{
|
||||
coords[(i * 3) + 1] = 0.5;
|
||||
str += strlen ("center");
|
||||
}
|
||||
else
|
||||
{
|
||||
coords[(i * 3) + 1] = g_ascii_strtod (str, &end);
|
||||
|
||||
if (str == end)
|
||||
return set_default_error (error, G_VALUE_TYPE (value));
|
||||
|
||||
str = end;
|
||||
}
|
||||
|
||||
SKIP_SPACES (str);
|
||||
|
||||
if (type == CAIRO_PATTERN_TYPE_RADIAL)
|
||||
{
|
||||
/* Parse radius */
|
||||
if (*str != ',')
|
||||
if (! _gtk_css_parser_try (parser, ",", TRUE))
|
||||
{
|
||||
g_set_error_literal (error,
|
||||
GTK_CSS_PROVIDER_ERROR,
|
||||
GTK_CSS_PROVIDER_ERROR_PROPERTY_VALUE,
|
||||
_gtk_css_parser_error (parser,
|
||||
"Expected ','");
|
||||
return FALSE;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
str++;
|
||||
SKIP_SPACES (str);
|
||||
|
||||
coords[(i * 3) + 2] = g_ascii_strtod (str, &end);
|
||||
str = end;
|
||||
|
||||
SKIP_SPACES (str);
|
||||
if (! _gtk_css_parser_try_double (parser, &coords[(i * 3) + 2]))
|
||||
{
|
||||
_gtk_css_parser_error (parser,
|
||||
"Expected a numer for the radius");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1093,102 +827,120 @@ gradient_value_from_string (const char *str,
|
||||
gradient = gtk_gradient_new_radial (coords[0], coords[1], coords[2],
|
||||
coords[3], coords[4], coords[5]);
|
||||
|
||||
while (*str == ',')
|
||||
while (_gtk_css_parser_try (parser, ",", TRUE))
|
||||
{
|
||||
GtkSymbolicColor *color;
|
||||
gdouble position;
|
||||
|
||||
str++;
|
||||
SKIP_SPACES (str);
|
||||
|
||||
if (g_str_has_prefix (str, "from"))
|
||||
if (_gtk_css_parser_try (parser, "from", TRUE))
|
||||
{
|
||||
position = 0;
|
||||
str += strlen ("from");
|
||||
SKIP_SPACES (str);
|
||||
|
||||
if (*str != '(')
|
||||
if (!_gtk_css_parser_try (parser, "(", TRUE))
|
||||
{
|
||||
g_object_unref (gradient);
|
||||
return set_default_error (error, G_VALUE_TYPE (value));
|
||||
gtk_gradient_unref (gradient);
|
||||
_gtk_css_parser_error (parser,
|
||||
"Expected '('");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
}
|
||||
else if (g_str_has_prefix (str, "to"))
|
||||
else if (_gtk_css_parser_try (parser, "to", TRUE))
|
||||
{
|
||||
position = 1;
|
||||
str += strlen ("to");
|
||||
SKIP_SPACES (str);
|
||||
|
||||
if (*str != '(')
|
||||
if (!_gtk_css_parser_try (parser, "(", TRUE))
|
||||
{
|
||||
g_object_unref (gradient);
|
||||
return set_default_error (error, G_VALUE_TYPE (value));
|
||||
}
|
||||
}
|
||||
else if (g_str_has_prefix (str, "color-stop"))
|
||||
{
|
||||
str += strlen ("color-stop");
|
||||
SKIP_SPACES (str);
|
||||
|
||||
if (*str != '(')
|
||||
{
|
||||
g_object_unref (gradient);
|
||||
return set_default_error (error, G_VALUE_TYPE (value));
|
||||
gtk_gradient_unref (gradient);
|
||||
_gtk_css_parser_error (parser,
|
||||
"Expected '('");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
str++;
|
||||
SKIP_SPACES (str);
|
||||
|
||||
position = g_ascii_strtod (str, &end);
|
||||
|
||||
str = end;
|
||||
SKIP_SPACES (str);
|
||||
|
||||
if (*str != ',')
|
||||
}
|
||||
else if (_gtk_css_parser_try (parser, "color-stop", TRUE))
|
||||
{
|
||||
g_object_unref (gradient);
|
||||
return set_default_error (error, G_VALUE_TYPE (value));
|
||||
if (!_gtk_css_parser_try (parser, "(", TRUE))
|
||||
{
|
||||
gtk_gradient_unref (gradient);
|
||||
_gtk_css_parser_error (parser,
|
||||
"Expected '('");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!_gtk_css_parser_try_double (parser, &position))
|
||||
{
|
||||
gtk_gradient_unref (gradient);
|
||||
_gtk_css_parser_error (parser,
|
||||
"Expected a valid number");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!_gtk_css_parser_try (parser, ",", TRUE))
|
||||
{
|
||||
gtk_gradient_unref (gradient);
|
||||
_gtk_css_parser_error (parser,
|
||||
"Expected a comma");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
g_object_unref (gradient);
|
||||
return set_default_error (error, G_VALUE_TYPE (value));
|
||||
gtk_gradient_unref (gradient);
|
||||
_gtk_css_parser_error (parser,
|
||||
"Not a valid color-stop definition");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
str++;
|
||||
SKIP_SPACES (str);
|
||||
|
||||
color = symbolic_color_parse_str (str, &end);
|
||||
|
||||
str = end;
|
||||
SKIP_SPACES (str);
|
||||
|
||||
if (*str != ')')
|
||||
color = _gtk_css_parser_read_symbolic_color (parser);
|
||||
if (color == NULL)
|
||||
{
|
||||
if (color)
|
||||
gtk_symbolic_color_unref (color);
|
||||
g_object_unref (gradient);
|
||||
return set_default_error (error, G_VALUE_TYPE (value));
|
||||
gtk_gradient_unref (gradient);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
str++;
|
||||
SKIP_SPACES (str);
|
||||
|
||||
if (color)
|
||||
{
|
||||
gtk_gradient_add_color_stop (gradient, position, color);
|
||||
gtk_symbolic_color_unref (color);
|
||||
}
|
||||
}
|
||||
|
||||
if (*str != ')')
|
||||
if (!_gtk_css_parser_try (parser, ")", TRUE))
|
||||
{
|
||||
g_object_unref (gradient);
|
||||
return set_default_error (error, G_VALUE_TYPE (value));
|
||||
gtk_gradient_unref (gradient);
|
||||
_gtk_css_parser_error (parser,
|
||||
"Expected ')'");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
g_value_take_boxed (value, gradient);
|
||||
if (!_gtk_css_parser_try (parser, ")", TRUE))
|
||||
{
|
||||
gtk_gradient_unref (gradient);
|
||||
_gtk_css_parser_error (parser,
|
||||
"Expected ')'");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return gradient;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gradient_value_from_string (const char *str,
|
||||
GFile *base,
|
||||
GValue *value,
|
||||
GError **error)
|
||||
{
|
||||
GtkGradient *gradient;
|
||||
GtkCssParser *parser;
|
||||
|
||||
parser = _gtk_css_parser_new (str,
|
||||
propagate_parser_error,
|
||||
error);
|
||||
gradient = _gtk_css_parse_gradient (parser);
|
||||
_gtk_css_parser_free (parser);
|
||||
|
||||
if (gradient == NULL)
|
||||
return FALSE;
|
||||
|
||||
g_value_set_boxed (value, gradient);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@ -1422,7 +1174,7 @@ flags_value_from_string (const char *str,
|
||||
{
|
||||
g_set_error (error,
|
||||
GTK_CSS_PROVIDER_ERROR,
|
||||
GTK_CSS_PROVIDER_ERROR_PROPERTY_NAME,
|
||||
GTK_CSS_PROVIDER_ERROR_SYNTAX,
|
||||
"Unknown flag value '%s' for type '%s'",
|
||||
strv[i], g_type_name (G_VALUE_TYPE (value)));
|
||||
g_type_class_unref (flags_class);
|
||||
@ -1559,7 +1311,7 @@ _gtk_css_value_from_string (GValue *value,
|
||||
{
|
||||
g_set_error (error,
|
||||
GTK_CSS_PROVIDER_ERROR,
|
||||
GTK_CSS_PROVIDER_ERROR_PROPERTY_VALUE,
|
||||
GTK_CSS_PROVIDER_ERROR_SYNTAX,
|
||||
"Cannot convert to type '%s'",
|
||||
g_type_name (G_VALUE_TYPE (value)));
|
||||
return FALSE;
|
||||
@ -1587,32 +1339,6 @@ _gtk_css_value_to_string (const GValue *value)
|
||||
return g_strdup_value_contents (value);
|
||||
}
|
||||
|
||||
GtkSymbolicColor *
|
||||
_gtk_css_parse_symbolic_color (const char *str,
|
||||
GError **error)
|
||||
{
|
||||
GtkSymbolicColor *color;
|
||||
gchar *end;
|
||||
|
||||
color = symbolic_color_parse_str (str, &end);
|
||||
|
||||
if (*end != '\0')
|
||||
{
|
||||
if (color)
|
||||
{
|
||||
gtk_symbolic_color_unref (color);
|
||||
color = NULL;
|
||||
}
|
||||
|
||||
g_set_error_literal (error,
|
||||
GTK_CSS_PROVIDER_ERROR,
|
||||
GTK_CSS_PROVIDER_ERROR_PROPERTY_VALUE,
|
||||
"Failed to parse symbolic color");
|
||||
}
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
GFile *
|
||||
_gtk_css_parse_url (GFile *base,
|
||||
const char *str,
|
||||
@ -1631,7 +1357,7 @@ _gtk_css_parse_url (GFile *base,
|
||||
{
|
||||
g_set_error_literal (error,
|
||||
GTK_CSS_PROVIDER_ERROR,
|
||||
GTK_CSS_PROVIDER_ERROR_PROPERTY_VALUE,
|
||||
GTK_CSS_PROVIDER_ERROR_SYNTAX,
|
||||
"Expected '(' after 'url'");
|
||||
return NULL;
|
||||
}
|
||||
@ -1641,7 +1367,7 @@ _gtk_css_parse_url (GFile *base,
|
||||
{
|
||||
g_set_error_literal (error,
|
||||
GTK_CSS_PROVIDER_ERROR,
|
||||
GTK_CSS_PROVIDER_ERROR_PROPERTY_VALUE,
|
||||
GTK_CSS_PROVIDER_ERROR_SYNTAX,
|
||||
"No closing ')' found for 'url'");
|
||||
return NULL;
|
||||
}
|
||||
@ -1665,7 +1391,7 @@ _gtk_css_parse_url (GFile *base,
|
||||
{
|
||||
g_set_error_literal (error,
|
||||
GTK_CSS_PROVIDER_ERROR,
|
||||
GTK_CSS_PROVIDER_ERROR_PROPERTY_VALUE,
|
||||
GTK_CSS_PROVIDER_ERROR_SYNTAX,
|
||||
"Did not find closing quote for url");
|
||||
return NULL;
|
||||
}
|
||||
@ -1674,7 +1400,7 @@ _gtk_css_parse_url (GFile *base,
|
||||
{
|
||||
g_set_error_literal (error,
|
||||
GTK_CSS_PROVIDER_ERROR,
|
||||
GTK_CSS_PROVIDER_ERROR_PROPERTY_VALUE,
|
||||
GTK_CSS_PROVIDER_ERROR_SYNTAX,
|
||||
"url not properly escaped");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -30,9 +30,6 @@ gboolean _gtk_css_value_from_string (GValue *value,
|
||||
GError **error);
|
||||
char * _gtk_css_value_to_string (const GValue *value);
|
||||
|
||||
GtkSymbolicColor * _gtk_css_parse_symbolic_color (const char *str,
|
||||
GError **error);
|
||||
|
||||
GFile * _gtk_css_parse_url (GFile *base,
|
||||
const char *str,
|
||||
char **end,
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
boolean.css:26: error: GTK_CSS_PROVIDER_ERROR_PROPERTY_VALUE
|
||||
boolean.css:29: error: GTK_CSS_PROVIDER_ERROR_PROPERTY_VALUE
|
||||
boolean.css:32: error: GTK_CSS_PROVIDER_ERROR_PROPERTY_VALUE
|
||||
boolean.css:35: error: GTK_CSS_PROVIDER_ERROR_PROPERTY_VALUE
|
||||
boolean.css:38: error: GTK_CSS_PROVIDER_ERROR_PROPERTY_VALUE
|
||||
boolean.css:41: error: GTK_CSS_PROVIDER_ERROR_PROPERTY_VALUE
|
||||
boolean.css:44: error: GTK_CSS_PROVIDER_ERROR_PROPERTY_VALUE
|
||||
boolean.css:47: error: GTK_CSS_PROVIDER_ERROR_PROPERTY_VALUE
|
||||
boolean.css:26: error: GTK_CSS_PROVIDER_ERROR_SYNTAX
|
||||
boolean.css:29: error: GTK_CSS_PROVIDER_ERROR_SYNTAX
|
||||
boolean.css:32: error: GTK_CSS_PROVIDER_ERROR_SYNTAX
|
||||
boolean.css:35: error: GTK_CSS_PROVIDER_ERROR_SYNTAX
|
||||
boolean.css:38: error: GTK_CSS_PROVIDER_ERROR_SYNTAX
|
||||
boolean.css:41: error: GTK_CSS_PROVIDER_ERROR_SYNTAX
|
||||
boolean.css:44: error: GTK_CSS_PROVIDER_ERROR_SYNTAX
|
||||
boolean.css:47: error: GTK_CSS_PROVIDER_ERROR_SYNTAX
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
border.css:26: error: GTK_CSS_PROVIDER_ERROR_PROPERTY_VALUE
|
||||
border.css:30: error: GTK_CSS_PROVIDER_ERROR_PROPERTY_VALUE
|
||||
border.css:34: error: GTK_CSS_PROVIDER_ERROR_PROPERTY_VALUE
|
||||
border.css:38: error: GTK_CSS_PROVIDER_ERROR_PROPERTY_VALUE
|
||||
border.css:42: error: GTK_CSS_PROVIDER_ERROR_PROPERTY_VALUE
|
||||
border.css:46: error: GTK_CSS_PROVIDER_ERROR_PROPERTY_VALUE
|
||||
border.css:50: error: GTK_CSS_PROVIDER_ERROR_PROPERTY_VALUE
|
||||
border.css:54: error: GTK_CSS_PROVIDER_ERROR_PROPERTY_NAME
|
||||
border.css:26: error: GTK_CSS_PROVIDER_ERROR_SYNTAX
|
||||
border.css:30: error: GTK_CSS_PROVIDER_ERROR_SYNTAX
|
||||
border.css:34: error: GTK_CSS_PROVIDER_ERROR_SYNTAX
|
||||
border.css:38: error: GTK_CSS_PROVIDER_ERROR_SYNTAX
|
||||
border.css:42: error: GTK_CSS_PROVIDER_ERROR_SYNTAX
|
||||
border.css:46: error: GTK_CSS_PROVIDER_ERROR_SYNTAX
|
||||
border.css:50: error: GTK_CSS_PROVIDER_ERROR_SYNTAX
|
||||
border.css:54: error: GTK_CSS_PROVIDER_ERROR_SYNTAX
|
||||
|
||||
@ -1 +1 @@
|
||||
does-not-exist.css:2: error: GTK_CSS_PROVIDER_ERROR_PROPERTY_NAME
|
||||
does-not-exist.css:2: error: GTK_CSS_PROVIDER_ERROR_NAME
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
integer.css:17: error: GTK_CSS_PROVIDER_ERROR_PROPERTY_VALUE
|
||||
integer.css:20: error: GTK_CSS_PROVIDER_ERROR_PROPERTY_VALUE
|
||||
integer.css:23: error: GTK_CSS_PROVIDER_ERROR_PROPERTY_VALUE
|
||||
integer.css:29: error: GTK_CSS_PROVIDER_ERROR_PROPERTY_VALUE
|
||||
integer.css:32: error: GTK_CSS_PROVIDER_ERROR_PROPERTY_VALUE
|
||||
integer.css:17: error: GTK_CSS_PROVIDER_ERROR_SYNTAX
|
||||
integer.css:20: error: GTK_CSS_PROVIDER_ERROR_SYNTAX
|
||||
integer.css:23: error: GTK_CSS_PROVIDER_ERROR_SYNTAX
|
||||
integer.css:29: error: GTK_CSS_PROVIDER_ERROR_SYNTAX
|
||||
integer.css:32: error: GTK_CSS_PROVIDER_ERROR_SYNTAX
|
||||
integer.css:35: error: GTK_CSS_PROVIDER_ERROR_SYNTAX
|
||||
integer.css:38: error: GTK_CSS_PROVIDER_ERROR_PROPERTY_VALUE
|
||||
integer.css:41: error: GTK_CSS_PROVIDER_ERROR_PROPERTY_VALUE
|
||||
integer.css:38: error: GTK_CSS_PROVIDER_ERROR_SYNTAX
|
||||
integer.css:41: error: GTK_CSS_PROVIDER_ERROR_SYNTAX
|
||||
|
||||
Reference in New Issue
Block a user