gdm r5660 - in trunk: . gui/simple-greeter



Author: halfline
Date: Thu Jan 31 21:12:41 2008
New Revision: 5660
URL: http://svn.gnome.org/viewvc/gdm?rev=5660&view=rev

Log:
2008-01-31  Ray Strode  <rstrode redhat com>

	* gui/simple-greeter/gdm-languages.[ch]:
	New files that copy and paste the non-widget
	specific locale handling code from
	gdm-language-chooser (so it can be used
	for language selection from the panel too)


Added:
   trunk/gui/simple-greeter/gdm-languages.c
   trunk/gui/simple-greeter/gdm-languages.h
Modified:
   trunk/ChangeLog

Added: trunk/gui/simple-greeter/gdm-languages.c
==============================================================================
--- (empty file)
+++ trunk/gui/simple-greeter/gdm-languages.c	Thu Jan 31 21:12:41 2008
@@ -0,0 +1,851 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright 2008  Red Hat, Inc,
+ *           2007  William Jon McCann <mccann jhu edu>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Written by : William Jon McCann <mccann jhu edu>
+ *              Ray Strode <rstrode redhat com>
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <dirent.h>
+#include <locale.h>
+#include <sys/stat.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib/gstdio.h>
+
+#include "gdm-languages.h"
+
+#include <langinfo.h>
+#ifndef __LC_LAST
+#define __LC_LAST       13
+#endif
+#include "locarchive.h"
+
+#define ALIASES_FILE LIBLOCALEDIR "/locale.alias"
+#define ARCHIVE_FILE LIBLOCALEDIR "/locale-archive"
+#define ISO_CODES_DATADIR ISO_CODES_PREFIX "/share/xml/iso-codes"
+#define ISO_CODES_LOCALESDIR ISO_CODES_PREFIX "/share/locale"
+
+typedef struct _GdmLocale {
+        char *name;
+        char *language_code;
+        char *territory_code;
+        char *codeset;
+        char *modifier;
+        char *title;
+        char *language;
+        char *territory;
+} GdmLocale;
+
+static GHashTable *gdm_languages_map;
+static GHashTable *gdm_territories_map;
+static GHashTable *gdm_available_locales_map;
+
+static gboolean gdm_languages_is_initialized = FALSE;
+
+static void
+chooser_locale_free (GdmLocale *locale)
+{
+        if (locale == NULL) {
+                return;
+        }
+
+        g_free (locale->name);
+        g_free (locale->title);
+        g_free (locale->language);
+        g_free (locale->territory);
+        g_free (locale);
+}
+
+/*
+ * According to http://en.wikipedia.org/wiki/Locale
+ * locale names are of the form:
+ * [language[_territory][ codeset][ modifier]]
+ */
+void
+gdm_parse_language_name (const char *name,
+                         char      **language_codep,
+                         char      **territory_codep,
+                         char      **codesetp,
+                         char      **modifierp)
+{
+        GRegex     *re;
+        GMatchInfo *match_info;
+        gboolean    res;
+        GError     *error;
+
+        error = NULL;
+        re = g_regex_new ("(?P<language>[a-zA-Z]+)(_(?P<territory>[a-zA-Z]+))?(.(?P<codeset>[0-9a-zA-Z]+))?(@(?P<modifier>[0-9a-zA-Z]+))?", 0, 0, &error);
+        if (re == NULL) {
+                g_critical (error->message);
+        }
+
+        g_regex_match (re, name, 0, &match_info);
+
+        res = g_match_info_matches (match_info);
+        if (! res) {
+                g_warning ("Unable to parse locale: %s", name);
+                return;
+        }
+
+        if (language_codep != NULL) {
+                *language_codep = g_match_info_fetch_named (match_info, "language");
+        }
+
+        if (territory_codep != NULL) {
+                *territory_codep = g_match_info_fetch_named (match_info, "territory");
+        }
+
+        if (codesetp != NULL) {
+                *codesetp = g_match_info_fetch_named (match_info, "codeset");
+        }
+
+        if (modifierp != NULL) {
+                *modifierp = g_match_info_fetch_named (match_info, "modifier");
+        }
+
+        g_match_info_free (match_info);
+        g_regex_unref (re);
+}
+
+static char *
+construct_language_name (const char *language,
+                         const char *territory,
+                         const char *codeset,
+                         const char *modifier)
+{
+        char *name;
+
+        /* Ignore codeset and modifier for this */
+        /* FIXME: that can't be right. It's going to break
+         * serbian among other things.
+         */
+        if (territory == NULL) {
+                name = g_strdup (language);
+        } else {
+                name = g_strdup_printf ("%s_%s",
+                                        language,
+                                        territory);
+        }
+
+        return name;
+}
+
+char *
+gdm_normalize_language_name (const char *name)
+{
+        char *normalized_name;
+        char *language_code;
+        char *territory_code;
+
+        gdm_parse_language_name (name,
+                                 &language_code,
+                                 &territory_code,
+                                 NULL, NULL);
+
+        normalized_name = construct_language_name (language_code,
+                                                   territory_code, NULL, NULL);
+        g_free (language_code);
+        g_free (territory_code);
+
+        return normalized_name;
+}
+
+static char *
+utf8_convert (const char *str,
+              int         len)
+{
+        char *utf8;
+
+        utf8 = g_locale_to_utf8 (str, len, NULL, NULL, NULL);
+
+        /* if we couldn't convert text from locale then
+         * assume utf-8 and hope for the best */
+        if (utf8 == NULL) {
+                char *p;
+                char *q;
+
+                if (len < 0) {
+                        utf8 = g_strdup (str);
+                } else {
+                        utf8 = g_strndup (str, len);
+                }
+
+                p = utf8;
+                while (*p != '\0' && !g_utf8_validate ((const char *)p, -1, (const char **)&q)) {
+                        *q = '?';
+                        p = q + 1;
+                }
+        }
+
+        return utf8;
+}
+
+/* Magic number at the beginning of a locale data file for CATEGORY.  */
+#define LIMAGIC(category) \
+  (category == LC_COLLATE                                               \
+   ? ((unsigned int) (0x20051014 ^ (category)))                         \
+   : ((unsigned int) (0x20031115 ^ (category))))
+
+
+/* This seems to be specified by ISO/IEC 14652 */
+static void
+get_lc_identification (GdmLocale *locale,
+                       void             *data,
+                       gsize             size)
+{
+        struct {
+                unsigned int magic;
+                unsigned int nstrings;
+                unsigned int strindex[];
+        } *filedata = data;
+
+#ifdef LC_IDENTIFICATION
+        if (filedata->magic == LIMAGIC (LC_IDENTIFICATION)
+            && (sizeof *filedata + (filedata->nstrings * sizeof (unsigned int)) <= size)) {
+
+#define GET_HANDLE(idx) ((char *) data + filedata->strindex[_NL_ITEM_INDEX (_NL_IDENTIFICATION_##idx)])
+
+                locale->title = utf8_convert (GET_HANDLE (TITLE), -1);
+                locale->language = utf8_convert (GET_HANDLE (LANGUAGE), -1);
+                locale->territory = utf8_convert (GET_HANDLE (TERRITORY), -1);
+        }
+#endif
+}
+
+struct nameent
+{
+        char    *name;
+        uint32_t locrec_offset;
+};
+
+static int
+nameentcmp (const void *a, const void *b)
+{
+        return strcoll (((const struct nameent *) a)->name,
+                        ((const struct nameent *) b)->name);
+}
+
+static void
+collect_locales_from_archive (void)
+{
+        GMappedFile        *mapped;
+        GError             *error;
+        char               *addr;
+        struct locarhead   *head;
+        struct namehashent *namehashtab;
+        struct nameent     *names;
+        uint32_t            used;
+        uint32_t            cnt;
+        gsize               len;
+
+        error = NULL;
+        mapped = g_mapped_file_new (ARCHIVE_FILE, FALSE, &error);
+        if (mapped == NULL) {
+                g_warning ("Mapping failed for %s: %s", ARCHIVE_FILE, error->message);
+                g_error_free (error);
+                return;
+        }
+
+        addr = g_mapped_file_get_contents (mapped);
+        len = g_mapped_file_get_length (mapped);
+
+        head = (struct locarhead *) addr;
+        if (head->namehash_offset + head->namehash_size > len
+            || head->string_offset + head->string_size > len
+            || head->locrectab_offset + head->locrectab_size > len
+            || head->sumhash_offset + head->sumhash_size > len) {
+                goto out;
+        }
+
+        namehashtab = (struct namehashent *) (addr + head->namehash_offset);
+
+        names = (struct nameent *) g_new0 (struct nameent, head->namehash_used);
+        for (cnt = used = 0; cnt < head->namehash_size; ++cnt) {
+                if (namehashtab[cnt].locrec_offset != 0) {
+                        names[used].name = addr + namehashtab[cnt].name_offset;
+                        names[used++].locrec_offset = namehashtab[cnt].locrec_offset;
+                }
+        }
+
+        /* Sort the names.  */
+        qsort (names, used, sizeof (struct nameent), nameentcmp);
+
+        for (cnt = 0; cnt < used; ++cnt) {
+                struct locrecent *locrec;
+                GdmLocale *locale;
+
+                locale = g_new0 (GdmLocale, 1);
+
+                gdm_parse_language_name (names[cnt].name,
+                                         &locale->language_code,
+                                         &locale->territory_code,
+                                         NULL, NULL);
+
+                locale->name = construct_language_name (locale->language_code, locale->territory_code, NULL, NULL);
+
+                if (g_hash_table_lookup (gdm_available_locales_map, locale->name) != NULL) {
+                        chooser_locale_free (locale);
+                        continue;
+                }
+
+                locrec = (struct locrecent *) (addr + names[cnt].locrec_offset);
+
+#ifdef LC_IDENTIFICATION
+                get_lc_identification (locale,
+                                       addr + locrec->record[LC_IDENTIFICATION].offset,
+                                       locrec->record[LC_IDENTIFICATION].len);
+#endif
+
+                g_hash_table_insert (gdm_available_locales_map, g_strdup (locale->name), locale);
+        }
+
+        g_free (names);
+
+ out:
+
+        g_mapped_file_free (mapped);
+}
+
+static int
+select_dirs (const struct dirent *dirent)
+{
+        int result = 0;
+
+        if (strcmp (dirent->d_name, ".") != 0 && strcmp (dirent->d_name, "..") != 0) {
+                mode_t mode = 0;
+
+#ifdef _DIRENT_HAVE_D_TYPE
+                if (dirent->d_type != DT_UNKNOWN && dirent->d_type != DT_LNK) {
+                        mode = DTTOIF (dirent->d_type);
+                } else
+#endif
+                        {
+                                struct stat st;
+                                char       *path;
+
+                                path = g_build_filename (LIBLOCALEDIR, dirent->d_name, NULL);
+                                if (g_stat (path, &st) == 0) {
+                                        mode = st.st_mode;
+                                }
+                                g_free (path);
+                        }
+
+                result = S_ISDIR (mode);
+        }
+
+        return result;
+}
+
+static void
+collect_locales_from_directory (void)
+{
+        struct dirent **dirents;
+        int             ndirents;
+        int             cnt;
+
+        ndirents = scandir (LIBLOCALEDIR, &dirents, select_dirs, alphasort);
+
+        for (cnt = 0; cnt < ndirents; ++cnt) {
+                char             *path;
+                GdmLocale *locale;
+                gboolean          res;
+
+                locale = g_new0 (GdmLocale, 1);
+                gdm_parse_language_name (dirents[cnt]->d_name,
+                                         &locale->language_code,
+                                         &locale->territory_code,
+                                         NULL, NULL);
+
+                /* Ignore codeset and modifier for this */
+                locale->name = construct_language_name (locale->language_code, locale->territory_code, NULL, NULL);
+
+                if (g_hash_table_lookup (gdm_available_locales_map, locale->name) != NULL) {
+                        chooser_locale_free (locale);
+                        continue;
+                }
+
+                /* try to get additional information from LC_IDENTIFICATION */
+                path = g_build_filename (LIBLOCALEDIR, dirents[cnt]->d_name, "LC_IDENTIFICATION", NULL);
+                res = g_file_test (path, G_FILE_TEST_IS_REGULAR);
+                if (res) {
+                        GMappedFile      *mapped;
+                        GError           *error;
+
+                        error = NULL;
+                        mapped = g_mapped_file_new (path, FALSE, &error);
+                        if (mapped == NULL) {
+                                g_warning ("Mapping failed for %s: %s", path, error->message);
+                                g_error_free (error);
+                        } else {
+                                get_lc_identification (locale,
+                                                       g_mapped_file_get_contents (mapped),
+                                                       g_mapped_file_get_length (mapped));
+                                g_mapped_file_free (mapped);
+                        }
+                }
+                g_free (path);
+
+                g_hash_table_insert (gdm_available_locales_map, g_strdup (locale->name), locale);
+        }
+
+        if (ndirents > 0) {
+                free (dirents);
+        }
+}
+
+static void
+collect_locales_from_aliases (void)
+{
+        /* FIXME: */
+}
+
+static void
+collect_locales (void)
+{
+
+        if (gdm_available_locales_map == NULL) {
+                gdm_available_locales_map = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) chooser_locale_free);
+        }
+
+        collect_locales_from_archive ();
+        collect_locales_from_directory ();
+        collect_locales_from_aliases ();
+}
+
+static const char *
+get_language (const char *code)
+{
+        const char *name;
+        int         len;
+
+        g_assert (code != NULL);
+
+        len = strlen (code);
+        if (len != 2 && len != 3) {
+                return NULL;
+        }
+
+        name = (const char *) g_hash_table_lookup (gdm_languages_map, code);
+
+        return name;
+}
+
+static char *
+get_translated_language (const char *code,
+                         const char *locale)
+{
+        const char *language;
+        char *name;
+
+        language = get_language (code);
+
+        name = NULL;
+        if (language != NULL) {
+                const char *translated_name;
+                char *old_locale;
+                char **names;
+
+                old_locale = g_strdup (setlocale (LC_MESSAGES, NULL));
+                setlocale (LC_MESSAGES, locale);
+                translated_name = dgettext ("iso_639", language);
+                setlocale (LC_MESSAGES, old_locale);
+                g_free (old_locale);
+
+                names = g_strsplit (translated_name, "; ", 2);
+
+                name = g_strdup (names[0]);
+                g_strfreev (names);
+        }
+
+        return name;
+}
+
+static const char *
+get_territory (const char *code)
+{
+        const char *name;
+        int         len;
+
+        g_assert (code != NULL);
+
+        len = strlen (code);
+        if (len != 2 && len != 3) {
+                return NULL;
+        }
+
+        name = (const char *) g_hash_table_lookup (gdm_territories_map, code);
+
+        return name;
+}
+
+static const char *
+get_translated_territory (const char *code,
+                          const char *locale)
+{
+        const char *territory;
+        char *name;
+
+        territory = get_territory (code);
+
+        name = NULL;
+        if (territory != NULL) {
+                const char *translated_territory;
+                char *old_locale;
+                char **territories;
+
+                old_locale = g_strdup (setlocale (LC_MESSAGES, NULL));
+                setlocale (LC_MESSAGES, locale);
+                translated_territory = dgettext ("iso_3166", territory);
+                setlocale (LC_MESSAGES, old_locale);
+                g_free (old_locale);
+
+                territories = g_strsplit (translated_territory, "; ", 2);
+
+                name = g_strdup (territories[0]);
+                g_strfreev (territories);
+        }
+
+        return name;
+}
+
+static void
+languages_parse_start_tag (GMarkupParseContext      *ctx,
+                           const char               *element_name,
+                           const char              **attr_names,
+                           const char              **attr_values,
+                           gpointer                  user_data,
+                           GError                  **error)
+{
+        const char *ccode_longB;
+        const char *ccode_longT;
+        const char *ccode;
+        const char *lang_name;
+
+        if (! g_str_equal (element_name, "iso_639_entry") || attr_names == NULL || attr_values == NULL) {
+                return;
+        }
+
+        ccode = NULL;
+        ccode_longB = NULL;
+        ccode_longT = NULL;
+        lang_name = NULL;
+
+        while (*attr_names && *attr_values) {
+                if (g_str_equal (*attr_names, "iso_639_1_code")) {
+                        /* skip if empty */
+                        if (**attr_values) {
+                                if (strlen (*attr_values) != 2) {
+                                        return;
+                                }
+                                ccode = *attr_values;
+                        }
+                } else if (g_str_equal (*attr_names, "iso_639_2B_code")) {
+                        /* skip if empty */
+                        if (**attr_values) {
+                                if (strlen (*attr_values) != 3) {
+                                        return;
+                                }
+                                ccode_longB = *attr_values;
+                        }
+                } else if (g_str_equal (*attr_names, "iso_639_2T_code")) {
+                        /* skip if empty */
+                        if (**attr_values) {
+                                if (strlen (*attr_values) != 3) {
+                                        return;
+                                }
+                                ccode_longT = *attr_values;
+                        }
+                } else if (g_str_equal (*attr_names, "name")) {
+                        lang_name = *attr_values;
+                }
+
+                ++attr_names;
+                ++attr_values;
+        }
+
+        if (lang_name == NULL) {
+                return;
+        }
+
+        if (ccode != NULL) {
+                g_hash_table_insert (gdm_languages_map,
+                                     g_strdup (ccode),
+                                     g_strdup (lang_name));
+        }
+        if (ccode_longB != NULL) {
+                g_hash_table_insert (gdm_languages_map,
+                                     g_strdup (ccode_longB),
+                                     g_strdup (lang_name));
+        }
+        if (ccode_longT != NULL) {
+                g_hash_table_insert (gdm_languages_map,
+                                     g_strdup (ccode_longT),
+                                     g_strdup (lang_name));
+        }
+}
+
+static void
+territories_parse_start_tag (GMarkupParseContext      *ctx,
+                             const char               *element_name,
+                             const char              **attr_names,
+                             const char              **attr_values,
+                             gpointer                  user_data,
+                             GError                  **error)
+{
+        const char *acode_2;
+        const char *acode_3;
+        const char *ncode;
+        const char *territory_name;
+
+        if (! g_str_equal (element_name, "iso_3166_entry") || attr_names == NULL || attr_values == NULL) {
+                return;
+        }
+
+        acode_2 = NULL;
+        acode_3 = NULL;
+        ncode = NULL;
+        territory_name = NULL;
+
+        while (*attr_names && *attr_values) {
+                if (g_str_equal (*attr_names, "alpha_2_code")) {
+                        /* skip if empty */
+                        if (**attr_values) {
+                                if (strlen (*attr_values) != 2) {
+                                        return;
+                                }
+                                acode_2 = *attr_values;
+                        }
+                } else if (g_str_equal (*attr_names, "alpha_3_code")) {
+                        /* skip if empty */
+                        if (**attr_values) {
+                                if (strlen (*attr_values) != 3) {
+                                        return;
+                                }
+                                acode_3 = *attr_values;
+                        }
+                } else if (g_str_equal (*attr_names, "numeric_code")) {
+                        /* skip if empty */
+                        if (**attr_values) {
+                                if (strlen (*attr_values) != 3) {
+                                        return;
+                                }
+                                ncode = *attr_values;
+                        }
+                } else if (g_str_equal (*attr_names, "name")) {
+                        territory_name = *attr_values;
+                }
+
+                ++attr_names;
+                ++attr_values;
+        }
+
+        if (territory_name == NULL) {
+                return;
+        }
+
+        if (acode_2 != NULL) {
+                g_hash_table_insert (gdm_territories_map,
+                                     g_strdup (acode_2),
+                                     g_strdup (territory_name));
+        }
+        if (acode_3 != NULL) {
+                g_hash_table_insert (gdm_territories_map,
+                                     g_strdup (acode_3),
+                                     g_strdup (territory_name));
+        }
+        if (ncode != NULL) {
+                g_hash_table_insert (gdm_territories_map,
+                                     g_strdup (ncode),
+                                     g_strdup (territory_name));
+        }
+}
+
+static void
+languages_init (void)
+{
+        GError  *error;
+        gboolean res;
+        char    *buf;
+        gsize    buf_len;
+
+        bindtextdomain ("iso_639", ISO_CODES_LOCALESDIR);
+        bind_textdomain_codeset ("iso_639", "UTF-8");
+
+        gdm_languages_map = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+
+        error = NULL;
+        res = g_file_get_contents (ISO_CODES_DATADIR "/iso_639.xml",
+                                   &buf,
+                                   &buf_len,
+                                   &error);
+        if (res) {
+                GMarkupParseContext *ctx;
+                GMarkupParser        parser = { languages_parse_start_tag, NULL, NULL, NULL, NULL };
+
+                ctx = g_markup_parse_context_new (&parser, 0, NULL, NULL);
+
+                error = NULL;
+                res = g_markup_parse_context_parse (ctx, buf, buf_len, &error);
+
+                if (! res) {
+                        g_warning ("Failed to parse '%s': %s\n",
+                                   ISO_CODES_DATADIR "/iso_639.xml",
+                                   error->message);
+                        g_error_free (error);
+                }
+
+                g_markup_parse_context_free (ctx);
+                g_free (buf);
+        } else {
+                g_warning ("Failed to load '%s': %s\n",
+                           ISO_CODES_DATADIR "/iso_639.xml",
+                           error->message);
+                g_error_free (error);
+        }
+}
+
+static void
+territories_init (void)
+{
+        GError  *error;
+        gboolean res;
+        char    *buf;
+        gsize    buf_len;
+
+        bindtextdomain ("iso_3166", ISO_CODES_LOCALESDIR);
+        bind_textdomain_codeset ("iso_3166", "UTF-8");
+
+        gdm_territories_map = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+
+        error = NULL;
+        res = g_file_get_contents (ISO_CODES_DATADIR "/iso_3166.xml",
+                                   &buf,
+                                   &buf_len,
+                                   &error);
+        if (res) {
+                GMarkupParseContext *ctx;
+                GMarkupParser        parser = { territories_parse_start_tag, NULL, NULL, NULL, NULL };
+
+                ctx = g_markup_parse_context_new (&parser, 0, NULL, NULL);
+
+                error = NULL;
+                res = g_markup_parse_context_parse (ctx, buf, buf_len, &error);
+
+                if (! res) {
+                        g_warning ("Failed to parse '%s': %s\n",
+                                   ISO_CODES_DATADIR "/iso_3166.xml",
+                                   error->message);
+                        g_error_free (error);
+                }
+
+                g_markup_parse_context_free (ctx);
+                g_free (buf);
+        } else {
+                g_warning ("Failed to load '%s': %s\n",
+                           ISO_CODES_DATADIR "/iso_3166.xml",
+                           error->message);
+                g_error_free (error);
+        }
+}
+
+char *
+gdm_get_language_from_name (const char *name)
+{
+        char *full_language;
+        char *language_code;
+        char *territory_code;
+        const char *language;
+        const char *territory;
+
+        if (!gdm_languages_is_initialized) {
+                collect_locales ();
+                languages_init ();
+                territories_init ();
+
+                gdm_languages_is_initialized = TRUE;
+        }
+
+        language_code = NULL;
+        territory_code = NULL;
+        full_language = NULL;
+
+        gdm_parse_language_name (name, &language_code, &territory_code,
+                                 NULL, NULL);
+
+        if (language_code == NULL) {
+                goto out;
+        }
+
+        language = get_translated_language (language_code, name);
+
+        if (territory_code != NULL) {
+                territory = get_translated_territory (territory_code, name);
+        } else {
+                territory = NULL;
+        }
+
+        if (territory != NULL) {
+                full_language  = g_strdup_printf ("%s (%s)", language, territory);
+        } else {
+                full_language  = g_strdup (language);
+        }
+
+out:
+       g_free (language_code);
+       g_free (territory_code);
+
+       return full_language;
+}
+
+char **
+gdm_get_all_language_names (void)
+{
+        GHashTableIter iter;
+        gpointer key, value;
+        GPtrArray *array;
+
+        if (!gdm_languages_is_initialized) {
+                collect_locales ();
+                languages_init ();
+                territories_init ();
+
+                gdm_languages_is_initialized = TRUE;
+        }
+
+        array = g_ptr_array_new ();
+        g_hash_table_iter_init (&iter, gdm_available_locales_map);
+        while (g_hash_table_iter_next (&iter, &key, &value)) {
+                GdmLocale *locale;
+
+                locale = (GdmLocale *) value;
+
+                g_ptr_array_add (array, g_strdup (locale->name));
+        }
+        g_ptr_array_add (array, NULL);
+
+        return (char **) g_ptr_array_free (array, FALSE);
+}

Added: trunk/gui/simple-greeter/gdm-languages.h
==============================================================================
--- (empty file)
+++ trunk/gui/simple-greeter/gdm-languages.h	Thu Jan 31 21:12:41 2008
@@ -0,0 +1,40 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright 2008 Red Hat, Inc.
+ * Copyright 2007 William Jon McCann <mccann jhu edu>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Written by: Ray Strode
+ *             William Jon McCann
+ */
+
+#ifndef __GDM_LANGUAGES_H
+#define __GDM_LANGUAGES_H
+
+G_BEGIN_DECLS
+
+char *                 gdm_get_language_from_name (const char *name);
+char **                gdm_get_all_language_names (void);
+void                   gdm_parse_language_name (const char *name,
+                                                char      **language_codep,
+                                                char      **territory_codep,
+                                                char      **codesetp,
+                                                char      **modifierp);
+char *                 gdm_normalize_language_name (const char *name);
+
+G_END_DECLS
+
+#endif /* __GDM_LANGUAGE_CHOOSER_WIDGET_H */



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]