diff --git a/gtk/gtkaccessiblevalue.c b/gtk/gtkaccessiblevalue.c index 2cefba0bc4..45bf824648 100644 --- a/gtk/gtkaccessiblevalue.c +++ b/gtk/gtkaccessiblevalue.c @@ -49,6 +49,7 @@ #include #include +#include G_DEFINE_QUARK (gtk-accessible-value-error-quark, gtk_accessible_value_error) @@ -637,6 +638,7 @@ typedef struct { */ GCallback ctor; GCallback getter; + GCallback parser; } GtkAccessibleCollect; static const GtkAccessibleCollect collect_states[] = { @@ -670,7 +672,8 @@ static const GtkAccessibleCollect collect_states[] = { .ctype = GTK_ACCESSIBLE_COLLECT_TOKEN, .name = "invalid", .ctor = (GCallback) gtk_invalid_accessible_value_new, - .getter = (GCallback) gtk_invalid_accessible_value_get + .getter = (GCallback) gtk_invalid_accessible_value_get, + .parser = (GCallback) gtk_invalid_accessible_value_parse, }, [GTK_ACCESSIBLE_STATE_PRESSED] = { .value = GTK_ACCESSIBLE_STATE_PRESSED, @@ -691,7 +694,8 @@ static const GtkAccessibleCollect collect_props[] = { .ctype = GTK_ACCESSIBLE_COLLECT_TOKEN, .name = "autocomplete", .ctor = (GCallback) gtk_autocomplete_accessible_value_new, - .getter = (GCallback) gtk_autocomplete_accessible_value_get + .getter = (GCallback) gtk_autocomplete_accessible_value_get, + .parser = (GCallback) gtk_autocomplete_accessible_value_parse, }, [GTK_ACCESSIBLE_PROPERTY_DESCRIPTION] = { .value = GTK_ACCESSIBLE_PROPERTY_DESCRIPTION, @@ -742,7 +746,8 @@ static const GtkAccessibleCollect collect_props[] = { .ctype = GTK_ACCESSIBLE_COLLECT_TOKEN | GTK_ACCESSIBLE_COLLECT_UNDEFINED, .name = "orientation", .ctor = (GCallback) gtk_orientation_accessible_value_new, - .getter = (GCallback) gtk_orientation_accessible_value_get + .getter = (GCallback) gtk_orientation_accessible_value_get, + .parser = (GCallback) gtk_orientation_accessible_value_parse, }, [GTK_ACCESSIBLE_PROPERTY_PLACEHOLDER] = { .value = GTK_ACCESSIBLE_PROPERTY_PLACEHOLDER, @@ -769,7 +774,8 @@ static const GtkAccessibleCollect collect_props[] = { .ctype = GTK_ACCESSIBLE_COLLECT_TOKEN, .name = "sort", .ctor = (GCallback) gtk_sort_accessible_value_new, - .getter = (GCallback) gtk_sort_accessible_value_get + .getter = (GCallback) gtk_sort_accessible_value_get, + .parser = (GCallback) gtk_sort_accessible_value_parse, }, [GTK_ACCESSIBLE_PROPERTY_VALUE_MAX] = { .value = GTK_ACCESSIBLE_PROPERTY_VALUE_MAX, @@ -896,6 +902,10 @@ typedef GtkAccessibleValue * (* GtkAccessibleValueStringCtor) (const char *val typedef GtkAccessibleValue * (* GtkAccessibleValueRefCtor) (GtkAccessible *value); typedef GtkAccessibleValue * (* GtkAccessibleValueRefListCtor) (GList *value); +typedef GtkAccessibleValue * (* GtkAccessibleValueEnumParser) (const char *str, + gsize len, + GError **error); + /*< private > * gtk_accessible_value_get_default_for_state: * @state: a #GtkAccessibleState @@ -1314,6 +1324,144 @@ gtk_accessible_value_collect_value (const GtkAccessibleCollect *cstate, return res; } +static GtkAccessibleValue * +gtk_accessible_value_parse (const GtkAccessibleCollect *cstate, + const char *str, + gsize len, + GError **error) +{ + GtkAccessibleValue *res = NULL; + GtkAccessibleCollectType ctype = cstate->ctype; + gboolean collects_undef = (ctype & GTK_ACCESSIBLE_COLLECT_UNDEFINED) != 0; + + ctype &= (GTK_ACCESSIBLE_COLLECT_UNDEFINED - 1); + + /* Tristate values include "undefined" by definition */ + if (ctype == GTK_ACCESSIBLE_COLLECT_TRISTATE) + collects_undef = TRUE; + + switch (ctype) + { + case GTK_ACCESSIBLE_COLLECT_BOOLEAN: + { + if (strncmp (str, "true", 4) == 0) + res = gtk_boolean_accessible_value_new (TRUE); + else if (strncmp (str, "false", 5) == 0) + res = gtk_boolean_accessible_value_new (FALSE); + else if (collects_undef && strncmp (str, "undefined", 9) == 0) + res = gtk_undefined_accessible_value_new (); + else + g_set_error (error, GTK_ACCESSIBLE_VALUE_ERROR, + GTK_ACCESSIBLE_VALUE_ERROR_INVALID_TOKEN, + "Invalid token “%s” for boolean attribute", + str); + } + break; + + case GTK_ACCESSIBLE_COLLECT_TRISTATE: + { + if (strncmp (str, "true", 4) == 0) + res = gtk_tristate_accessible_value_new (GTK_ACCESSIBLE_TRISTATE_TRUE); + else if (strncmp (str, "false", 5) == 0) + res = gtk_tristate_accessible_value_new (GTK_ACCESSIBLE_TRISTATE_FALSE); + else if (strncmp (str, "mixed", 5) == 0) + res = gtk_tristate_accessible_value_new (GTK_ACCESSIBLE_TRISTATE_MIXED); + else if (collects_undef && strncmp (str, "undefined", 9) == 0) + res = gtk_undefined_accessible_value_new (); + else + { + g_set_error (error, GTK_ACCESSIBLE_VALUE_ERROR, + GTK_ACCESSIBLE_VALUE_ERROR_INVALID_TOKEN, + "Invalid token “%s” for tristate attribute", + str); + return NULL; + } + } + break; + + case GTK_ACCESSIBLE_COLLECT_TOKEN: + { + GtkAccessibleValueEnumParser parser = + (GtkAccessibleValueEnumParser) cstate->parser; + + if (collects_undef && strncmp (str, "undefined", 9) == 0) + { + res = gtk_undefined_accessible_value_new (); + } + else + { + /* Token collection requires a constructor */ + g_assert (parser != NULL); + + res = (* parser) (str, len, error); + } + } + break; + + case GTK_ACCESSIBLE_COLLECT_INTEGER: + { + char *end = NULL; + gint64 value = g_ascii_strtoll (str, &end, 10); + + if (str == end) + { + int saved_errno = errno; + g_set_error (error, GTK_ACCESSIBLE_VALUE_ERROR, + GTK_ACCESSIBLE_VALUE_ERROR_INVALID_VALUE, + "Invalid integer value “%s”: %s", + str, g_strerror (saved_errno)); + + return NULL; + } + else + res = gtk_int_accessible_value_new ((int) value); + } + break; + + case GTK_ACCESSIBLE_COLLECT_NUMBER: + { + char *end = NULL; + double value = g_ascii_strtod (str, &end); + + if (str == end || isnan (value) || isinf (value)) + { + g_set_error (error, GTK_ACCESSIBLE_VALUE_ERROR, + GTK_ACCESSIBLE_VALUE_ERROR_INVALID_VALUE, + "Invalid numeric value “%s”", + str); + return NULL; + } + + res = gtk_number_accessible_value_new (value); + } + break; + + case GTK_ACCESSIBLE_COLLECT_STRING: + { + res = gtk_string_accessible_value_new (str); + } + break; + + case GTK_ACCESSIBLE_COLLECT_REFERENCE: + case GTK_ACCESSIBLE_COLLECT_REFERENCE_LIST: + { + res = NULL; + g_set_error (error, GTK_ACCESSIBLE_VALUE_ERROR, + GTK_ACCESSIBLE_VALUE_ERROR_INVALID_VALUE, + "Invalid relation “%s”", + str); + } + break; + + case GTK_ACCESSIBLE_COLLECT_UNDEFINED: + case GTK_ACCESSIBLE_COLLECT_INVALID: + default: + g_assert_not_reached (); + break; + } + + return res; +} /*< private > * gtk_accessible_value_collect_for_state: * @state: a #GtkAccessibleState @@ -1370,6 +1518,19 @@ gtk_accessible_value_collect_for_state_value (GtkAccessibleState state, return gtk_accessible_value_collect_value (cstate, value, error); } +GtkAccessibleValue * +gtk_accessible_value_parse_for_state (GtkAccessibleState state, + const char *str, + gsize len, + GError **error) +{ + const GtkAccessibleCollect *cstate = &collect_states[state]; + + g_return_val_if_fail (state <= GTK_ACCESSIBLE_STATE_SELECTED, NULL); + + return gtk_accessible_value_parse (cstate, str, len, error); +} + /*< private > * gtk_accessible_value_get_default_for_property: * @property: a #GtkAccessibleProperty @@ -1487,6 +1648,19 @@ gtk_accessible_value_collect_for_property_value (GtkAccessibleProperty propert return gtk_accessible_value_collect_value (cstate, value, error); } +GtkAccessibleValue * +gtk_accessible_value_parse_for_property (GtkAccessibleProperty property, + const char *str, + gsize len, + GError **error) +{ + const GtkAccessibleCollect *cstate = &collect_props[property]; + + g_return_val_if_fail (property <= GTK_ACCESSIBLE_PROPERTY_VALUE_TEXT, NULL); + + return gtk_accessible_value_parse (cstate, str, len, error); +} + /*< private > * gtk_accessible_value_get_default_for_relation: * @relation: a #GtkAccessibleRelation @@ -1596,4 +1770,17 @@ gtk_accessible_value_collect_for_relation_value (GtkAccessibleRelation relatio return gtk_accessible_value_collect_value (cstate, value, error); } +GtkAccessibleValue * +gtk_accessible_value_parse_for_relation (GtkAccessibleRelation relation, + const char *str, + gsize len, + GError **error) +{ + const GtkAccessibleCollect *cstate = &collect_rels[relation]; + + g_return_val_if_fail (relation <= GTK_ACCESSIBLE_RELATION_SET_SIZE, NULL); + + return gtk_accessible_value_parse (cstate, str, len, error); +} + /* }}} */ diff --git a/gtk/gtkaccessiblevalueprivate.h b/gtk/gtkaccessiblevalueprivate.h index 073b2c2c45..3290fc1e6e 100644 --- a/gtk/gtkaccessiblevalueprivate.h +++ b/gtk/gtkaccessiblevalueprivate.h @@ -98,6 +98,10 @@ GtkAccessibleValue * gtk_accessible_value_collect_for_state (GtkAcce GtkAccessibleValue * gtk_accessible_value_collect_for_state_value (GtkAccessibleState state, const GValue *value, GError **error); +GtkAccessibleValue * gtk_accessible_value_parse_for_state (GtkAccessibleState state, + const char *str, + gsize len, + GError **error); GtkAccessibleValue * gtk_accessible_value_get_default_for_property (GtkAccessibleProperty property); GtkAccessibleValue * gtk_accessible_value_collect_for_property (GtkAccessibleProperty property, @@ -106,6 +110,10 @@ GtkAccessibleValue * gtk_accessible_value_collect_for_property (GtkAcce GtkAccessibleValue * gtk_accessible_value_collect_for_property_value (GtkAccessibleProperty property, const GValue *value, GError **error); +GtkAccessibleValue * gtk_accessible_value_parse_for_property (GtkAccessibleProperty property, + const char *str, + gsize len, + GError **error); GtkAccessibleValue * gtk_accessible_value_get_default_for_relation (GtkAccessibleRelation relation); GtkAccessibleValue * gtk_accessible_value_collect_for_relation (GtkAccessibleRelation relation, @@ -114,6 +122,10 @@ GtkAccessibleValue * gtk_accessible_value_collect_for_relation (GtkAcce GtkAccessibleValue * gtk_accessible_value_collect_for_relation_value (GtkAccessibleRelation relation, const GValue *value, GError **error); +GtkAccessibleValue * gtk_accessible_value_parse_for_relation (GtkAccessibleRelation relation, + const char *str, + gsize len, + GError **error); /* Basic values */ GtkAccessibleValue * gtk_undefined_accessible_value_new (void); @@ -143,14 +155,26 @@ GList * gtk_reference_list_accessible_value_get (const G /* Token values */ GtkAccessibleValue * gtk_invalid_accessible_value_new (GtkAccessibleInvalidState value); GtkAccessibleInvalidState gtk_invalid_accessible_value_get (const GtkAccessibleValue *value); +GtkAccessibleValue * gtk_invalid_accessible_value_parse (const char *str, + gsize len, + GError **error); GtkAccessibleValue * gtk_autocomplete_accessible_value_new (GtkAccessibleAutocomplete value); GtkAccessibleAutocomplete gtk_autocomplete_accessible_value_get (const GtkAccessibleValue *value); +GtkAccessibleValue * gtk_autocomplete_accessible_value_parse (const char *str, + gsize len, + GError **error); GtkAccessibleValue * gtk_orientation_accessible_value_new (GtkOrientation value); GtkOrientation gtk_orientation_accessible_value_get (const GtkAccessibleValue *value); +GtkAccessibleValue * gtk_orientation_accessible_value_parse (const char *str, + gsize len, + GError **error); GtkAccessibleValue * gtk_sort_accessible_value_new (GtkAccessibleSort value); GtkAccessibleSort gtk_sort_accessible_value_get (const GtkAccessibleValue *value); +GtkAccessibleValue * gtk_sort_accessible_value_parse (const char *str, + gsize len, + GError **error); G_END_DECLS diff --git a/gtk/gtkaccessiblevaluestatic.c b/gtk/gtkaccessiblevaluestatic.c index 6d26ea2900..5cb761eba5 100644 --- a/gtk/gtkaccessiblevaluestatic.c +++ b/gtk/gtkaccessiblevaluestatic.c @@ -282,6 +282,30 @@ gtk_invalid_accessible_value_get (const GtkAccessibleValue *value) return self->value; } +GtkAccessibleValue * +gtk_invalid_accessible_value_parse (const char *str, + gsize len, + GError **error) +{ + g_return_val_if_fail (str == NULL || len == 0, NULL); + + if (strncmp (str, "false", 5) == 0) + return gtk_invalid_accessible_value_new (GTK_ACCESSIBLE_INVALID_FALSE); + else if (strncmp (str, "true", 4) == 0) + return gtk_invalid_accessible_value_new (GTK_ACCESSIBLE_INVALID_TRUE); + else if (strncmp (str, "grammar", 7) == 0) + return gtk_invalid_accessible_value_new (GTK_ACCESSIBLE_INVALID_GRAMMAR); + else if (strncmp (str, "spelling", 8) == 0) + return gtk_invalid_accessible_value_new (GTK_ACCESSIBLE_INVALID_SPELLING); + else + g_set_error (error, GTK_ACCESSIBLE_VALUE_ERROR, + GTK_ACCESSIBLE_VALUE_ERROR_INVALID_TOKEN, + "Unknown token “%s”", + str); + + return NULL; +} + static const GtkAccessibleValueClass GTK_AUTOCOMPLETE_ACCESSIBLE_VALUE = { .type = GTK_ACCESSIBLE_VALUE_TYPE_TOKEN, .type_name = "GtkAutocompleteAccessibleValue", @@ -327,6 +351,30 @@ gtk_autocomplete_accessible_value_get (const GtkAccessibleValue *value) return self->value; } +GtkAccessibleValue * +gtk_autocomplete_accessible_value_parse (const char *str, + gsize len, + GError **error) +{ + g_return_val_if_fail (str == NULL || len == 0, NULL); + + if (strncmp (str, "none", 4) == 0) + return gtk_autocomplete_accessible_value_new (GTK_ACCESSIBLE_AUTOCOMPLETE_NONE); + else if (strncmp (str, "inline", 6) == 0) + return gtk_autocomplete_accessible_value_new (GTK_ACCESSIBLE_AUTOCOMPLETE_INLINE); + else if (strncmp (str, "list", 4) == 0) + return gtk_autocomplete_accessible_value_new (GTK_ACCESSIBLE_AUTOCOMPLETE_LIST); + else if (strncmp (str, "both", 4) == 0) + return gtk_autocomplete_accessible_value_new (GTK_ACCESSIBLE_AUTOCOMPLETE_BOTH); + else + g_set_error (error, GTK_ACCESSIBLE_VALUE_ERROR, + GTK_ACCESSIBLE_VALUE_ERROR_INVALID_TOKEN, + "Unknown token “%s”", + str); + + return NULL; +} + static const GtkAccessibleValueClass GTK_ORIENTATION_ACCESSIBLE_VALUE = { .type = GTK_ACCESSIBLE_VALUE_TYPE_TOKEN, .type_name = "GtkOrientationAccessibleValue", @@ -366,6 +414,26 @@ gtk_orientation_accessible_value_get (const GtkAccessibleValue *value) return self->value; } +GtkAccessibleValue * +gtk_orientation_accessible_value_parse (const char *str, + gsize len, + GError **error) +{ + g_return_val_if_fail (str == NULL || len == 0, NULL); + + if (strncmp (str, "horizontal", 10) == 0) + return gtk_orientation_accessible_value_new (GTK_ORIENTATION_HORIZONTAL); + else if (strncmp (str, "vertical", 8) == 0) + return gtk_orientation_accessible_value_new (GTK_ORIENTATION_VERTICAL); + else + g_set_error (error, GTK_ACCESSIBLE_VALUE_ERROR, + GTK_ACCESSIBLE_VALUE_ERROR_INVALID_TOKEN, + "Unknown token “%s”", + str); + + return NULL; +} + static const GtkAccessibleValueClass GTK_SORT_ACCESSIBLE_VALUE = { .type = GTK_ACCESSIBLE_VALUE_TYPE_TOKEN, .type_name = "GtkSortAccessibleValue", @@ -411,4 +479,28 @@ gtk_sort_accessible_value_get (const GtkAccessibleValue *value) return self->value; } +GtkAccessibleValue * +gtk_sort_accessible_value_parse (const char *str, + gsize len, + GError **error) +{ + g_return_val_if_fail (str == NULL || len == 0, NULL); + + if (strncmp (str, "none", 4) == 0) + return gtk_sort_accessible_value_new (GTK_ACCESSIBLE_SORT_NONE); + else if (strncmp (str, "ascending", 9) == 0) + return gtk_sort_accessible_value_new (GTK_ACCESSIBLE_SORT_ASCENDING); + else if (strncmp (str, "descending", 10) == 0) + return gtk_sort_accessible_value_new (GTK_ACCESSIBLE_SORT_DESCENDING); + else if (strncmp (str, "other", 5) == 0) + return gtk_sort_accessible_value_new (GTK_ACCESSIBLE_SORT_OTHER); + else + g_set_error (error, GTK_ACCESSIBLE_VALUE_ERROR, + GTK_ACCESSIBLE_VALUE_ERROR_INVALID_TOKEN, + "Unknown token “%s”", + str); + + return NULL; +} + /* }}} */