/* * Copyright (C) 2004, 2005 Jean-Yves Lefort * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of Jean-Yves Lefort nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include "config.h" #include #include #include "translate-pair.h" #include "translate-pair-private.h" #include "translate.h" enum { PROP_0, PROP_FLAGS, PROP_FROM, PROP_TO }; struct _TranslatePairPrivate { TranslatePairFlags flags; char *from; char *to; }; static GObjectClass *parent_class = NULL; static void translate_pair_register_type (GType *type); static void translate_pair_flags_register_type (GType *type); static void translate_pair_class_init (TranslatePairClass *class); static void translate_pair_init (TranslatePair *pair); static void translate_pair_finalize (GObject *object); static void translate_pair_set_property (GObject *object, unsigned int prop_id, const GValue *value, GParamSpec *pspec); static void translate_pair_get_property (GObject *object, unsigned int prop_id, GValue *value, GParamSpec *pspec); static int translate_pairs_tag_compare_func (TranslatePair *a, TranslatePair *b); static int translate_pairs_name_compare_func (TranslatePair *a, TranslatePair *b); GType translate_pair_get_type (void) { static GType type; static GOnce once = G_ONCE_INIT; g_once(&once, (GThreadFunc) translate_pair_register_type, &type); return type; } static void translate_pair_register_type (GType *type) { static const GTypeInfo info = { sizeof(TranslatePairClass), NULL, NULL, (GClassInitFunc) translate_pair_class_init, NULL, NULL, sizeof(TranslatePair), 0, (GInstanceInitFunc) translate_pair_init }; *type = g_type_register_static(G_TYPE_OBJECT, "TranslatePair", &info, 0); } GType translate_pair_flags_get_type (void) { static GType type; static GOnce once = G_ONCE_INIT; g_once(&once, (GThreadFunc) translate_pair_flags_register_type, &type); return type; } static void translate_pair_flags_register_type (GType *type) { static const GFlagsValue values[] = { { TRANSLATE_PAIR_TEXT, "TRANSLATE_PAIR_TEXT", "text" }, { TRANSLATE_PAIR_WEB_PAGE, "TRANSLATE_PAIR_WEB_PAGE", "web-page" }, { 0, NULL, NULL } }; *type = g_flags_register_static("TranslatePairFlags", values); } static void translate_pair_class_init (TranslatePairClass *class) { GObjectClass *object_class = G_OBJECT_CLASS(class); g_type_class_add_private(class, sizeof(TranslatePairPrivate)); parent_class = g_type_class_peek_parent(class); object_class->finalize = translate_pair_finalize; object_class->set_property = translate_pair_set_property; object_class->get_property = translate_pair_get_property; g_object_class_install_property(object_class, PROP_FLAGS, g_param_spec_flags("flags", _("Flags"), _("The pair flags"), TRANSLATE_TYPE_PAIR_FLAGS, 0, G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)); g_object_class_install_property(object_class, PROP_FROM, g_param_spec_string("from", _("From"), _("The source language RFC 3066 tag"), NULL, G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)); g_object_class_install_property(object_class, PROP_TO, g_param_spec_string("to", _("To"), _("The destination language RFC 3066 tag"), NULL, G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)); } static void translate_pair_init (TranslatePair *pair) { pair->priv = G_TYPE_INSTANCE_GET_PRIVATE(pair, TRANSLATE_TYPE_PAIR, TranslatePairPrivate); } static void translate_pair_finalize (GObject *object) { TranslatePair *pair = TRANSLATE_PAIR(object); g_free(pair->priv->from); g_free(pair->priv->to); parent_class->finalize(object); } static void translate_pair_set_property (GObject *object, unsigned int prop_id, const GValue *value, GParamSpec *pspec) { TranslatePair *pair = TRANSLATE_PAIR(object); switch (prop_id) { case PROP_FLAGS: pair->priv->flags = g_value_get_flags(value); break; case PROP_FROM: pair->priv->from = g_value_dup_string(value); break; case PROP_TO: pair->priv->to = g_value_dup_string(value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void translate_pair_get_property (GObject *object, unsigned int prop_id, GValue *value, GParamSpec *pspec) { TranslatePair *pair = TRANSLATE_PAIR(object); switch (prop_id) { case PROP_FLAGS: g_value_set_flags(value, pair->priv->flags); break; case PROP_FROM: g_value_set_string(value, pair->priv->from); break; case PROP_TO: g_value_set_string(value, pair->priv->to); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } /** * translate_pair_get_flags: * @pair: a pair. * * Gets the flags of @pair. * * Return value: the pair flags. **/ TranslatePairFlags translate_pair_get_flags (TranslatePair *pair) { g_return_val_if_fail(TRANSLATE_IS_PAIR(pair), 0); return pair->priv->flags; } void translate_pair_set_flags (TranslatePair *pair, TranslatePairFlags flags) { g_return_if_fail(TRANSLATE_IS_PAIR(pair)); pair->priv->flags = flags; } /** * translate_pair_get_from: * @pair: a pair. * * Gets the source language of @pair. * * Return value: the RFC 3066 tag of the source language of @pair. **/ const char * translate_pair_get_from (TranslatePair *pair) { g_return_val_if_fail(TRANSLATE_IS_PAIR(pair), NULL); return pair->priv->from; } /** * translate_pair_get_to: * @pair: a pair. * * Gets the destination language of @pair. * * Return value: the RFC 3066 tag of the destination language of * @pair. **/ const char * translate_pair_get_to (TranslatePair *pair) { g_return_val_if_fail(TRANSLATE_IS_PAIR(pair), NULL); return pair->priv->to; } /** * translate_pair_new: * @flags: the pair flags. * @from: the source language RFC 3066 tag. * @to: the destination language RFC 3066 tag. * * Creates a new language pair. * * Return value: a new language pair. **/ TranslatePair * translate_pair_new (TranslatePairFlags flags, const char *from, const char *to) { g_return_val_if_fail(from != NULL, NULL); g_return_val_if_fail(to != NULL, NULL); return g_object_new(TRANSLATE_TYPE_PAIR, "flags", flags, "from", from, "to", to, NULL); } GSList * translate_pairs_merge (GSList *pairs1, const GSList *pairs2) { const GSList *l; for (l = pairs2; l != NULL; l = l->next) { TranslatePair *pair = l->data; TranslatePair *existing_pair; existing_pair = translate_pairs_find(pairs1, pair->priv->from, pair->priv->to); if (existing_pair) existing_pair->priv->flags |= pair->priv->flags; else pairs1 = g_slist_append(pairs1, g_object_ref(pair)); } return pairs1; } /** * translate_pairs_sort_by_tag: * @pairs: a list of #TranslatePair objects. * * Sorts a pair list by source and destination RFC 3066 tag. Tag * comparisons are performed using translate_ascii_strcasecoll(). * * Return value: @pairs sorted. **/ GSList * translate_pairs_sort_by_tag (GSList *pairs) { return g_slist_sort(pairs, (GCompareFunc) translate_pairs_tag_compare_func); } /** * translate_pairs_sort_by_name: * @pairs: a list of #TranslatePair objects. * * Sorts a pair list by source and destination human-readable language * name. Names are obtained using translate_get_language_name(), and * are compared using translate_utf8_strcasecoll(). * * Return value: @pairs sorted. **/ GSList * translate_pairs_sort_by_name (GSList *pairs) { return g_slist_sort(pairs, (GCompareFunc) translate_pairs_name_compare_func); } static int translate_pairs_tag_compare_func (TranslatePair *a, TranslatePair *b) { int coll; coll = translate_ascii_strcasecoll(a->priv->from, b->priv->from); if (! coll) coll = translate_ascii_strcasecoll(a->priv->to, b->priv->to); return coll; } static int translate_pairs_name_compare_func (TranslatePair *a, TranslatePair *b) { int coll; coll = translate_utf8_strcasecoll(translate_get_language_name(a->priv->from), translate_get_language_name(b->priv->from)); if (! coll) coll = translate_utf8_strcasecoll(translate_get_language_name(a->priv->to), translate_get_language_name(b->priv->to)); return coll; } /** * translate_pairs_find: * @pairs: a list of #TranslatePair objects. * @from: a RFC 3066 tag, or %NULL. * @to: a RFC 3066 tag, or %NULL. * * Finds the first pair in @pairs whose source and/or destination * language match @from and/or @to. * * Return value: a pair, or %NULL if not found. The returned pair * belongs to @pairs, its reference count is not incremented. **/ TranslatePair * translate_pairs_find (const GSList *pairs, const char *from, const char *to) { const GSList *l; for (l = pairs; l != NULL; l = l->next) { TranslatePair *pair = l->data; if ((! from || ! g_ascii_strcasecmp(pair->priv->from, from)) && (! to || ! g_ascii_strcasecmp(pair->priv->to, to))) return pair; } return NULL; }