Esempio n. 1
0
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;
}
Esempio n. 2
0
gboolean
_gtk_css_parser_is_string (GtkCssParser *parser)
{
  g_return_val_if_fail (GTK_IS_CSS_PARSER (parser), FALSE);

  return *parser->data == '"' || *parser->data == '\'';
}
Esempio n. 3
0
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 != '\'')
    {
      _gtk_css_parser_error (parser, "Expected a string.");
      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;
}
Esempio n. 4
0
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;
}
Esempio n. 5
0
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);
}
Esempio n. 6
0
guint
_gtk_css_parser_get_line (GtkCssParser *parser)
{
  g_return_val_if_fail (GTK_IS_CSS_PARSER (parser), 1);

  return parser->line;
}
Esempio n. 7
0
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;
}
Esempio n. 8
0
void
_gtk_css_parser_free (GtkCssParser *parser)
{
  g_return_if_fail (GTK_IS_CSS_PARSER (parser));

  g_slice_free (GtkCssParser, parser);
}
Esempio n. 9
0
gboolean
_gtk_css_parser_is_eof (GtkCssParser *parser)
{
  g_return_val_if_fail (GTK_IS_CSS_PARSER (parser), TRUE);

  return *parser->data == 0;
}
Esempio n. 10
0
gboolean
_gtk_css_parser_try_uint (GtkCssParser *parser,
                          guint        *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;
}
Esempio n. 11
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;
}
Esempio n. 12
0
gboolean
_gtk_css_parser_has_prefix (GtkCssParser *parser,
                            const char   *prefix)
{
  g_return_val_if_fail (GTK_IS_CSS_PARSER (parser), FALSE);

  return g_ascii_strncasecmp (parser->data, prefix, strlen (prefix)) == 0;
}
Esempio n. 13
0
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);
}
Esempio n. 14
0
void
_gtk_css_parser_free (GtkCssParser *parser)
{
  g_return_if_fail (GTK_IS_CSS_PARSER (parser));

  if (parser->file)
    g_object_unref (parser->file);

  g_slice_free (GtkCssParser, parser);
}
Esempio n. 15
0
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;
}
Esempio n. 16
0
gboolean
_gtk_css_parser_try_enum (GtkCssParser *parser,
			  GType         enum_type,
			  int          *value)
{
  GEnumClass *enum_class;
  gboolean result;
  const char *start;
  char *str;

  g_return_val_if_fail (GTK_IS_CSS_PARSER (parser), FALSE);
  g_return_val_if_fail (value != NULL, FALSE);

  result = FALSE;

  enum_class = g_type_class_ref (enum_type);

  start = parser->data;

  str = _gtk_css_parser_try_ident (parser, TRUE);
  if (str == NULL)
    return FALSE;

  if (enum_class->n_values)
    {
      GEnumValue *enum_value;

      for (enum_value = enum_class->values; enum_value->value_name; enum_value++)
	{
	  if (enum_value->value_nick &&
	      g_ascii_strcasecmp (str, enum_value->value_nick) == 0)
	    {
	      *value = enum_value->value;
	      result = TRUE;
	      break;
	    }
	}
    }

  g_free (str);
  g_type_class_unref (enum_class);

  if (!result)
    parser->data = start;

  return result;
}
Esempio n. 17
0
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;
}
Esempio n. 18
0
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);
}
Esempio n. 19
0
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;
}
Esempio n. 20
0
GtkCssValue *
_gtk_css_number_value_parse (GtkCssParser           *parser,
                             GtkCssNumberParseFlags  flags)
{
  static const struct {
    const char *name;
    GtkCssUnit unit;
    GtkCssNumberParseFlags required_flags;
  } units[] = {
    { "px",   GTK_CSS_PX,      GTK_CSS_PARSE_LENGTH },
    { "pt",   GTK_CSS_PT,      GTK_CSS_PARSE_LENGTH },
    { "em",   GTK_CSS_EM,      GTK_CSS_PARSE_LENGTH },
    { "ex",   GTK_CSS_EX,      GTK_CSS_PARSE_LENGTH },
    { "pc",   GTK_CSS_PC,      GTK_CSS_PARSE_LENGTH },
    { "in",   GTK_CSS_IN,      GTK_CSS_PARSE_LENGTH },
    { "cm",   GTK_CSS_CM,      GTK_CSS_PARSE_LENGTH },
    { "mm",   GTK_CSS_MM,      GTK_CSS_PARSE_LENGTH },
    { "rad",  GTK_CSS_RAD,     GTK_CSS_PARSE_ANGLE  },
    { "deg",  GTK_CSS_DEG,     GTK_CSS_PARSE_ANGLE  },
    { "grad", GTK_CSS_GRAD,    GTK_CSS_PARSE_ANGLE  },
    { "turn", GTK_CSS_TURN,    GTK_CSS_PARSE_ANGLE  },
    { "s",    GTK_CSS_S,       GTK_CSS_PARSE_TIME   },
    { "ms",   GTK_CSS_MS,      GTK_CSS_PARSE_TIME   }
  };
  char *end, *unit_name;
  double value;
  GtkCssUnit unit;

  g_return_val_if_fail (GTK_IS_CSS_PARSER (parser), NULL);

  errno = 0;
  value = g_ascii_strtod (parser->data, &end);
  if (errno)
    {
      _gtk_css_parser_error (parser, "not a number: %s", g_strerror (errno));
      return NULL;
    }
  if (parser->data == end)
    {
      _gtk_css_parser_error (parser, "not a number");
      return NULL;
    }

  parser->data = end;

  if (flags & GTK_CSS_POSITIVE_ONLY &&
      value < 0)
    {
      _gtk_css_parser_error (parser, "negative values are not allowed.");
      return NULL;
    }

  unit_name = _gtk_css_parser_try_ident (parser, FALSE);

  if (unit_name)
    {
      guint i;

      for (i = 0; i < G_N_ELEMENTS (units); i++)
        {
          if (flags & units[i].required_flags &&
              g_ascii_strcasecmp (unit_name, units[i].name) == 0)
            break;
        }

      if (i >= G_N_ELEMENTS (units))
        {
          _gtk_css_parser_error (parser, "`%s' is not a valid unit.", unit_name);
          g_free (unit_name);
          return NULL;
        }

      unit = units[i].unit;

      g_free (unit_name);
    }
  else
    {
      if ((flags & GTK_CSS_PARSE_PERCENT) &&
          _gtk_css_parser_try (parser, "%", FALSE))
        {
          unit = GTK_CSS_PERCENT;
        }
      else if (value == 0.0)
        {
          if (flags & GTK_CSS_PARSE_NUMBER)
            unit = GTK_CSS_NUMBER;
          else if (flags & GTK_CSS_PARSE_LENGTH)
            unit = GTK_CSS_PX;
          else if (flags & GTK_CSS_PARSE_ANGLE)
            unit = GTK_CSS_DEG;
          else if (flags & GTK_CSS_PARSE_TIME)
            unit = GTK_CSS_S;
          else
            unit = GTK_CSS_PERCENT;
        }
      else if (flags & GTK_CSS_NUMBER_AS_PIXELS)
        {
          _gtk_css_parser_error_full (parser,
                                      GTK_CSS_PROVIDER_ERROR_DEPRECATED,
                                      "Not using units is deprecated. Assuming 'px'.");
          unit = GTK_CSS_PX;
        }
      else if (flags & GTK_CSS_PARSE_NUMBER)
        {
          unit = GTK_CSS_NUMBER;
        }
      else
        {
          _gtk_css_parser_error (parser, "Unit is missing.");
          return NULL;
        }
    }

  _gtk_css_parser_skip_whitespace (parser);

  return _gtk_css_number_value_new (value, unit);
}
Esempio n. 21
0
GtkSymbolicColor *
_gtk_css_parser_read_symbolic_color (GtkCssParser *parser)
{
  GtkSymbolicColor *symbolic;
  guint color;
  const char *names[] = {"rgba", "rgb",  "lighter", "darker", "shade", "alpha", "mix",
			 GTK_WIN32_THEME_SYMBOLIC_COLOR_NAME};
  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;
}