static gboolean check_parent (GMarkupParseContext *context, const gchar *element_name, GError **error) { const GSList *stack; const gchar *parent_name; const gchar *our_name; stack = g_markup_parse_context_get_element_stack (context); our_name = stack->data; parent_name = stack->next ? stack->next->data : ""; if (g_strcmp0 (parent_name, element_name) != 0) { gint line; gint col; g_markup_parse_context_get_position (context, &line, &col); g_set_error (error, GTK_BUILDER_ERROR, GTK_BUILDER_ERROR_INVALID_TAG, "%d:%d: Element <%s> found in <%s>, expected <%s>.", line, col, our_name, parent_name, element_name); return FALSE; } return TRUE; }
static void start_element (GMarkupParseContext *context, const gchar *element_name, const gchar **attribute_names, const gchar **attribute_values, gpointer user_data, GError **error) { ParseState *state = user_data; const GSList *element_stack; const gchar *container; element_stack = g_markup_parse_context_get_element_stack (context); container = element_stack->next ? element_stack->next->data : NULL; #define COLLECT(first, ...) \ g_markup_collect_attributes (element_name, \ attribute_names, attribute_values, error, \ first, __VA_ARGS__, G_MARKUP_COLLECT_INVALID) #define OPTIONAL G_MARKUP_COLLECT_OPTIONAL #define STRDUP G_MARKUP_COLLECT_STRDUP #define STRING G_MARKUP_COLLECT_STRING #define BOOL G_MARKUP_COLLECT_BOOLEAN #define NO_ATTRS() COLLECT (G_MARKUP_COLLECT_INVALID, NULL) if (container == NULL) { if (strcmp (element_name, "gresources") == 0) return; } else if (strcmp (container, "gresources") == 0) { if (strcmp (element_name, "gresource") == 0) { COLLECT (OPTIONAL | STRDUP, "prefix", &state->prefix); return; } } else if (strcmp (container, "gresource") == 0) { if (strcmp (element_name, "file") == 0) { COLLECT (OPTIONAL | STRDUP, "alias", &state->alias, OPTIONAL | BOOL, "compressed", &state->compressed, OPTIONAL | STRDUP, "preprocess", &state->preproc_options); state->string = g_string_new (""); return; } } if (container) g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_UNKNOWN_ELEMENT, _("Element <%s> not allowed inside <%s>"), element_name, container); else g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_UNKNOWN_ELEMENT, _("Element <%s> not allowed at toplevel"), element_name); }
void KeyConfig::start_element(GMarkupParseContext *context, const char *element_name, const char **attribute_names, const char **attribute_values, GError **error) { const GSList *stack = g_markup_parse_context_get_element_stack(context); guint size = g_slist_length(const_cast<GSList*>(stack)); if (size == 1) { if (strcmp(element_name, "keyconfig")) { *error = g_error_new(g_markup_error_quark(), G_MARKUP_ERROR_PARSE, _("Expected 'keyconfig' element, found '%s'"), element_name); } } else if (size == 2) { if (strcmp(element_name, "bind")) { *error = g_error_new(g_markup_error_quark(), G_MARKUP_ERROR_PARSE, _("Expected 'bind' element, found '%s'"), element_name); return; } const char *context; const char *action; const char *key; if (!g_markup_collect_attributes (element_name, attribute_names, attribute_values, error, G_MARKUP_COLLECT_STRING, "context", &context, G_MARKUP_COLLECT_STRING, "action", &action, G_MARKUP_COLLECT_STRING, "key", &key, G_MARKUP_COLLECT_INVALID)) return; if (!BindKey(context, action, key)) { *error = g_error_new(g_markup_error_quark(), G_MARKUP_ERROR_INVALID_CONTENT, _("Unrecognized key '%s'"), key); return; } } else *error = g_error_new(g_markup_error_quark(), G_MARKUP_ERROR_PARSE, _("Unexpected element '%s'"), element_name); }
static void views_parser_start_element (GMarkupParseContext *context, const gchar *element_name, const gchar **attribute_names, const gchar **attribute_values, gpointer user_data, GError **error) { ViewsParserData *parser_data = user_data; GtkWidget *item; g_assert (context != NULL); g_assert (element_name != NULL); g_assert (parser_data != NULL); if (g_strcmp0 (element_name, "views") == 0) { } else if (g_strcmp0 (element_name, "view") == 0) { const gchar *name = NULL; if (!check_parent (context, "views", error)) return; if (!g_markup_collect_attributes (element_name, attribute_names, attribute_values, error, G_MARKUP_COLLECT_STRING, "name", &name, G_MARKUP_COLLECT_INVALID)) return; item = g_object_new (GB_TYPE_SHORTCUTS_VIEW, "view-name", name, "visible", TRUE, NULL); g_queue_push_head (parser_data->stack, g_object_ref_sink (item)); } else if (g_strcmp0 (element_name, "page") == 0) { if (!check_parent (context, "view", error)) return; item = g_object_new (GB_TYPE_SHORTCUTS_PAGE, "visible", TRUE, NULL); g_queue_push_head (parser_data->stack, g_object_ref_sink (item)); } else if (g_strcmp0 (element_name, "column") == 0) { GtkSizeGroup *size_group; if (!check_parent (context, "page", error)) return; size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL); g_queue_push_head (parser_data->column_image_size_groups, size_group); size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL); g_queue_push_head (parser_data->column_desc_size_groups, size_group); item = g_object_new (GB_TYPE_SHORTCUTS_COLUMN, "visible", TRUE, NULL); g_queue_push_head (parser_data->stack, g_object_ref_sink (item)); } else if (g_strcmp0 (element_name, "group") == 0) { if (!check_parent (context, "column", error)) return; item = g_object_new (GB_TYPE_SHORTCUTS_GROUP, "visible", TRUE, NULL); g_queue_push_head (parser_data->stack, g_object_ref_sink (item)); } else if (g_strcmp0 (element_name, "shortcut") == 0) { GtkSizeGroup *accel_size_group; GtkSizeGroup *desc_size_group; if (!check_parent (context, "group", error)) return; accel_size_group = g_queue_peek_head (parser_data->column_image_size_groups); desc_size_group = g_queue_peek_head (parser_data->column_desc_size_groups); parser_data->search_item = g_object_new (GB_TYPE_SHORTCUTS_SHORTCUT, "visible", TRUE, NULL); item = g_object_new (GB_TYPE_SHORTCUTS_SHORTCUT, "accelerator-size-group", accel_size_group, "title-size-group", desc_size_group, "visible", TRUE, NULL); g_queue_push_head (parser_data->stack, g_object_ref_sink (item)); } else if (g_strcmp0 (element_name, "gesture") == 0) { GtkSizeGroup *accel_size_group; GtkSizeGroup *desc_size_group; if (!check_parent (context, "group", error)) return; accel_size_group = g_queue_peek_head (parser_data->column_image_size_groups); desc_size_group = g_queue_peek_head (parser_data->column_desc_size_groups); parser_data->search_item = g_object_new (GB_TYPE_SHORTCUTS_GESTURE, "visible", TRUE, NULL); item = g_object_new (GB_TYPE_SHORTCUTS_GESTURE, "desc-size-group", desc_size_group, "icon-size-group", accel_size_group, "visible", TRUE, NULL); g_queue_push_head (parser_data->stack, g_object_ref_sink (item)); } else if (g_strcmp0 (element_name, "property") == 0) { const gchar *name = NULL; const gchar *translatable = NULL; item = g_queue_peek_head (parser_data->stack); if (item == NULL) { g_set_error (error, GTK_BUILDER_ERROR, GTK_BUILDER_ERROR_INVALID_TAG, "Property called without a parent object"); return; } if (!g_markup_collect_attributes (element_name, attribute_names, attribute_values, error, G_MARKUP_COLLECT_STRING, "name", &name, G_MARKUP_COLLECT_OPTIONAL | G_MARKUP_COLLECT_STRING, "translatable", &translatable, G_MARKUP_COLLECT_INVALID)) return; g_free (parser_data->property_name); parser_data->property_name = g_strdup (name); parser_data->translatable = (g_strcmp0 (translatable, "yes") == 0); } else { const GSList *stack; const gchar *parent_name; const gchar *our_name; gint line; gint col; stack = g_markup_parse_context_get_element_stack (context); our_name = stack->data; parent_name = stack->next ? stack->next->data : ""; g_markup_parse_context_get_position (context, &line, &col); g_set_error (error, GTK_BUILDER_ERROR, GTK_BUILDER_ERROR_INVALID_TAG, "%d:%d: Unknown element <%s> found in <%s>.", line, col, our_name, parent_name); } }
static void start_element (GMarkupParseContext *context, const gchar *element_name, const gchar **attribute_names, const gchar **attribute_values, gpointer user_data, GError **error) { ParseState *state = user_data; const GSList *element_stack; const gchar *container; element_stack = g_markup_parse_context_get_element_stack (context); container = element_stack->next ? element_stack->next->data : NULL; #define COLLECT(first, ...) \ g_markup_collect_attributes (element_name, \ attribute_names, attribute_values, error, \ first, __VA_ARGS__, G_MARKUP_COLLECT_INVALID) #define OPTIONAL G_MARKUP_COLLECT_OPTIONAL #define STRDUP G_MARKUP_COLLECT_STRDUP #define STRING G_MARKUP_COLLECT_STRING #define NO_ATTRS() COLLECT (G_MARKUP_COLLECT_INVALID, NULL) if (container == NULL) { if (strcmp (element_name, "schemalist") == 0) { COLLECT (OPTIONAL | STRDUP, "gettext-domain", &state->schemalist_domain); return; } } else if (strcmp (container, "schemalist") == 0) { if (strcmp (element_name, "schema") == 0) { const gchar *id, *path; if (COLLECT (STRING, "id", &id, OPTIONAL | STRING, "path", &path, OPTIONAL | STRDUP, "gettext-domain", &state->schema_domain)) { if (!g_hash_table_lookup (state->schemas, id)) { state->schema = gvdb_hash_table_new (state->schemas, id); state->schema_root = gvdb_hash_table_insert (state->schema, ""); if (path != NULL) gvdb_hash_table_insert_string (state->schema, ".path", path); } else g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, "<schema id='%s'> already specified", id); } return; } } else if (strcmp (container, "schema") == 0) { if (strcmp (element_name, "key") == 0) { const gchar *name, *type; if (COLLECT (STRING, "name", &name, STRING, "type", &type)) { if (!is_valid_keyname (name, error)) return; if (!g_hash_table_lookup (state->schema, name)) { state->key = gvdb_hash_table_insert (state->schema, name); gvdb_item_set_parent (state->key, state->schema_root); } else { g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, "<key name='%s'> already specified", name); return; } if (g_variant_type_string_is_valid (type)) state->type = g_variant_type_new (type); else { g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, "invalid GVariant type string '%s'", type); return; } g_variant_builder_init (&state->key_options, G_VARIANT_TYPE ("a{sv}")); } return; } else if (strcmp (element_name, "child") == 0) { const gchar *name, *schema; if (COLLECT (STRING, "name", &name, STRING, "schema", &schema)) { gchar *childname; if (!is_valid_keyname (name, error)) return; childname = g_strconcat (name, "/", NULL); if (!g_hash_table_lookup (state->schema, childname)) gvdb_hash_table_insert_string (state->schema, childname, schema); else g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, "<child name='%s'> already specified", name); g_free (childname); return; } } } else if (strcmp (container, "key") == 0) { if (strcmp (element_name, "default") == 0) { const gchar *l10n; if (COLLECT (STRING | OPTIONAL, "l10n", &l10n, STRDUP | OPTIONAL, "context", &state->context)) { if (l10n != NULL) { if (!g_hash_table_lookup (state->schema, ".gettext-domain")) { const gchar *domain = state->schema_domain ? state->schema_domain : state->schemalist_domain; if (domain == NULL) { g_set_error_literal (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, "l10n requested, but no " "gettext domain given"); return; } gvdb_hash_table_insert_string (state->schema, ".gettext-domain", domain); if (strcmp (l10n, "messages") == 0) state->l10n = 'm'; else if (strcmp (l10n, "time") == 0) state->l10n = 't'; else { g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, "unsupported l10n category: %s", l10n); return; } } } else { state->l10n = '\0'; if (state->context != NULL) { g_set_error_literal (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, "translation context given for " " value without l10n enabled"); return; } } state->string = g_string_new (NULL); } return; } else if (strcmp (element_name, "summary") == 0 || strcmp (element_name, "description") == 0) { state->string = g_string_new (NULL); NO_ATTRS (); return; } else if (strcmp (element_name, "range") == 0) { const gchar *min_str, *max_str; if (!type_allows_range (state->type)) { gchar *type = g_variant_type_dup_string (state->type); g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, "Element <%s> not allowed for keys of type \"%s\"\n", element_name, type); g_free (type); return; } if (!COLLECT (STRING, "min", &min_str, STRING, "max", &max_str)) return; state->min = g_variant_parse (state->type, min_str, NULL, NULL, error); if (state->min == NULL) return; state->max = g_variant_parse (state->type, max_str, NULL, NULL, error); if (state->max == NULL) return; if (g_variant_compare (state->min, state->max) > 0) { g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, "Element <%s> specified minimum is greater than maxmimum", element_name); return; } g_variant_builder_add (&state->key_options, "{sv}", "range", g_variant_new ("(@?@?)", state->min, state->max)); return; } else if (strcmp (element_name, "choices") == 0) { if (!type_allows_choices (state->type)) { gchar *type = g_variant_type_dup_string (state->type); g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, "Element <%s> not allowed for keys of type \"%s\"\n", element_name, type); g_free (type); return; } state->choices = g_string_new ("\xff"); NO_ATTRS (); return; } } else if (strcmp (container, "choices") == 0) { if (strcmp (element_name, "choice") == 0) { const gchar *value; if (COLLECT (STRING, "value", &value)) g_string_append_printf (state->choices, "%s\xff", value); return; } } if (container) g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_UNKNOWN_ELEMENT, "Element <%s> not allowed inside <%s>\n", element_name, container); else g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_UNKNOWN_ELEMENT, "Element <%s> not allowed at toplevel\n", element_name); }