source: proiecte/PPPP/gdm/gui/simple-greeter/gdm-languages.c @ 134

Last change on this file since 134 was 134, checked in by (none), 14 years ago

gdm sources with the modifications for webcam

File size: 29.7 KB
Line 
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
2 *
3 * Copyright 2008  Red Hat, Inc,
4 *           2007  William Jon McCann <mccann@jhu.edu>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 *
20 * Written by : William Jon McCann <mccann@jhu.edu>
21 *              Ray Strode <rstrode@redhat.com>
22 */
23
24#include "config.h"
25
26#include <stdlib.h>
27#include <stdio.h>
28#include <unistd.h>
29#include <string.h>
30#include <errno.h>
31#include <dirent.h>
32#include <locale.h>
33#include <langinfo.h>
34#include <sys/stat.h>
35
36#include <glib.h>
37#include <glib/gi18n.h>
38#include <glib/gstdio.h>
39
40#include "gdm-languages.h"
41
42#include <langinfo.h>
43#ifndef __LC_LAST
44#define __LC_LAST       13
45#endif
46#include "locarchive.h"
47
48#define ALIASES_FILE LIBLOCALEDIR "/locale.alias"
49#define ARCHIVE_FILE LIBLOCALEDIR "/locale-archive"
50#define ISO_CODES_DATADIR ISO_CODES_PREFIX "/share/xml/iso-codes"
51#define ISO_CODES_LOCALESDIR ISO_CODES_PREFIX "/share/locale"
52
53typedef struct _GdmLocale {
54        char *id;
55        char *name;
56        char *language_code;
57        char *territory_code;
58        char *codeset;
59        char *modifier;
60} GdmLocale;
61
62static GHashTable *gdm_languages_map;
63static GHashTable *gdm_territories_map;
64static GHashTable *gdm_available_locales_map;
65
66static void
67gdm_locale_free (GdmLocale *locale)
68{
69        if (locale == NULL) {
70                return;
71        }
72
73        g_free (locale->id);
74        g_free (locale->name);
75        g_free (locale->codeset);
76        g_free (locale->modifier);
77        g_free (locale);
78}
79
80static char *
81normalize_codeset (const char *codeset)
82{
83        char *normalized_codeset;
84        const char *p;
85        char *q;
86
87        normalized_codeset = g_strdup (codeset);
88
89        if (codeset != NULL) {
90                for (p = codeset, q = normalized_codeset;
91                     *p != '\0'; p++) {
92
93                        if (*p == '-' || *p == '_') {
94                                continue;
95                        }
96
97                        *q = g_ascii_tolower (*p);
98                        q++;
99                }
100                *q = '\0';
101        }
102
103        return normalized_codeset;
104}
105
106/*
107 * According to http://en.wikipedia.org/wiki/Locale
108 * locale names are of the form:
109 * [language[_territory][.codeset][@modifier]]
110 */
111void
112gdm_parse_language_name (const char *name,
113                         char      **language_codep,
114                         char      **territory_codep,
115                         char      **codesetp,
116                         char      **modifierp)
117{
118        GRegex     *re;
119        GMatchInfo *match_info;
120        gboolean    res;
121        GError     *error;
122
123        error = NULL;
124        re = g_regex_new ("^(?P<language>[^_.@[:space:]]+)"
125                          "(_(?P<territory>[[:upper:]]+))?"
126                          "(\\.(?P<codeset>[-_0-9a-zA-Z]+))?"
127                          "(@(?P<modifier>[[:ascii:]]+))?$",
128                          0, 0, &error);
129        if (re == NULL) {
130                g_critical ("%s", error->message);
131                return;
132        }
133
134        if (!g_regex_match (re, name, 0, &match_info) ||
135            g_match_info_is_partial_match (match_info)) {
136                g_match_info_free (match_info);
137                g_regex_unref (re);
138                g_warning ("locale %s isn't valid\n", name);
139                return;
140        }
141
142        res = g_match_info_matches (match_info);
143        if (! res) {
144                g_warning ("Unable to parse locale: %s", name);
145                return;
146        }
147
148        if (language_codep != NULL) {
149                *language_codep = g_match_info_fetch_named (match_info, "language");
150        }
151
152        if (territory_codep != NULL) {
153                *territory_codep = g_match_info_fetch_named (match_info, "territory");
154
155                if (*territory_codep != NULL &&
156                    *territory_codep[0] == '\0') {
157                        g_free (*territory_codep);
158                        *territory_codep = NULL;
159                }
160        }
161
162        if (codesetp != NULL) {
163                *codesetp = g_match_info_fetch_named (match_info, "codeset");
164
165                if (*codesetp != NULL &&
166                    *codesetp[0] == '\0') {
167                        g_free (*codesetp);
168                        *codesetp = NULL;
169                }
170
171                if (*codesetp != NULL) {
172                        char *codeset;
173
174                        codeset = normalize_codeset (*codesetp);
175                        g_free (*codesetp);
176                        *codesetp = codeset;
177                }
178        }
179
180        if (modifierp != NULL) {
181                *modifierp = g_match_info_fetch_named (match_info, "modifier");
182
183                if (*modifierp != NULL &&
184                    *modifierp[0] == '\0') {
185                        g_free (*modifierp);
186                        *modifierp = NULL;
187                }
188        }
189
190        g_match_info_free (match_info);
191        g_regex_unref (re);
192}
193
194static char *
195construct_language_name (const char *language,
196                         const char *territory,
197                         const char *codeset,
198                         const char *modifier)
199{
200        char *name;
201
202        g_assert (language[0] != 0);
203        g_assert (territory == NULL || territory[0] != 0);
204        g_assert (codeset == NULL || codeset[0] != 0);
205        g_assert (modifier == NULL || modifier[0] != 0);
206
207        name = g_strdup_printf ("%s%s%s%s%s%s%s",
208                                language,
209                                territory != NULL? "_" : "",
210                                territory != NULL? territory : "",
211                                codeset != NULL? "." : "",
212                                codeset != NULL? codeset : "",
213                                modifier != NULL? "@" : "",
214                                modifier != NULL? modifier : "");
215
216        return name;
217}
218
219static void
220make_codeset_canonical_for_locale (const char  *name,
221                                   char       **codeset)
222{
223        char *old_locale;
224
225        old_locale = setlocale (LC_CTYPE, NULL);
226
227        if (setlocale (LC_CTYPE, name) == NULL) {
228                return;
229        }
230
231        g_free (*codeset);
232        *codeset = g_strdup (nl_langinfo (CODESET));
233
234        setlocale (LC_CTYPE, old_locale);
235}
236
237char *
238gdm_normalize_language_name (const char *name)
239{
240        char *normalized_name;
241        char *language_code;
242        char *territory_code;
243        char *codeset;
244        char *modifier;
245
246        if (name[0] == '\0') {
247                return NULL;
248        }
249
250        gdm_parse_language_name (name,
251                                 &language_code,
252                                 &territory_code,
253                                 &codeset, &modifier);
254
255        if (codeset != NULL) {
256                make_codeset_canonical_for_locale (name, &codeset);
257        }
258
259        normalized_name = construct_language_name (language_code,
260                                                   territory_code,
261                                                   codeset, modifier);
262        g_free (language_code);
263        g_free (territory_code);
264        g_free (codeset);
265        g_free (modifier);
266
267        return normalized_name;
268}
269
270static gboolean
271language_name_is_valid (const char *language_name)
272{
273        char     *old_locale;
274        gboolean  is_valid;
275
276        old_locale = g_strdup (setlocale (LC_MESSAGES, NULL));
277        is_valid = setlocale (LC_MESSAGES, language_name) != NULL;
278        setlocale (LC_MESSAGES, old_locale);
279        g_free (old_locale);
280
281        return is_valid;
282}
283
284static gboolean
285language_name_is_utf8 (const char *language_name)
286{
287        char     *old_locale;
288        char     *codeset;
289        gboolean  is_utf8;
290
291        old_locale = g_strdup (setlocale (LC_CTYPE, NULL));
292
293        if (setlocale (LC_CTYPE, language_name) == NULL) {
294                g_free (old_locale);
295                return FALSE;
296        }
297
298        codeset = normalize_codeset (nl_langinfo (CODESET));
299
300        is_utf8 = strcmp (codeset, "utf8") == 0;
301        g_free (codeset);
302
303        setlocale (LC_CTYPE, old_locale);
304        g_free (old_locale);
305
306        return is_utf8;
307}
308
309static gboolean
310language_name_has_translations (const char *language_name)
311{
312        GDir        *dir;
313        char        *path;
314        const char  *name;
315        gboolean     has_translations;
316
317        path = g_build_filename (GNOMELOCALEDIR, language_name, "LC_MESSAGES", NULL);
318
319        has_translations = FALSE;
320        dir = g_dir_open (path, 0, NULL);
321        g_free (path);
322
323        if (dir == NULL) {
324                goto out;
325        }
326
327        do {
328                name = g_dir_read_name (dir);
329
330                if (name == NULL) {
331                        break;
332                }
333
334                if (g_str_has_suffix (name, ".mo")) {
335                        has_translations = TRUE;
336                        break;
337                }
338        } while (name != NULL);
339        g_dir_close (dir);
340
341out:
342        return has_translations;
343}
344
345static gboolean
346add_locale (const char *language_name)
347{
348        GdmLocale *locale;
349        GdmLocale *old_locale;
350        char      *name;
351
352        if (language_name_is_utf8 (language_name)) {
353                name = g_strdup (language_name);
354        } else {
355                name = g_strdup_printf ("%s.utf8", language_name);
356
357                if (!language_name_is_utf8 (name)) {
358                        g_free (name);
359                        return FALSE;
360                }
361        }
362
363        if (!language_name_is_valid (name)) {
364                g_free (name);
365                return FALSE;
366        }
367
368
369        locale = g_new0 (GdmLocale, 1);
370        gdm_parse_language_name (name,
371                                 &locale->language_code,
372                                 &locale->territory_code,
373                                 &locale->codeset,
374                                 &locale->modifier);
375        g_free (name);
376        name = NULL;
377
378        locale->id = construct_language_name (locale->language_code, locale->territory_code,
379                                              NULL, locale->modifier);
380        locale->name = construct_language_name (locale->language_code, locale->territory_code,
381                                                locale->codeset, locale->modifier);
382
383        if (!language_name_has_translations (locale->name) &&
384            !language_name_has_translations (locale->id) &&
385            !language_name_has_translations (locale->language_code)) {
386                gdm_locale_free (locale);
387                return FALSE;
388        }
389
390        old_locale = g_hash_table_lookup (gdm_available_locales_map, locale->id);
391        if (old_locale != NULL) {
392                if (strlen (old_locale->name) > strlen (locale->name)) {
393                        gdm_locale_free (locale);
394                        return FALSE;
395                }
396        }
397
398        g_hash_table_insert (gdm_available_locales_map, g_strdup (locale->id), locale);
399
400        return TRUE;
401}
402
403struct nameent
404{
405        char    *name;
406        uint32_t locrec_offset;
407};
408
409static gboolean
410collect_locales_from_archive (void)
411{
412        GMappedFile        *mapped;
413        GError             *error;
414        char               *addr;
415        struct locarhead   *head;
416        struct namehashent *namehashtab;
417        struct nameent     *names;
418        uint32_t            used;
419        uint32_t            cnt;
420        gsize               len;
421        gboolean            locales_collected;
422
423        error = NULL;
424        mapped = g_mapped_file_new (ARCHIVE_FILE, FALSE, &error);
425        if (mapped == NULL) {
426                g_warning ("Mapping failed for %s: %s", ARCHIVE_FILE, error->message);
427                g_error_free (error);
428                return FALSE;
429        }
430
431        locales_collected = FALSE;
432
433        addr = g_mapped_file_get_contents (mapped);
434        len = g_mapped_file_get_length (mapped);
435
436        head = (struct locarhead *) addr;
437        if (head->namehash_offset + head->namehash_size > len
438            || head->string_offset + head->string_size > len
439            || head->locrectab_offset + head->locrectab_size > len
440            || head->sumhash_offset + head->sumhash_size > len) {
441                goto out;
442        }
443
444        namehashtab = (struct namehashent *) (addr + head->namehash_offset);
445
446        names = (struct nameent *) g_new0 (struct nameent, head->namehash_used);
447        for (cnt = used = 0; cnt < head->namehash_size; ++cnt) {
448                if (namehashtab[cnt].locrec_offset != 0) {
449                        names[used].name = addr + namehashtab[cnt].name_offset;
450                        names[used++].locrec_offset = namehashtab[cnt].locrec_offset;
451                }
452        }
453
454        for (cnt = 0; cnt < used; ++cnt) {
455                add_locale (names[cnt].name);
456        }
457
458        g_free (names);
459
460        locales_collected = TRUE;
461 out:
462
463        g_mapped_file_free (mapped);
464        return locales_collected;
465}
466
467static int
468select_dirs (const struct dirent *dirent)
469{
470        int result = 0;
471
472        if (strcmp (dirent->d_name, ".") != 0 && strcmp (dirent->d_name, "..") != 0) {
473                mode_t mode = 0;
474
475#ifdef _DIRENT_HAVE_D_TYPE
476                if (dirent->d_type != DT_UNKNOWN && dirent->d_type != DT_LNK) {
477                        mode = DTTOIF (dirent->d_type);
478                } else
479#endif
480                        {
481                                struct stat st;
482                                char       *path;
483
484                                path = g_build_filename (LIBLOCALEDIR, dirent->d_name, NULL);
485                                if (g_stat (path, &st) == 0) {
486                                        mode = st.st_mode;
487                                }
488                                g_free (path);
489                        }
490
491                result = S_ISDIR (mode);
492        }
493
494        return result;
495}
496
497static void
498collect_locales_from_directory (void)
499{
500        struct dirent **dirents;
501        int             ndirents;
502        int             cnt;
503
504        ndirents = scandir (LIBLOCALEDIR, &dirents, select_dirs, alphasort);
505
506        for (cnt = 0; cnt < ndirents; ++cnt) {
507                add_locale (dirents[cnt]->d_name);
508        }
509
510        if (ndirents > 0) {
511                free (dirents);
512        }
513}
514
515static void
516collect_locales (void)
517{
518
519        if (gdm_available_locales_map == NULL) {
520                gdm_available_locales_map = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) gdm_locale_free);
521        }
522
523        if (collect_locales_from_archive ()) {
524                return;
525        } else {
526                g_warning ("Could not read list of available locales from libc, "
527                           "guessing possible locales from available translations, "
528                           "but list may be incomplete!");
529
530                collect_locales_from_directory ();
531        }
532}
533
534static gboolean
535is_fallback_language (const char *code)
536{
537        const char *fallback_language_names[] = { "C", "POSIX", NULL };
538        int i;
539
540        for (i = 0; fallback_language_names[i] != NULL; i++) {
541                if (strcmp (code, fallback_language_names[i]) == 0) {
542                        return TRUE;
543                }
544        }
545
546        return FALSE;
547}
548
549static const char *
550get_language (const char *code)
551{
552        const char *name;
553        int         len;
554
555        g_assert (code != NULL);
556
557        if (is_fallback_language (code)) {
558                return "Unspecified";
559        }
560
561        len = strlen (code);
562        if (len != 2 && len != 3) {
563                return NULL;
564        }
565
566        name = (const char *) g_hash_table_lookup (gdm_languages_map, code);
567
568        return name;
569}
570
571static char *
572get_first_item_in_semicolon_list (const char *list)
573{
574    char **items;
575    char  *item;
576
577    /* Some entries in iso codes have multiple values, separated
578     * by semicolons.  Not really sure which one to pick, so
579     * we just arbitrarily pick the first one.
580     */
581    items = g_strsplit (list, "; ", 2);
582
583    item = g_strdup (items[0]);
584    g_strfreev (items);
585
586    return item;
587}
588
589static char *
590get_translated_language (const char *code,
591                         const char *locale)
592{
593        const char *language;
594        char *name;
595
596        language = get_language (code);
597
598        name = NULL;
599        if (language != NULL) {
600                const char  *translated_name;
601                char        *old_locale;
602
603                if (locale != NULL) {
604                        old_locale = g_strdup (setlocale (LC_MESSAGES, NULL));
605                        setlocale (LC_MESSAGES, locale);
606                }
607
608                if (is_fallback_language (code)) {
609                        name = _("Unspecified");
610                } else {
611                        translated_name = dgettext ("iso_639", language);
612                        name = get_first_item_in_semicolon_list (translated_name);
613                }
614
615                if (locale != NULL) {
616                        setlocale (LC_MESSAGES, old_locale);
617                        g_free (old_locale);
618                }
619        }
620
621        return name;
622}
623
624static const char *
625get_territory (const char *code)
626{
627        const char *name;
628        int         len;
629
630        g_assert (code != NULL);
631
632        len = strlen (code);
633        if (len != 2 && len != 3) {
634                return NULL;
635        }
636
637        name = (const char *) g_hash_table_lookup (gdm_territories_map, code);
638
639        return name;
640}
641
642static const char *
643get_translated_territory (const char *code,
644                          const char *locale)
645{
646        const char *territory;
647        char *name;
648
649        territory = get_territory (code);
650
651        name = NULL;
652        if (territory != NULL) {
653                const char *translated_territory;
654                char       *old_locale;
655
656                if (locale != NULL) {
657                        old_locale = g_strdup (setlocale (LC_MESSAGES, NULL));
658                        setlocale (LC_MESSAGES, locale);
659                }
660
661                translated_territory = dgettext ("iso_3166", territory);
662                name = get_first_item_in_semicolon_list (translated_territory);
663
664                if (locale != NULL) {
665                        setlocale (LC_MESSAGES, old_locale);
666                        g_free (old_locale);
667                }
668        }
669
670        return name;
671}
672
673static void
674languages_parse_start_tag (GMarkupParseContext      *ctx,
675                           const char               *element_name,
676                           const char              **attr_names,
677                           const char              **attr_values,
678                           gpointer                  user_data,
679                           GError                  **error)
680{
681        const char *ccode_longB;
682        const char *ccode_longT;
683        const char *ccode;
684        const char *lang_name;
685
686        if (! g_str_equal (element_name, "iso_639_entry") || attr_names == NULL || attr_values == NULL) {
687                return;
688        }
689
690        ccode = NULL;
691        ccode_longB = NULL;
692        ccode_longT = NULL;
693        lang_name = NULL;
694
695        while (*attr_names && *attr_values) {
696                if (g_str_equal (*attr_names, "iso_639_1_code")) {
697                        /* skip if empty */
698                        if (**attr_values) {
699                                if (strlen (*attr_values) != 2) {
700                                        return;
701                                }
702                                ccode = *attr_values;
703                        }
704                } else if (g_str_equal (*attr_names, "iso_639_2B_code")) {
705                        /* skip if empty */
706                        if (**attr_values) {
707                                if (strlen (*attr_values) != 3) {
708                                        return;
709                                }
710                                ccode_longB = *attr_values;
711                        }
712                } else if (g_str_equal (*attr_names, "iso_639_2T_code")) {
713                        /* skip if empty */
714                        if (**attr_values) {
715                                if (strlen (*attr_values) != 3) {
716                                        return;
717                                }
718                                ccode_longT = *attr_values;
719                        }
720                } else if (g_str_equal (*attr_names, "name")) {
721                        lang_name = *attr_values;
722                }
723
724                ++attr_names;
725                ++attr_values;
726        }
727
728        if (lang_name == NULL) {
729                return;
730        }
731
732        if (ccode != NULL) {
733                g_hash_table_insert (gdm_languages_map,
734                                     g_strdup (ccode),
735                                     g_strdup (lang_name));
736        }
737        if (ccode_longB != NULL) {
738                g_hash_table_insert (gdm_languages_map,
739                                     g_strdup (ccode_longB),
740                                     g_strdup (lang_name));
741        }
742        if (ccode_longT != NULL) {
743                g_hash_table_insert (gdm_languages_map,
744                                     g_strdup (ccode_longT),
745                                     g_strdup (lang_name));
746        }
747}
748
749static void
750territories_parse_start_tag (GMarkupParseContext      *ctx,
751                             const char               *element_name,
752                             const char              **attr_names,
753                             const char              **attr_values,
754                             gpointer                  user_data,
755                             GError                  **error)
756{
757        const char *acode_2;
758        const char *acode_3;
759        const char *ncode;
760        const char *territory_common_name;
761        const char *territory_name;
762
763        if (! g_str_equal (element_name, "iso_3166_entry") || attr_names == NULL || attr_values == NULL) {
764                return;
765        }
766
767        acode_2 = NULL;
768        acode_3 = NULL;
769        ncode = NULL;
770        territory_common_name = NULL;
771        territory_name = NULL;
772
773        while (*attr_names && *attr_values) {
774                if (g_str_equal (*attr_names, "alpha_2_code")) {
775                        /* skip if empty */
776                        if (**attr_values) {
777                                if (strlen (*attr_values) != 2) {
778                                        return;
779                                }
780                                acode_2 = *attr_values;
781                        }
782                } else if (g_str_equal (*attr_names, "alpha_3_code")) {
783                        /* skip if empty */
784                        if (**attr_values) {
785                                if (strlen (*attr_values) != 3) {
786                                        return;
787                                }
788                                acode_3 = *attr_values;
789                        }
790                } else if (g_str_equal (*attr_names, "numeric_code")) {
791                        /* skip if empty */
792                        if (**attr_values) {
793                                if (strlen (*attr_values) != 3) {
794                                        return;
795                                }
796                                ncode = *attr_values;
797                        }
798                } else if (g_str_equal (*attr_names, "common_name")) {
799                        /* skip if empty */
800                        if (**attr_values) {
801                                territory_common_name = *attr_values;
802                        }
803                } else if (g_str_equal (*attr_names, "name")) {
804                        territory_name = *attr_values;
805                }
806
807                ++attr_names;
808                ++attr_values;
809        }
810
811        if (territory_common_name != NULL) {
812                territory_name = territory_common_name;
813        }
814
815        if (territory_name == NULL) {
816                return;
817        }
818
819        if (acode_2 != NULL) {
820                g_hash_table_insert (gdm_territories_map,
821                                     g_strdup (acode_2),
822                                     g_strdup (territory_name));
823        }
824        if (acode_3 != NULL) {
825                g_hash_table_insert (gdm_territories_map,
826                                     g_strdup (acode_3),
827                                     g_strdup (territory_name));
828        }
829        if (ncode != NULL) {
830                g_hash_table_insert (gdm_territories_map,
831                                     g_strdup (ncode),
832                                     g_strdup (territory_name));
833        }
834}
835
836static void
837languages_init (void)
838{
839        GError  *error;
840        gboolean res;
841        char    *buf;
842        gsize    buf_len;
843
844        bindtextdomain ("iso_639", ISO_CODES_LOCALESDIR);
845        bind_textdomain_codeset ("iso_639", "UTF-8");
846
847        gdm_languages_map = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
848
849        error = NULL;
850        res = g_file_get_contents (ISO_CODES_DATADIR "/iso_639.xml",
851                                   &buf,
852                                   &buf_len,
853                                   &error);
854        if (res) {
855                GMarkupParseContext *ctx;
856                GMarkupParser        parser = { languages_parse_start_tag, NULL, NULL, NULL, NULL };
857
858                ctx = g_markup_parse_context_new (&parser, 0, NULL, NULL);
859
860                error = NULL;
861                res = g_markup_parse_context_parse (ctx, buf, buf_len, &error);
862
863                if (! res) {
864                        g_warning ("Failed to parse '%s': %s\n",
865                                   ISO_CODES_DATADIR "/iso_639.xml",
866                                   error->message);
867                        g_error_free (error);
868                }
869
870                g_markup_parse_context_free (ctx);
871                g_free (buf);
872        } else {
873                g_warning ("Failed to load '%s': %s\n",
874                           ISO_CODES_DATADIR "/iso_639.xml",
875                           error->message);
876                g_error_free (error);
877        }
878}
879
880static void
881territories_init (void)
882{
883        GError  *error;
884        gboolean res;
885        char    *buf;
886        gsize    buf_len;
887
888        bindtextdomain ("iso_3166", ISO_CODES_LOCALESDIR);
889        bind_textdomain_codeset ("iso_3166", "UTF-8");
890
891        gdm_territories_map = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
892
893        error = NULL;
894        res = g_file_get_contents (ISO_CODES_DATADIR "/iso_3166.xml",
895                                   &buf,
896                                   &buf_len,
897                                   &error);
898        if (res) {
899                GMarkupParseContext *ctx;
900                GMarkupParser        parser = { territories_parse_start_tag, NULL, NULL, NULL, NULL };
901
902                ctx = g_markup_parse_context_new (&parser, 0, NULL, NULL);
903
904                error = NULL;
905                res = g_markup_parse_context_parse (ctx, buf, buf_len, &error);
906
907                if (! res) {
908                        g_warning ("Failed to parse '%s': %s\n",
909                                   ISO_CODES_DATADIR "/iso_3166.xml",
910                                   error->message);
911                        g_error_free (error);
912                }
913
914                g_markup_parse_context_free (ctx);
915                g_free (buf);
916        } else {
917                g_warning ("Failed to load '%s': %s\n",
918                           ISO_CODES_DATADIR "/iso_3166.xml",
919                           error->message);
920                g_error_free (error);
921        }
922}
923
924char *
925gdm_get_language_from_name (const char *name,
926                            const char *locale)
927{
928        char *full_language;
929        char *language_code;
930        char *territory_code;
931        const char *language;
932        const char *territory;
933
934        if (gdm_languages_map == NULL) {
935                languages_init ();
936        }
937
938        if (gdm_territories_map == NULL) {
939                territories_init ();
940        }
941
942        language_code = NULL;
943        territory_code = NULL;
944        full_language = NULL;
945
946        gdm_parse_language_name (name, &language_code, &territory_code,
947                                 NULL, NULL);
948
949        if (language_code == NULL) {
950                goto out;
951        }
952
953        language = get_translated_language (language_code, locale);
954
955        if (territory_code != NULL) {
956                territory = get_translated_territory (territory_code, locale);
957        } else {
958                territory = NULL;
959        }
960
961        if (territory != NULL) {
962                full_language  = g_strdup_printf ("%s (%s)",
963                        language ? language : "",
964                        territory ? territory : "");
965        } else {
966                full_language  = g_strdup (language);
967        }
968
969out:
970       g_free (language_code);
971       g_free (territory_code);
972
973       return full_language;
974}
975
976char **
977gdm_get_all_language_names (void)
978{
979        GHashTableIter iter;
980        gpointer key, value;
981        GPtrArray *array;
982
983        if (gdm_available_locales_map == NULL) {
984                collect_locales ();
985        }
986
987        array = g_ptr_array_new ();
988        g_hash_table_iter_init (&iter, gdm_available_locales_map);
989        while (g_hash_table_iter_next (&iter, &key, &value)) {
990                GdmLocale *locale;
991
992                locale = (GdmLocale *) value;
993
994                g_ptr_array_add (array, g_strdup (locale->name));
995        }
996        g_ptr_array_add (array, NULL);
997
998        return (char **) g_ptr_array_free (array, FALSE);
999}
Note: See TracBrowser for help on using the repository browser.