diff options
Diffstat (limited to '')
-rw-r--r-- | src/VBox/Additions/linux/lightdm-greeter/liblightdm-gobject-1.5.0/language.c | 416 |
1 files changed, 416 insertions, 0 deletions
diff --git a/src/VBox/Additions/linux/lightdm-greeter/liblightdm-gobject-1.5.0/language.c b/src/VBox/Additions/linux/lightdm-greeter/liblightdm-gobject-1.5.0/language.c new file mode 100644 index 00000000..9709619e --- /dev/null +++ b/src/VBox/Additions/linux/lightdm-greeter/liblightdm-gobject-1.5.0/language.c @@ -0,0 +1,416 @@ +/* + * Copyright (C) 2010 Robert Ancell. + * Author: Robert Ancell <robert.ancell@canonical.com> + * + * 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 or version 3 of the License. + * See http://www.gnu.org/copyleft/lgpl.html the full text of the license. + */ + +/* + * Oracle LGPL Disclaimer: For the avoidance of doubt, except that if any license choice + * other than GPL or LGPL is available it will apply instead, Oracle elects to use only + * the Lesser General Public License version 2.1 (LGPLv2) at this time for any software where + * a choice of LGPL license versions is made available with the language indicating + * that LGPLv2 or any later version may be used, or where a choice of which version + * of the LGPL is applied is otherwise unspecified. + */ + +#include <string.h> +#include <locale.h> +#include <langinfo.h> +#include <stdio.h> +#include <glib/gi18n.h> + +#include "lightdm/language.h" + +enum { + PROP_0, + PROP_CODE, + PROP_NAME, + PROP_TERRITORY +}; + +typedef struct +{ + gchar *code; + gchar *name; + gchar *territory; +} LightDMLanguagePrivate; + +G_DEFINE_TYPE (LightDMLanguage, lightdm_language, G_TYPE_OBJECT); + +#define GET_PRIVATE(obj) G_TYPE_INSTANCE_GET_PRIVATE ((obj), LIGHTDM_TYPE_LANGUAGE, LightDMLanguagePrivate) + +static gboolean have_languages = FALSE; +static GList *languages = NULL; + +static void +update_languages (void) +{ + gchar *command = "locale -a"; + gchar *stdout_text = NULL, *stderr_text = NULL; + gint exit_status; + gboolean result; + GError *error = NULL; + + if (have_languages) + return; + + result = g_spawn_command_line_sync (command, &stdout_text, &stderr_text, &exit_status, &error); + if (error) + { + g_warning ("Failed to run '%s': %s", command, error->message); + g_clear_error (&error); + } + else if (exit_status != 0) + g_warning ("Failed to get languages, '%s' returned %d", command, exit_status); + else if (result) + { + gchar **tokens; + int i; + + tokens = g_strsplit_set (stdout_text, "\n\r", -1); + for (i = 0; tokens[i]; i++) + { + LightDMLanguage *language; + gchar *code; + + code = g_strchug (tokens[i]); + if (code[0] == '\0') + continue; + + /* Ignore the non-interesting languages */ + if (strcmp (command, "locale -a") == 0 && !g_strrstr (code, ".utf8")) + continue; + + language = g_object_new (LIGHTDM_TYPE_LANGUAGE, "code", code, NULL); + languages = g_list_append (languages, language); + } + + g_strfreev (tokens); + } + + g_free (stdout_text); + g_free (stderr_text); + + have_languages = TRUE; +} + +static gboolean +is_utf8 (const gchar *code) +{ + return g_strrstr (code, ".utf8") || g_strrstr (code, ".UTF-8"); +} + +/* Get a valid locale name that can be passed to setlocale(), so we always can use nl_langinfo() to get language and country names. */ +static gchar * +get_locale_name (const gchar *code) +{ + gchar *locale = NULL, *language; + char *at; + static gchar **avail_locales; + gint i; + + if (is_utf8 (code)) + return (gchar *) code; + + if ((at = strchr (code, '@'))) + language = g_strndup (code, at - code); + else + language = g_strdup (code); + + if (!avail_locales) + { + gchar *locales; + GError *error = NULL; + + if (g_spawn_command_line_sync ("locale -a", &locales, NULL, NULL, &error)) + { + avail_locales = g_strsplit (g_strchomp (locales), "\n", -1); + g_free (locales); + } + else + { + g_warning ("Failed to run 'locale -a': %s", error->message); + g_clear_error (&error); + } + } + + if (avail_locales) + { + for (i = 0; avail_locales[i]; i++) + { + gchar *loc = avail_locales[i]; + if (!g_strrstr (loc, ".utf8")) + continue; + if (g_str_has_prefix (loc, language)) + { + locale = g_strdup (loc); + break; + } + } + } + + g_free (language); + + return locale; +} + +/** + * lightdm_get_language: + * + * Get the current language. + * + * Return value: (transfer none): The current language or #NULL if no language. + **/ +LightDMLanguage * +lightdm_get_language (void) +{ + const gchar *lang; + GList *link; + + lang = g_getenv ("LANG"); + if (!lang) + return NULL; + + for (link = lightdm_get_languages (); link; link = link->next) + { + LightDMLanguage *language = link->data; + if (lightdm_language_matches (language, lang)) + return language; + } + + return NULL; +} + +/** + * lightdm_get_languages: + * + * Get a list of languages to present to the user. + * + * Return value: (element-type LightDMLanguage) (transfer none): A list of #LightDMLanguage that should be presented to the user. + **/ +GList * +lightdm_get_languages (void) +{ + update_languages (); + return languages; +} + +/** + * lightdm_language_get_code: + * @language: A #LightDMLanguage + * + * Get the code of a language. + * + * Return value: The code of the language + **/ +const gchar * +lightdm_language_get_code (LightDMLanguage *language) +{ + g_return_val_if_fail (LIGHTDM_IS_LANGUAGE (language), NULL); + return GET_PRIVATE (language)->code; +} + +/** + * lightdm_language_get_name: + * @language: A #LightDMLanguage + * + * Get the name of a language. + * + * Return value: The name of the language + **/ +const gchar * +lightdm_language_get_name (LightDMLanguage *language) +{ + LightDMLanguagePrivate *priv; + + g_return_val_if_fail (LIGHTDM_IS_LANGUAGE (language), NULL); + + priv = GET_PRIVATE (language); + + if (!priv->name) + { + gchar *locale = get_locale_name (priv->code); + if (locale) + { + gchar *current = setlocale (LC_ALL, NULL); + setlocale (LC_IDENTIFICATION, locale); + setlocale (LC_MESSAGES, ""); + + gchar *language_en = nl_langinfo (_NL_IDENTIFICATION_LANGUAGE); + if (language_en && strlen (language_en) > 0) + priv->name = g_strdup (dgettext ("iso_639_3", language_en)); + + setlocale (LC_ALL, current); + } + if (!priv->name) + { + gchar **tokens = g_strsplit_set (priv->code, "_.@", 2); + priv->name = g_strdup (tokens[0]); + g_strfreev (tokens); + } + } + + return priv->name; +} + +/** + * lightdm_language_get_territory: + * @language: A #LightDMLanguage + * + * Get the territory the language is used in. + * + * Return value: The territory the language is used in. + **/ +const gchar * +lightdm_language_get_territory (LightDMLanguage *language) +{ + LightDMLanguagePrivate *priv; + + g_return_val_if_fail (LIGHTDM_IS_LANGUAGE (language), NULL); + + priv = GET_PRIVATE (language); + + if (!priv->territory && strchr (priv->code, '_')) + { + gchar *locale = get_locale_name (priv->code); + if (locale) + { + gchar *current = setlocale (LC_ALL, NULL); + setlocale (LC_IDENTIFICATION, locale); + setlocale (LC_MESSAGES, ""); + + gchar *country_en = nl_langinfo (_NL_IDENTIFICATION_TERRITORY); + if (country_en && strlen (country_en) > 0 && g_strcmp0 (country_en, "ISO") != 0) + priv->territory = g_strdup (dgettext ("iso_3166", country_en)); + + setlocale (LC_ALL, current); + } + if (!priv->territory) + { + gchar **tokens = g_strsplit_set (priv->code, "_.@", 3); + priv->territory = g_strdup (tokens[1]); + g_strfreev (tokens); + } + } + + return priv->territory; +} + +/** + * lightdm_language_matches: + * @language: A #LightDMLanguage + * @code: A language code + * + * Check if a language code matches this language. + * + * Return value: #TRUE if the code matches this language. + **/ +gboolean +lightdm_language_matches (LightDMLanguage *language, const gchar *code) +{ + LightDMLanguagePrivate *priv; + + g_return_val_if_fail (LIGHTDM_IS_LANGUAGE (language), FALSE); + g_return_val_if_fail (code != NULL, FALSE); + + priv = GET_PRIVATE (language); + + /* Handle the fact the UTF-8 is specified both as '.utf8' and '.UTF-8' */ + if (is_utf8 (priv->code) && is_utf8 (code)) + { + /* Match the characters before the '.' */ + int i; + for (i = 0; priv->code[i] && code[i] && priv->code[i] == code[i] && code[i] != '.' ; i++); + return priv->code[i] == '.' && code[i] == '.'; + } + + return g_str_equal (priv->code, code); +} + +static void +lightdm_language_init (LightDMLanguage *language) +{ +} + +static void +lightdm_language_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + LightDMLanguage *self = LIGHTDM_LANGUAGE (object); + LightDMLanguagePrivate *priv = GET_PRIVATE (self); + + switch (prop_id) { + case PROP_CODE: + g_free (priv->name); + priv->code = g_strdup (g_value_get_string (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +lightdm_language_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + LightDMLanguage *self; + + self = LIGHTDM_LANGUAGE (object); + + switch (prop_id) { + case PROP_CODE: + g_value_set_string (value, lightdm_language_get_code (self)); + break; + case PROP_NAME: + g_value_set_string (value, lightdm_language_get_name (self)); + break; + case PROP_TERRITORY: + g_value_set_string (value, lightdm_language_get_territory (self)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +lightdm_language_class_init (LightDMLanguageClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private (klass, sizeof (LightDMLanguagePrivate)); + + object_class->set_property = lightdm_language_set_property; + object_class->get_property = lightdm_language_get_property; + + g_object_class_install_property (object_class, + PROP_CODE, + g_param_spec_string ("code", + "code", + "Language code", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + g_object_class_install_property (object_class, + PROP_NAME, + g_param_spec_string ("name", + "name", + "Name of the language", + NULL, + G_PARAM_READABLE)); + g_object_class_install_property (object_class, + PROP_TERRITORY, + g_param_spec_string ("territory", + "territory", + "Territory the language is from", + NULL, + G_PARAM_READABLE)); +} |