|
 |
f05f88 |
From f7e7d11a38437305ee31c195d8e910f2230a21b4 Mon Sep 17 00:00:00 2001
|
|
 |
f05f88 |
From: Stefan Sperling <stsp@openbsd.org>
|
|
 |
f05f88 |
Date: Wed, 28 Aug 2013 18:25:34 +0200
|
|
 |
f05f88 |
Subject: [PATCH 1/4] Obtain supported locales from "locale -a" output.
|
|
 |
f05f88 |
|
|
 |
f05f88 |
Instead of parsing the locale archive file which is private to glibc
|
|
 |
f05f88 |
(see https://bugzilla.redhat.com/show_bug.cgi?id=956993), run the
|
|
 |
f05f88 |
"locale -a" command to obtain the list of supported locales.
|
|
 |
f05f88 |
|
|
 |
f05f88 |
"locale -a" is specified in POSIX and should thus exist on most UNIX-like
|
|
 |
f05f88 |
systems (e.g. on OpenBSD, which triggered the related bugzilla entry
|
|
 |
f05f88 |
because GNOME was unable to find a list of supported locales).
|
|
 |
f05f88 |
|
|
 |
f05f88 |
Keep scanning the /usr/share/locale directory as a fallback.
|
|
 |
f05f88 |
|
|
 |
f05f88 |
Remove code wrapped in #ifdef WITH_INCOMPLETE_LOCALES. This code was
|
|
 |
f05f88 |
inherited from gdm but is now unused.
|
|
 |
f05f88 |
|
|
 |
f05f88 |
https://bugzilla.gnome.org/show_bug.cgi?id=698383
|
|
 |
f05f88 |
---
|
|
 |
f05f88 |
libgnome-desktop/gnome-languages.c | 150 +++++++++----------------------------
|
|
 |
f05f88 |
1 file changed, 35 insertions(+), 115 deletions(-)
|
|
 |
f05f88 |
|
|
 |
f05f88 |
diff --git a/libgnome-desktop/gnome-languages.c b/libgnome-desktop/gnome-languages.c
|
|
 |
f05f88 |
index 18e3705..667eb81 100644
|
|
 |
f05f88 |
--- a/libgnome-desktop/gnome-languages.c
|
|
 |
f05f88 |
+++ b/libgnome-desktop/gnome-languages.c
|
|
 |
f05f88 |
@@ -17,64 +17,61 @@
|
|
 |
f05f88 |
* along with this program; if not, write to the Free Software
|
|
 |
f05f88 |
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
 |
f05f88 |
*
|
|
 |
f05f88 |
* Written by : William Jon McCann <mccann@jhu.edu>
|
|
 |
f05f88 |
* Ray Strode <rstrode@redhat.com>
|
|
 |
f05f88 |
*/
|
|
 |
f05f88 |
|
|
 |
f05f88 |
#include "config.h"
|
|
 |
f05f88 |
|
|
 |
f05f88 |
#include <stdlib.h>
|
|
 |
f05f88 |
#include <stdio.h>
|
|
 |
f05f88 |
#include <unistd.h>
|
|
 |
f05f88 |
#include <string.h>
|
|
 |
f05f88 |
#include <errno.h>
|
|
 |
f05f88 |
#include <dirent.h>
|
|
 |
f05f88 |
#include <locale.h>
|
|
 |
f05f88 |
#include <langinfo.h>
|
|
 |
f05f88 |
#include <sys/stat.h>
|
|
 |
f05f88 |
|
|
 |
f05f88 |
#include <glib.h>
|
|
 |
f05f88 |
#include <glib/gi18n.h>
|
|
 |
f05f88 |
#include <glib/gstdio.h>
|
|
 |
f05f88 |
|
|
 |
f05f88 |
#define GNOME_DESKTOP_USE_UNSTABLE_API
|
|
 |
f05f88 |
#include "gnome-languages.h"
|
|
 |
f05f88 |
|
|
 |
f05f88 |
#include <langinfo.h>
|
|
 |
f05f88 |
#ifndef __LC_LAST
|
|
 |
f05f88 |
#define __LC_LAST 13
|
|
 |
f05f88 |
#endif
|
|
 |
f05f88 |
-#include "locarchive.h"
|
|
 |
f05f88 |
|
|
 |
f05f88 |
-#define ARCHIVE_FILE LIBLOCALEDIR "/locale-archive"
|
|
 |
f05f88 |
-#define SYSTEM_ARCHIVE_FILE "/usr/lib/locale/locale-archive"
|
|
 |
f05f88 |
#define ISO_CODES_DATADIR ISO_CODES_PREFIX "/share/xml/iso-codes"
|
|
 |
f05f88 |
#define ISO_CODES_LOCALESDIR ISO_CODES_PREFIX "/share/locale"
|
|
 |
f05f88 |
|
|
 |
f05f88 |
#include "default-input-sources.h"
|
|
 |
f05f88 |
|
|
 |
f05f88 |
typedef struct _GnomeLocale {
|
|
 |
f05f88 |
char *id;
|
|
 |
f05f88 |
char *name;
|
|
 |
f05f88 |
char *language_code;
|
|
 |
f05f88 |
char *territory_code;
|
|
 |
f05f88 |
char *codeset;
|
|
 |
f05f88 |
char *modifier;
|
|
 |
f05f88 |
} GnomeLocale;
|
|
 |
f05f88 |
|
|
 |
f05f88 |
static GHashTable *gnome_languages_map;
|
|
 |
f05f88 |
static GHashTable *gnome_territories_map;
|
|
 |
f05f88 |
static GHashTable *gnome_available_locales_map;
|
|
 |
f05f88 |
static GHashTable *gnome_language_count_map;
|
|
 |
f05f88 |
static GHashTable *gnome_territory_count_map;
|
|
 |
f05f88 |
|
|
 |
f05f88 |
static char * construct_language_name (const char *language,
|
|
 |
f05f88 |
const char *territory,
|
|
 |
f05f88 |
const char *codeset,
|
|
 |
f05f88 |
const char *modifier);
|
|
 |
f05f88 |
|
|
 |
f05f88 |
static gboolean language_name_is_valid (const char *language_name);
|
|
 |
f05f88 |
|
|
 |
f05f88 |
static void
|
|
 |
f05f88 |
gnome_locale_free (GnomeLocale *locale)
|
|
 |
f05f88 |
{
|
|
 |
f05f88 |
@@ -283,65 +280,61 @@ gnome_normalize_locale (const char *locale)
|
|
 |
f05f88 |
char *modifier;
|
|
 |
f05f88 |
gboolean valid;
|
|
 |
f05f88 |
|
|
 |
f05f88 |
if (locale[0] == '\0') {
|
|
 |
f05f88 |
return NULL;
|
|
 |
f05f88 |
}
|
|
 |
f05f88 |
|
|
 |
f05f88 |
valid = gnome_parse_locale (locale,
|
|
 |
f05f88 |
&language_code,
|
|
 |
f05f88 |
&territory_code,
|
|
 |
f05f88 |
&codeset, &modifier);
|
|
 |
f05f88 |
if (!valid)
|
|
 |
f05f88 |
return NULL;
|
|
 |
f05f88 |
|
|
 |
f05f88 |
normalized_name = construct_language_name (language_code,
|
|
 |
f05f88 |
territory_code,
|
|
 |
f05f88 |
codeset, modifier);
|
|
 |
f05f88 |
g_free (language_code);
|
|
 |
f05f88 |
g_free (territory_code);
|
|
 |
f05f88 |
g_free (codeset);
|
|
 |
f05f88 |
g_free (modifier);
|
|
 |
f05f88 |
|
|
 |
f05f88 |
return normalized_name;
|
|
 |
f05f88 |
}
|
|
 |
f05f88 |
|
|
 |
f05f88 |
static gboolean
|
|
 |
f05f88 |
language_name_is_valid (const char *language_name)
|
|
 |
f05f88 |
{
|
|
 |
f05f88 |
char *old_locale;
|
|
 |
f05f88 |
gboolean is_valid;
|
|
 |
f05f88 |
-#ifdef WITH_INCOMPLETE_LOCALES
|
|
 |
f05f88 |
- int lc_type_id = LC_CTYPE;
|
|
 |
f05f88 |
-#else
|
|
 |
f05f88 |
int lc_type_id = LC_MESSAGES;
|
|
 |
f05f88 |
-#endif
|
|
 |
f05f88 |
|
|
 |
f05f88 |
old_locale = g_strdup (setlocale (lc_type_id, NULL));
|
|
 |
f05f88 |
is_valid = setlocale (lc_type_id, language_name) != NULL;
|
|
 |
f05f88 |
setlocale (lc_type_id, old_locale);
|
|
 |
f05f88 |
g_free (old_locale);
|
|
 |
f05f88 |
|
|
 |
f05f88 |
return is_valid;
|
|
 |
f05f88 |
}
|
|
 |
f05f88 |
|
|
 |
f05f88 |
static void
|
|
 |
f05f88 |
language_name_get_codeset_details (const char *language_name,
|
|
 |
f05f88 |
char **pcodeset,
|
|
 |
f05f88 |
gboolean *is_utf8)
|
|
 |
f05f88 |
{
|
|
 |
f05f88 |
char *old_locale;
|
|
 |
f05f88 |
char *codeset;
|
|
 |
f05f88 |
|
|
 |
f05f88 |
old_locale = g_strdup (setlocale (LC_CTYPE, NULL));
|
|
 |
f05f88 |
|
|
 |
f05f88 |
if (setlocale (LC_CTYPE, language_name) == NULL) {
|
|
 |
f05f88 |
g_free (old_locale);
|
|
 |
f05f88 |
return;
|
|
 |
f05f88 |
}
|
|
 |
f05f88 |
|
|
 |
f05f88 |
codeset = nl_langinfo (CODESET);
|
|
 |
f05f88 |
|
|
 |
f05f88 |
if (pcodeset != NULL) {
|
|
 |
f05f88 |
*pcodeset = g_strdup (codeset);
|
|
 |
f05f88 |
}
|
|
 |
f05f88 |
|
|
 |
f05f88 |
@@ -418,304 +411,231 @@ add_locale (const char *language_name,
|
|
 |
f05f88 |
|
|
 |
f05f88 |
if (is_utf8) {
|
|
 |
f05f88 |
name = g_strdup (language_name);
|
|
 |
f05f88 |
} else if (utf8_only) {
|
|
 |
f05f88 |
name = g_strdup_printf ("%s.utf8", language_name);
|
|
 |
f05f88 |
|
|
 |
f05f88 |
language_name_get_codeset_details (name, NULL, &is_utf8);
|
|
 |
f05f88 |
if (!is_utf8) {
|
|
 |
f05f88 |
g_free (name);
|
|
 |
f05f88 |
return FALSE;
|
|
 |
f05f88 |
}
|
|
 |
f05f88 |
} else {
|
|
 |
f05f88 |
name = g_strdup (language_name);
|
|
 |
f05f88 |
}
|
|
 |
f05f88 |
|
|
 |
f05f88 |
if (!language_name_is_valid (name)) {
|
|
 |
f05f88 |
g_debug ("Ignoring '%s' as a locale, since it's invalid", name);
|
|
 |
f05f88 |
g_free (name);
|
|
 |
f05f88 |
return FALSE;
|
|
 |
f05f88 |
}
|
|
 |
f05f88 |
|
|
 |
f05f88 |
locale = g_new0 (GnomeLocale, 1);
|
|
 |
f05f88 |
gnome_parse_locale (name,
|
|
 |
f05f88 |
&locale->language_code,
|
|
 |
f05f88 |
&locale->territory_code,
|
|
 |
f05f88 |
&locale->codeset,
|
|
 |
f05f88 |
&locale->modifier);
|
|
 |
f05f88 |
g_free (name);
|
|
 |
f05f88 |
name = NULL;
|
|
 |
f05f88 |
|
|
 |
f05f88 |
-#ifdef WITH_INCOMPLETE_LOCALES
|
|
 |
f05f88 |
- if (utf8_only) {
|
|
 |
f05f88 |
- if (locale->territory_code == NULL || locale->modifier) {
|
|
 |
f05f88 |
- g_debug ("Ignoring '%s' as a locale, since it lacks territory code or modifier", name);
|
|
 |
f05f88 |
- gnome_locale_free (locale);
|
|
 |
f05f88 |
- return FALSE;
|
|
 |
f05f88 |
- }
|
|
 |
f05f88 |
- }
|
|
 |
f05f88 |
-#endif
|
|
 |
f05f88 |
-
|
|
 |
f05f88 |
locale->id = construct_language_name (locale->language_code, locale->territory_code,
|
|
 |
f05f88 |
NULL, locale->modifier);
|
|
 |
f05f88 |
locale->name = construct_language_name (locale->language_code, locale->territory_code,
|
|
 |
f05f88 |
locale->codeset, locale->modifier);
|
|
 |
f05f88 |
|
|
 |
f05f88 |
-#ifndef WITH_INCOMPLETE_LOCALES
|
|
 |
f05f88 |
if (!gnome_language_has_translations (locale->name) &&
|
|
 |
f05f88 |
!gnome_language_has_translations (locale->id) &&
|
|
 |
f05f88 |
!gnome_language_has_translations (locale->language_code) &&
|
|
 |
f05f88 |
utf8_only) {
|
|
 |
f05f88 |
g_debug ("Ignoring '%s' as a locale, since it lacks translations", locale->name);
|
|
 |
f05f88 |
gnome_locale_free (locale);
|
|
 |
f05f88 |
return FALSE;
|
|
 |
f05f88 |
}
|
|
 |
f05f88 |
-#endif
|
|
 |
f05f88 |
|
|
 |
f05f88 |
if (!utf8_only) {
|
|
 |
f05f88 |
g_free (locale->id);
|
|
 |
f05f88 |
locale->id = g_strdup (locale->name);
|
|
 |
f05f88 |
}
|
|
 |
f05f88 |
|
|
 |
f05f88 |
old_locale = g_hash_table_lookup (gnome_available_locales_map, locale->id);
|
|
 |
f05f88 |
if (old_locale != NULL) {
|
|
 |
f05f88 |
if (strlen (old_locale->name) > strlen (locale->name)) {
|
|
 |
f05f88 |
gnome_locale_free (locale);
|
|
 |
f05f88 |
return FALSE;
|
|
 |
f05f88 |
}
|
|
 |
f05f88 |
}
|
|
 |
f05f88 |
|
|
 |
f05f88 |
g_hash_table_insert (gnome_available_locales_map, g_strdup (locale->id), locale);
|
|
 |
f05f88 |
|
|
 |
f05f88 |
return TRUE;
|
|
 |
f05f88 |
}
|
|
 |
f05f88 |
|
|
 |
f05f88 |
struct nameent
|
|
 |
f05f88 |
{
|
|
 |
f05f88 |
char *name;
|
|
 |
f05f88 |
- uint32_t locrec_offset;
|
|
 |
f05f88 |
+ guint32 locrec_offset;
|
|
 |
f05f88 |
};
|
|
 |
f05f88 |
|
|
 |
f05f88 |
-static gboolean
|
|
 |
f05f88 |
-mapped_file_new_allow_noent (const char *path,
|
|
 |
f05f88 |
- GMappedFile **out_mfile,
|
|
 |
f05f88 |
- GError **error)
|
|
 |
f05f88 |
-{
|
|
 |
f05f88 |
- gboolean ret = FALSE;
|
|
 |
f05f88 |
- GError *tmp_error = NULL;
|
|
 |
f05f88 |
- GMappedFile *mfile = NULL;
|
|
 |
f05f88 |
-
|
|
 |
f05f88 |
- mfile = g_mapped_file_new (path, FALSE, &tmp_error);
|
|
 |
f05f88 |
- if (mfile == NULL) {
|
|
 |
f05f88 |
- if (!g_error_matches (tmp_error, G_FILE_ERROR, G_FILE_ERROR_NOENT)) {
|
|
 |
f05f88 |
- g_propagate_error (error, tmp_error);
|
|
 |
f05f88 |
- goto out;
|
|
 |
f05f88 |
- }
|
|
 |
f05f88 |
- g_clear_error (&tmp_error);
|
|
 |
f05f88 |
- }
|
|
 |
f05f88 |
-
|
|
 |
f05f88 |
- ret = TRUE;
|
|
 |
f05f88 |
- out:
|
|
 |
f05f88 |
- *out_mfile = mfile;
|
|
 |
f05f88 |
- return ret;
|
|
 |
f05f88 |
-}
|
|
 |
f05f88 |
-
|
|
 |
f05f88 |
-static gboolean
|
|
 |
f05f88 |
-collect_locales_from_archive (gboolean *out_found_locales,
|
|
 |
f05f88 |
- GError **error)
|
|
 |
f05f88 |
-{
|
|
 |
f05f88 |
- gboolean ret = FALSE;
|
|
 |
f05f88 |
- GMappedFile *mapped;
|
|
 |
f05f88 |
- char *addr;
|
|
 |
f05f88 |
- struct locarhead *head;
|
|
 |
f05f88 |
- struct namehashent *namehashtab;
|
|
 |
f05f88 |
- struct nameent *names = NULL;
|
|
 |
f05f88 |
- uint32_t used;
|
|
 |
f05f88 |
- uint32_t cnt;
|
|
 |
f05f88 |
- gsize len;
|
|
 |
f05f88 |
- gboolean locales_collected = FALSE;
|
|
 |
f05f88 |
-
|
|
 |
f05f88 |
- if (!mapped_file_new_allow_noent (ARCHIVE_FILE, &mapped, error))
|
|
 |
f05f88 |
- goto out;
|
|
 |
f05f88 |
- if (!mapped) {
|
|
 |
f05f88 |
- if (!mapped_file_new_allow_noent (SYSTEM_ARCHIVE_FILE, &mapped, error))
|
|
 |
f05f88 |
- goto out;
|
|
 |
f05f88 |
- }
|
|
 |
f05f88 |
- if (!mapped) {
|
|
 |
f05f88 |
- goto out_success;
|
|
 |
f05f88 |
- }
|
|
 |
f05f88 |
-
|
|
 |
f05f88 |
- addr = g_mapped_file_get_contents (mapped);
|
|
 |
f05f88 |
- len = g_mapped_file_get_length (mapped);
|
|
 |
f05f88 |
-
|
|
 |
f05f88 |
- head = (struct locarhead *) addr;
|
|
 |
f05f88 |
- if (head->namehash_offset + head->namehash_size > len
|
|
 |
f05f88 |
- || head->string_offset + head->string_size > len
|
|
 |
f05f88 |
- || head->locrectab_offset + head->locrectab_size > len
|
|
 |
f05f88 |
- || head->sumhash_offset + head->sumhash_size > len) {
|
|
 |
f05f88 |
- goto out;
|
|
 |
f05f88 |
- }
|
|
 |
f05f88 |
-
|
|
 |
f05f88 |
- namehashtab = (struct namehashent *) (addr + head->namehash_offset);
|
|
 |
f05f88 |
-
|
|
 |
f05f88 |
- names = (struct nameent *) g_new0 (struct nameent, head->namehash_used);
|
|
 |
f05f88 |
- for (cnt = used = 0; cnt < head->namehash_size; ++cnt) {
|
|
 |
f05f88 |
- if (namehashtab[cnt].locrec_offset != 0) {
|
|
 |
f05f88 |
- names[used].name = addr + namehashtab[cnt].name_offset;
|
|
 |
f05f88 |
- names[used++].locrec_offset = namehashtab[cnt].locrec_offset;
|
|
 |
f05f88 |
- }
|
|
 |
f05f88 |
- }
|
|
 |
f05f88 |
-
|
|
 |
f05f88 |
- for (cnt = 0; cnt < used; ++cnt) {
|
|
 |
f05f88 |
- if (add_locale (names[cnt].name, TRUE))
|
|
 |
f05f88 |
- locales_collected = TRUE;
|
|
 |
f05f88 |
- }
|
|
 |
f05f88 |
-
|
|
 |
f05f88 |
-
|
|
 |
f05f88 |
- out_success:
|
|
 |
f05f88 |
- ret = TRUE;
|
|
 |
f05f88 |
- *out_found_locales = locales_collected;
|
|
 |
f05f88 |
- out:
|
|
 |
f05f88 |
- g_free (names);
|
|
 |
f05f88 |
- g_clear_pointer (&mapped, g_mapped_file_unref);
|
|
 |
f05f88 |
- return ret;
|
|
 |
f05f88 |
-}
|
|
 |
f05f88 |
-
|
|
 |
f05f88 |
static int
|
|
 |
f05f88 |
select_dirs (const struct dirent *dirent)
|
|
 |
f05f88 |
{
|
|
 |
f05f88 |
int result = 0;
|
|
 |
f05f88 |
|
|
 |
f05f88 |
if (strcmp (dirent->d_name, ".") != 0 && strcmp (dirent->d_name, "..") != 0) {
|
|
 |
f05f88 |
mode_t mode = 0;
|
|
 |
f05f88 |
|
|
 |
f05f88 |
#ifdef _DIRENT_HAVE_D_TYPE
|
|
 |
f05f88 |
if (dirent->d_type != DT_UNKNOWN && dirent->d_type != DT_LNK) {
|
|
 |
f05f88 |
mode = DTTOIF (dirent->d_type);
|
|
 |
f05f88 |
} else
|
|
 |
f05f88 |
#endif
|
|
 |
f05f88 |
{
|
|
 |
f05f88 |
struct stat st;
|
|
 |
f05f88 |
char *path;
|
|
 |
f05f88 |
|
|
 |
f05f88 |
path = g_build_filename (LIBLOCALEDIR, dirent->d_name, NULL);
|
|
 |
f05f88 |
if (g_stat (path, &st) == 0) {
|
|
 |
f05f88 |
mode = st.st_mode;
|
|
 |
f05f88 |
}
|
|
 |
f05f88 |
g_free (path);
|
|
 |
f05f88 |
}
|
|
 |
f05f88 |
|
|
 |
f05f88 |
result = S_ISDIR (mode);
|
|
 |
f05f88 |
}
|
|
 |
f05f88 |
|
|
 |
f05f88 |
return result;
|
|
 |
f05f88 |
}
|
|
 |
f05f88 |
|
|
 |
f05f88 |
static gboolean
|
|
 |
f05f88 |
collect_locales_from_directory (void)
|
|
 |
f05f88 |
{
|
|
 |
f05f88 |
gboolean found_locales = FALSE;
|
|
 |
f05f88 |
struct dirent **dirents;
|
|
 |
f05f88 |
int ndirents;
|
|
 |
f05f88 |
int cnt;
|
|
 |
f05f88 |
|
|
 |
f05f88 |
ndirents = scandir (LIBLOCALEDIR, &dirents, select_dirs, alphasort);
|
|
 |
f05f88 |
|
|
 |
f05f88 |
for (cnt = 0; cnt < ndirents; ++cnt) {
|
|
 |
f05f88 |
if (add_locale (dirents[cnt]->d_name, TRUE))
|
|
 |
f05f88 |
found_locales = TRUE;
|
|
 |
f05f88 |
}
|
|
 |
f05f88 |
|
|
 |
f05f88 |
if (ndirents > 0) {
|
|
 |
f05f88 |
free (dirents);
|
|
 |
f05f88 |
}
|
|
 |
f05f88 |
return found_locales;
|
|
 |
f05f88 |
}
|
|
 |
f05f88 |
|
|
 |
f05f88 |
+static gboolean
|
|
 |
f05f88 |
+collect_locales_from_localebin (void)
|
|
 |
f05f88 |
+{
|
|
 |
f05f88 |
+ gboolean found_locales = FALSE;
|
|
 |
f05f88 |
+ gchar *argv[] = { "locale", "-a", NULL };
|
|
 |
f05f88 |
+ gchar *output;
|
|
 |
f05f88 |
+ gchar **lines, **linep;
|
|
 |
f05f88 |
+
|
|
 |
f05f88 |
+ if (g_spawn_sync (NULL, argv, NULL,
|
|
 |
f05f88 |
+ G_SPAWN_SEARCH_PATH|G_SPAWN_STDERR_TO_DEV_NULL,
|
|
 |
f05f88 |
+ NULL, NULL, &output, NULL, NULL, NULL) == FALSE)
|
|
 |
f05f88 |
+ return FALSE;
|
|
 |
f05f88 |
+
|
|
 |
f05f88 |
+ g_return_val_if_fail (output != NULL, FALSE);
|
|
 |
f05f88 |
+
|
|
 |
f05f88 |
+ lines = g_strsplit (output, "\n", 0);
|
|
 |
f05f88 |
+ if (lines) {
|
|
 |
f05f88 |
+ linep = lines;
|
|
 |
f05f88 |
+ while (*linep) {
|
|
 |
f05f88 |
+ if (*linep[0] && add_locale (*linep, TRUE))
|
|
 |
f05f88 |
+ found_locales = TRUE;
|
|
 |
f05f88 |
+ linep++;
|
|
 |
f05f88 |
+ }
|
|
 |
f05f88 |
+ g_strfreev(lines);
|
|
 |
f05f88 |
+ }
|
|
 |
f05f88 |
+
|
|
 |
f05f88 |
+ g_free(output);
|
|
 |
f05f88 |
+
|
|
 |
f05f88 |
+ return found_locales;
|
|
 |
f05f88 |
+}
|
|
 |
f05f88 |
+
|
|
 |
f05f88 |
static void
|
|
 |
f05f88 |
count_languages_and_territories (void)
|
|
 |
f05f88 |
{
|
|
 |
f05f88 |
gpointer value;
|
|
 |
f05f88 |
GHashTableIter iter;
|
|
 |
f05f88 |
|
|
 |
f05f88 |
gnome_language_count_map = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
|
|
 |
f05f88 |
gnome_territory_count_map = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
|
|
 |
f05f88 |
|
|
 |
f05f88 |
g_hash_table_iter_init (&iter, gnome_available_locales_map);
|
|
 |
f05f88 |
while (g_hash_table_iter_next (&iter, NULL, &value)) {
|
|
 |
f05f88 |
GnomeLocale *locale;
|
|
 |
f05f88 |
|
|
 |
f05f88 |
locale = (GnomeLocale *) value;
|
|
 |
f05f88 |
|
|
 |
f05f88 |
if (locale->language_code != NULL) {
|
|
 |
f05f88 |
int count;
|
|
 |
f05f88 |
|
|
 |
f05f88 |
count = GPOINTER_TO_INT (g_hash_table_lookup (gnome_language_count_map, locale->language_code));
|
|
 |
f05f88 |
count++;
|
|
 |
f05f88 |
g_hash_table_insert (gnome_language_count_map, g_strdup (locale->language_code), GINT_TO_POINTER (count));
|
|
 |
f05f88 |
}
|
|
 |
f05f88 |
|
|
 |
f05f88 |
if (locale->territory_code != NULL) {
|
|
 |
f05f88 |
int count;
|
|
 |
f05f88 |
|
|
 |
f05f88 |
count = GPOINTER_TO_INT (g_hash_table_lookup (gnome_territory_count_map, locale->territory_code));
|
|
 |
f05f88 |
count++;
|
|
 |
f05f88 |
g_hash_table_insert (gnome_territory_count_map, g_strdup (locale->territory_code), GINT_TO_POINTER (count));
|
|
 |
f05f88 |
}
|
|
 |
f05f88 |
}
|
|
 |
f05f88 |
}
|
|
 |
f05f88 |
|
|
 |
f05f88 |
static void
|
|
 |
f05f88 |
collect_locales (void)
|
|
 |
f05f88 |
{
|
|
 |
f05f88 |
- gboolean found_archive_locales = FALSE;
|
|
 |
f05f88 |
+ gboolean found_localebin_locales = FALSE;
|
|
 |
f05f88 |
gboolean found_dir_locales = FALSE;
|
|
 |
f05f88 |
- GError *error = NULL;
|
|
 |
f05f88 |
|
|
 |
f05f88 |
if (gnome_available_locales_map == NULL) {
|
|
 |
f05f88 |
gnome_available_locales_map = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) gnome_locale_free);
|
|
 |
f05f88 |
}
|
|
 |
f05f88 |
|
|
 |
f05f88 |
-
|
|
 |
f05f88 |
- if (!collect_locales_from_archive (&found_archive_locales, &error)) {
|
|
 |
f05f88 |
- g_warning ("Failed to load locales from archive: %s", error->message);
|
|
 |
f05f88 |
- g_clear_error (&error);
|
|
 |
f05f88 |
- }
|
|
 |
f05f88 |
+ found_localebin_locales = collect_locales_from_localebin ();
|
|
 |
f05f88 |
|
|
 |
f05f88 |
found_dir_locales = collect_locales_from_directory ();
|
|
 |
f05f88 |
|
|
 |
f05f88 |
- if (!(found_archive_locales || found_dir_locales)) {
|
|
 |
f05f88 |
-#ifndef WITH_INCOMPLETE_LOCALES
|
|
 |
f05f88 |
+ if (!(found_localebin_locales || found_dir_locales)) {
|
|
 |
f05f88 |
g_warning ("Could not read list of available locales from libc, "
|
|
 |
f05f88 |
"guessing possible locales from available translations, "
|
|
 |
f05f88 |
"but list may be incomplete!");
|
|
 |
f05f88 |
-#endif
|
|
 |
f05f88 |
}
|
|
 |
f05f88 |
|
|
 |
f05f88 |
count_languages_and_territories ();
|
|
 |
f05f88 |
}
|
|
 |
f05f88 |
|
|
 |
f05f88 |
static gint
|
|
 |
f05f88 |
get_language_count (const char *language)
|
|
 |
f05f88 |
{
|
|
 |
f05f88 |
if (gnome_language_count_map == NULL) {
|
|
 |
f05f88 |
collect_locales ();
|
|
 |
f05f88 |
}
|
|
 |
f05f88 |
|
|
 |
f05f88 |
return GPOINTER_TO_INT (g_hash_table_lookup (gnome_language_count_map, language));
|
|
 |
f05f88 |
}
|
|
 |
f05f88 |
|
|
 |
f05f88 |
static gboolean
|
|
 |
f05f88 |
is_unique_language (const char *language)
|
|
 |
f05f88 |
{
|
|
 |
f05f88 |
return get_language_count (language) == 1;
|
|
 |
f05f88 |
}
|
|
 |
f05f88 |
|
|
 |
f05f88 |
static gint
|
|
 |
f05f88 |
get_territory_count (const char *territory)
|
|
 |
f05f88 |
{
|
|
 |
f05f88 |
if (gnome_territory_count_map == NULL) {
|
|
 |
f05f88 |
collect_locales ();
|
|
 |
f05f88 |
}
|
|
 |
f05f88 |
|
|
 |
f05f88 |
return GPOINTER_TO_INT (g_hash_table_lookup (gnome_territory_count_map, territory));
|
|
 |
f05f88 |
}
|
|
 |
f05f88 |
--
|
|
 |
f05f88 |
1.8.4.2
|
|
 |
f05f88 |
|
|
 |
f05f88 |
|
|
 |
f05f88 |
From 1dbefdc924691017e2ce9c3380b447bae8211723 Mon Sep 17 00:00:00 2001
|
|
 |
f05f88 |
From: Stefan Sperling <stsp@stsp.name>
|
|
 |
f05f88 |
Date: Wed, 2 Oct 2013 18:58:17 +0200
|
|
 |
f05f88 |
Subject: [PATCH 2/4] languages: Style fix in collect_locales_from_localebin()
|
|
 |
f05f88 |
|
|
 |
f05f88 |
Use spare-before-paren syntax for function calls.
|
|
 |
f05f88 |
---
|
|
 |
f05f88 |
libgnome-desktop/gnome-languages.c | 4 ++--
|
|
 |
f05f88 |
1 file changed, 2 insertions(+), 2 deletions(-)
|
|
 |
f05f88 |
|
|
 |
f05f88 |
diff --git a/libgnome-desktop/gnome-languages.c b/libgnome-desktop/gnome-languages.c
|
|
 |
f05f88 |
index 667eb81..f3e3d06 100644
|
|
 |
f05f88 |
--- a/libgnome-desktop/gnome-languages.c
|
|
 |
f05f88 |
+++ b/libgnome-desktop/gnome-languages.c
|
|
 |
f05f88 |
@@ -523,64 +523,64 @@ collect_locales_from_directory (void)
|
|
 |
f05f88 |
|
|
 |
f05f88 |
if (ndirents > 0) {
|
|
 |
f05f88 |
free (dirents);
|
|
 |
f05f88 |
}
|
|
 |
f05f88 |
return found_locales;
|
|
 |
f05f88 |
}
|
|
 |
f05f88 |
|
|
 |
f05f88 |
static gboolean
|
|
 |
f05f88 |
collect_locales_from_localebin (void)
|
|
 |
f05f88 |
{
|
|
 |
f05f88 |
gboolean found_locales = FALSE;
|
|
 |
f05f88 |
gchar *argv[] = { "locale", "-a", NULL };
|
|
 |
f05f88 |
gchar *output;
|
|
 |
f05f88 |
gchar **lines, **linep;
|
|
 |
f05f88 |
|
|
 |
f05f88 |
if (g_spawn_sync (NULL, argv, NULL,
|
|
 |
f05f88 |
G_SPAWN_SEARCH_PATH|G_SPAWN_STDERR_TO_DEV_NULL,
|
|
 |
f05f88 |
NULL, NULL, &output, NULL, NULL, NULL) == FALSE)
|
|
 |
f05f88 |
return FALSE;
|
|
 |
f05f88 |
|
|
 |
f05f88 |
g_return_val_if_fail (output != NULL, FALSE);
|
|
 |
f05f88 |
|
|
 |
f05f88 |
lines = g_strsplit (output, "\n", 0);
|
|
 |
f05f88 |
if (lines) {
|
|
 |
f05f88 |
linep = lines;
|
|
 |
f05f88 |
while (*linep) {
|
|
 |
f05f88 |
if (*linep[0] && add_locale (*linep, TRUE))
|
|
 |
f05f88 |
found_locales = TRUE;
|
|
 |
f05f88 |
linep++;
|
|
 |
f05f88 |
}
|
|
 |
f05f88 |
- g_strfreev(lines);
|
|
 |
f05f88 |
+ g_strfreev (lines);
|
|
 |
f05f88 |
}
|
|
 |
f05f88 |
|
|
 |
f05f88 |
- g_free(output);
|
|
 |
f05f88 |
+ g_free (output);
|
|
 |
f05f88 |
|
|
 |
f05f88 |
return found_locales;
|
|
 |
f05f88 |
}
|
|
 |
f05f88 |
|
|
 |
f05f88 |
static void
|
|
 |
f05f88 |
count_languages_and_territories (void)
|
|
 |
f05f88 |
{
|
|
 |
f05f88 |
gpointer value;
|
|
 |
f05f88 |
GHashTableIter iter;
|
|
 |
f05f88 |
|
|
 |
f05f88 |
gnome_language_count_map = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
|
|
 |
f05f88 |
gnome_territory_count_map = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
|
|
 |
f05f88 |
|
|
 |
f05f88 |
g_hash_table_iter_init (&iter, gnome_available_locales_map);
|
|
 |
f05f88 |
while (g_hash_table_iter_next (&iter, NULL, &value)) {
|
|
 |
f05f88 |
GnomeLocale *locale;
|
|
 |
f05f88 |
|
|
 |
f05f88 |
locale = (GnomeLocale *) value;
|
|
 |
f05f88 |
|
|
 |
f05f88 |
if (locale->language_code != NULL) {
|
|
 |
f05f88 |
int count;
|
|
 |
f05f88 |
|
|
 |
f05f88 |
count = GPOINTER_TO_INT (g_hash_table_lookup (gnome_language_count_map, locale->language_code));
|
|
 |
f05f88 |
count++;
|
|
 |
f05f88 |
g_hash_table_insert (gnome_language_count_map, g_strdup (locale->language_code), GINT_TO_POINTER (count));
|
|
 |
f05f88 |
}
|
|
 |
f05f88 |
|
|
 |
f05f88 |
if (locale->territory_code != NULL) {
|
|
 |
f05f88 |
int count;
|
|
 |
f05f88 |
|
|
 |
f05f88 |
--
|
|
 |
f05f88 |
1.8.4.2
|
|
 |
f05f88 |
|
|
 |
f05f88 |
|
|
 |
f05f88 |
From 9460a9fa6eff78d7ba1f176447550f66cecac770 Mon Sep 17 00:00:00 2001
|
|
 |
f05f88 |
From: Stefan Sperling <stsp@stsp.name>
|
|
 |
f05f88 |
Date: Wed, 2 Oct 2013 18:59:11 +0200
|
|
 |
f05f88 |
Subject: [PATCH 3/4] languages: Remove unused struct "nameent"
|
|
 |
f05f88 |
|
|
 |
f05f88 |
This struct was a left-over from the libc locale archive parsing code
|
|
 |
f05f88 |
removed in commit 91082e8d0ef7dc3fe372fb5228fd3bb5a26efa81.
|
|
 |
f05f88 |
---
|
|
 |
f05f88 |
libgnome-desktop/gnome-languages.c | 6 ------
|
|
 |
f05f88 |
1 file changed, 6 deletions(-)
|
|
 |
f05f88 |
|
|
 |
f05f88 |
diff --git a/libgnome-desktop/gnome-languages.c b/libgnome-desktop/gnome-languages.c
|
|
 |
f05f88 |
index f3e3d06..a4f9bd2 100644
|
|
 |
f05f88 |
--- a/libgnome-desktop/gnome-languages.c
|
|
 |
f05f88 |
+++ b/libgnome-desktop/gnome-languages.c
|
|
 |
f05f88 |
@@ -443,66 +443,60 @@ add_locale (const char *language_name,
|
|
 |
f05f88 |
locale->name = construct_language_name (locale->language_code, locale->territory_code,
|
|
 |
f05f88 |
locale->codeset, locale->modifier);
|
|
 |
f05f88 |
|
|
 |
f05f88 |
if (!gnome_language_has_translations (locale->name) &&
|
|
 |
f05f88 |
!gnome_language_has_translations (locale->id) &&
|
|
 |
f05f88 |
!gnome_language_has_translations (locale->language_code) &&
|
|
 |
f05f88 |
utf8_only) {
|
|
 |
f05f88 |
g_debug ("Ignoring '%s' as a locale, since it lacks translations", locale->name);
|
|
 |
f05f88 |
gnome_locale_free (locale);
|
|
 |
f05f88 |
return FALSE;
|
|
 |
f05f88 |
}
|
|
 |
f05f88 |
|
|
 |
f05f88 |
if (!utf8_only) {
|
|
 |
f05f88 |
g_free (locale->id);
|
|
 |
f05f88 |
locale->id = g_strdup (locale->name);
|
|
 |
f05f88 |
}
|
|
 |
f05f88 |
|
|
 |
f05f88 |
old_locale = g_hash_table_lookup (gnome_available_locales_map, locale->id);
|
|
 |
f05f88 |
if (old_locale != NULL) {
|
|
 |
f05f88 |
if (strlen (old_locale->name) > strlen (locale->name)) {
|
|
 |
f05f88 |
gnome_locale_free (locale);
|
|
 |
f05f88 |
return FALSE;
|
|
 |
f05f88 |
}
|
|
 |
f05f88 |
}
|
|
 |
f05f88 |
|
|
 |
f05f88 |
g_hash_table_insert (gnome_available_locales_map, g_strdup (locale->id), locale);
|
|
 |
f05f88 |
|
|
 |
f05f88 |
return TRUE;
|
|
 |
f05f88 |
}
|
|
 |
f05f88 |
|
|
 |
f05f88 |
-struct nameent
|
|
 |
f05f88 |
-{
|
|
 |
f05f88 |
- char *name;
|
|
 |
f05f88 |
- guint32 locrec_offset;
|
|
 |
f05f88 |
-};
|
|
 |
f05f88 |
-
|
|
 |
f05f88 |
static int
|
|
 |
f05f88 |
select_dirs (const struct dirent *dirent)
|
|
 |
f05f88 |
{
|
|
 |
f05f88 |
int result = 0;
|
|
 |
f05f88 |
|
|
 |
f05f88 |
if (strcmp (dirent->d_name, ".") != 0 && strcmp (dirent->d_name, "..") != 0) {
|
|
 |
f05f88 |
mode_t mode = 0;
|
|
 |
f05f88 |
|
|
 |
f05f88 |
#ifdef _DIRENT_HAVE_D_TYPE
|
|
 |
f05f88 |
if (dirent->d_type != DT_UNKNOWN && dirent->d_type != DT_LNK) {
|
|
 |
f05f88 |
mode = DTTOIF (dirent->d_type);
|
|
 |
f05f88 |
} else
|
|
 |
f05f88 |
#endif
|
|
 |
f05f88 |
{
|
|
 |
f05f88 |
struct stat st;
|
|
 |
f05f88 |
char *path;
|
|
 |
f05f88 |
|
|
 |
f05f88 |
path = g_build_filename (LIBLOCALEDIR, dirent->d_name, NULL);
|
|
 |
f05f88 |
if (g_stat (path, &st) == 0) {
|
|
 |
f05f88 |
mode = st.st_mode;
|
|
 |
f05f88 |
}
|
|
 |
f05f88 |
g_free (path);
|
|
 |
f05f88 |
}
|
|
 |
f05f88 |
|
|
 |
f05f88 |
result = S_ISDIR (mode);
|
|
 |
f05f88 |
}
|
|
 |
f05f88 |
|
|
 |
f05f88 |
return result;
|
|
 |
f05f88 |
}
|
|
 |
f05f88 |
|
|
 |
f05f88 |
--
|
|
 |
f05f88 |
1.8.4.2
|
|
 |
f05f88 |
|
|
 |
f05f88 |
|
|
 |
f05f88 |
From c02734c975d121a8200a4de0628ab073720e7eae Mon Sep 17 00:00:00 2001
|
|
 |
f05f88 |
From: Florian Weimer <fweimer@redhat.com>
|
|
 |
f05f88 |
Date: Fri, 20 Dec 2013 11:59:08 +0100
|
|
 |
f05f88 |
Subject: [PATCH 4/4] Remove locarchive.h
|
|
 |
f05f88 |
|
|
 |
f05f88 |
This include file is no longer needed since the switch to
|
|
 |
f05f88 |
"locale -a" for listing locales.
|
|
 |
f05f88 |
|
|
 |
f05f88 |
https://bugzilla.gnome.org/show_bug.cgi?id=720815
|
|
 |
f05f88 |
---
|
|
 |
f05f88 |
libgnome-desktop/Makefile.am | 3 +--
|
|
 |
f05f88 |
1 file changed, 1 insertion(+), 2 deletions(-)
|
|
 |
f05f88 |
|
|
 |
f05f88 |
diff --git a/libgnome-desktop/Makefile.am b/libgnome-desktop/Makefile.am
|
|
 |
f05f88 |
index 7041be5..e2382b6 100644
|
|
 |
f05f88 |
--- a/libgnome-desktop/Makefile.am
|
|
 |
f05f88 |
+++ b/libgnome-desktop/Makefile.am
|
|
 |
f05f88 |
@@ -19,62 +19,61 @@ AM_CPPFLAGS = \
|
|
 |
f05f88 |
AM_CFLAGS = $(WARN_CFLAGS)
|
|
 |
f05f88 |
|
|
 |
f05f88 |
libgsystem_srcpath := libgsystem
|
|
 |
f05f88 |
libgsystem_cflags = $(GNOME_DESKTOP_CFLAGS)
|
|
 |
f05f88 |
libgsystem_libs = $(GNOME_DESKTOP_LIBS)
|
|
 |
f05f88 |
include libgsystem/Makefile-libgsystem.am
|
|
 |
f05f88 |
|
|
 |
f05f88 |
introspection_sources = \
|
|
 |
f05f88 |
gnome-desktop-thumbnail.c \
|
|
 |
f05f88 |
gnome-thumbnail-pixbuf-utils.c \
|
|
 |
f05f88 |
gnome-bg.c \
|
|
 |
f05f88 |
gnome-bg-slide-show.c \
|
|
 |
f05f88 |
gnome-bg-crossfade.c \
|
|
 |
f05f88 |
display-name.c \
|
|
 |
f05f88 |
gnome-rr.c \
|
|
 |
f05f88 |
gnome-rr-config.c \
|
|
 |
f05f88 |
gnome-rr-output-info.c \
|
|
 |
f05f88 |
gnome-pnp-ids.c \
|
|
 |
f05f88 |
gnome-wall-clock.c \
|
|
 |
f05f88 |
gnome-xkb-info.c \
|
|
 |
f05f88 |
gnome-idle-monitor.c \
|
|
 |
f05f88 |
gnome-languages.c \
|
|
 |
f05f88 |
edid-parse.c
|
|
 |
f05f88 |
|
|
 |
f05f88 |
libgnome_desktop_3_la_SOURCES = \
|
|
 |
f05f88 |
$(introspection_sources) \
|
|
 |
f05f88 |
gnome-datetime-source.h \
|
|
 |
f05f88 |
gnome-datetime-source.c \
|
|
 |
f05f88 |
gnome-rr-private.h \
|
|
 |
f05f88 |
default-input-sources.h \
|
|
 |
f05f88 |
- edid.h \
|
|
 |
f05f88 |
- locarchive.h
|
|
 |
f05f88 |
+ edid.h
|
|
 |
f05f88 |
|
|
 |
f05f88 |
libgnome_desktop_3_la_LIBADD = \
|
|
 |
f05f88 |
$(XLIB_LIBS) \
|
|
 |
f05f88 |
$(LIBM) \
|
|
 |
f05f88 |
$(GNOME_DESKTOP_LIBS) \
|
|
 |
f05f88 |
libgsystem.la \
|
|
 |
f05f88 |
-lrt
|
|
 |
f05f88 |
|
|
 |
f05f88 |
libgnome_desktop_3_la_LDFLAGS = \
|
|
 |
f05f88 |
-version-info $(LT_VERSION) \
|
|
 |
f05f88 |
-export-symbols-regex "^gnome_.*" \
|
|
 |
f05f88 |
-no-undefined
|
|
 |
f05f88 |
|
|
 |
f05f88 |
pkgconfigdir = $(libdir)/pkgconfig
|
|
 |
f05f88 |
pkgconfig_DATA = gnome-desktop-3.0.pc
|
|
 |
f05f88 |
|
|
 |
f05f88 |
libgnome_desktopdir = $(includedir)/gnome-desktop-3.0/libgnome-desktop
|
|
 |
f05f88 |
libgnome_desktop_HEADERS = \
|
|
 |
f05f88 |
gnome-bg.h \
|
|
 |
f05f88 |
gnome-bg-crossfade.h \
|
|
 |
f05f88 |
gnome-bg-slide-show.h \
|
|
 |
f05f88 |
gnome-desktop-thumbnail.h \
|
|
 |
f05f88 |
gnome-rr.h \
|
|
 |
f05f88 |
gnome-rr-config.h \
|
|
 |
f05f88 |
gnome-pnp-ids.h \
|
|
 |
f05f88 |
gnome-wall-clock.h \
|
|
 |
f05f88 |
gnome-xkb-info.h \
|
|
 |
f05f88 |
gnome-idle-monitor.h \
|
|
 |
f05f88 |
gnome-languages.h
|
|
 |
f05f88 |
|
|
 |
f05f88 |
--
|
|
 |
f05f88 |
1.8.4.2
|
|
 |
f05f88 |
|