Blame libgnome-desktop/gnome-xkb-info.c

rpm-build 18b009
/*
rpm-build 18b009
 * Copyright (C) 2012 Red Hat, Inc.
rpm-build 18b009
 *
rpm-build 18b009
 * Written by: Rui Matos <rmatos@redhat.com>
rpm-build 18b009
 *
rpm-build 18b009
 * This program is free software; you can redistribute it and/or modify
rpm-build 18b009
 * it under the terms of the GNU General Public License as published by
rpm-build 18b009
 * the Free Software Foundation; either version 2, or (at your option)
rpm-build 18b009
 * any later version.
rpm-build 18b009
 *
rpm-build 18b009
 * This program is distributed in the hope that it will be useful,
rpm-build 18b009
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
rpm-build 18b009
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
rpm-build 18b009
 * GNU General Public License for more details.
rpm-build 18b009
 *
rpm-build 18b009
 * You should have received a copy of the GNU General Public License
rpm-build 18b009
 * along with this program; if not, write to the Free Software
rpm-build 18b009
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
rpm-build 18b009
 * 02110-1301, USA.
rpm-build 18b009
 */
rpm-build 18b009
rpm-build 18b009
#include <config.h>
rpm-build 18b009
rpm-build 18b009
#include <stdio.h>
rpm-build 18b009
#include <stdlib.h>
rpm-build 18b009
#include <string.h>
rpm-build 18b009
rpm-build 18b009
#include <gio/gio.h>
rpm-build 18b009
rpm-build 18b009
#include <glib/gi18n-lib.h>
rpm-build 18b009
#define XKEYBOARD_CONFIG_(String) ((char *) g_dgettext ("xkeyboard-config", String))
rpm-build 18b009
rpm-build 18b009
#define GNOME_DESKTOP_USE_UNSTABLE_API
rpm-build 18b009
#include "gnome-languages.h"
rpm-build 18b009
#include "gnome-xkb-info.h"
rpm-build 18b009
rpm-build 18b009
#ifndef XKB_RULES_FILE
rpm-build 18b009
#define XKB_RULES_FILE "evdev"
rpm-build 18b009
#endif
rpm-build 18b009
rpm-build 18b009
typedef struct _Layout Layout;
rpm-build 18b009
struct _Layout
rpm-build 18b009
{
rpm-build 18b009
  gchar *id;
rpm-build 18b009
  gchar *xkb_name;
rpm-build 18b009
  gchar *short_desc;
rpm-build 18b009
  gchar *description;
rpm-build 18b009
  gboolean is_variant;
rpm-build 18b009
  const Layout *main_layout;
rpm-build 18b009
  GSList *iso639Ids;
rpm-build 18b009
  GSList *iso3166Ids;
rpm-build 18b009
};
rpm-build 18b009
rpm-build 18b009
typedef struct _XkbOption XkbOption;
rpm-build 18b009
struct _XkbOption
rpm-build 18b009
{
rpm-build 18b009
  gchar *id;
rpm-build 18b009
  gchar *description;
rpm-build 18b009
};
rpm-build 18b009
rpm-build 18b009
typedef struct _XkbOptionGroup XkbOptionGroup;
rpm-build 18b009
struct _XkbOptionGroup
rpm-build 18b009
{
rpm-build 18b009
  gchar *id;
rpm-build 18b009
  gchar *description;
rpm-build 18b009
  gboolean allow_multiple_selection;
rpm-build 18b009
  GHashTable *options_table;
rpm-build 18b009
};
rpm-build 18b009
rpm-build 18b009
struct _GnomeXkbInfoPrivate
rpm-build 18b009
{
rpm-build 18b009
  GHashTable *option_groups_table;
rpm-build 18b009
  GHashTable *layouts_by_country;
rpm-build 18b009
  GHashTable *layouts_by_language;
rpm-build 18b009
  GHashTable *layouts_table;
rpm-build 18b009
rpm-build 18b009
  /* Only used while parsing */
rpm-build 18b009
  XkbOptionGroup *current_parser_group;
rpm-build 18b009
  XkbOption *current_parser_option;
rpm-build 18b009
  Layout *current_parser_layout;
rpm-build 18b009
  Layout *current_parser_variant;
rpm-build 18b009
  gchar  *current_parser_iso639Id;
rpm-build 18b009
  gchar  *current_parser_iso3166Id;
rpm-build 18b009
  gchar **current_parser_text;
rpm-build 18b009
};
rpm-build 18b009
rpm-build 18b009
G_DEFINE_TYPE (GnomeXkbInfo, gnome_xkb_info, G_TYPE_OBJECT);
rpm-build 18b009
rpm-build 18b009
static void
rpm-build 18b009
free_layout (gpointer data)
rpm-build 18b009
{
rpm-build 18b009
  Layout *layout = data;
rpm-build 18b009
rpm-build 18b009
  g_return_if_fail (layout != NULL);
rpm-build 18b009
rpm-build 18b009
  g_free (layout->id);
rpm-build 18b009
  g_free (layout->xkb_name);
rpm-build 18b009
  g_free (layout->short_desc);
rpm-build 18b009
  g_free (layout->description);
rpm-build 18b009
  g_slist_free_full (layout->iso639Ids, g_free);
rpm-build 18b009
  g_slist_free_full (layout->iso3166Ids, g_free);
rpm-build 18b009
  g_slice_free (Layout, layout);
rpm-build 18b009
}
rpm-build 18b009
rpm-build 18b009
static void
rpm-build 18b009
free_option (gpointer data)
rpm-build 18b009
{
rpm-build 18b009
  XkbOption *option = data;
rpm-build 18b009
rpm-build 18b009
  g_return_if_fail (option != NULL);
rpm-build 18b009
rpm-build 18b009
  g_free (option->id);
rpm-build 18b009
  g_free (option->description);
rpm-build 18b009
  g_slice_free (XkbOption, option);
rpm-build 18b009
}
rpm-build 18b009
rpm-build 18b009
static void
rpm-build 18b009
free_option_group (gpointer data)
rpm-build 18b009
{
rpm-build 18b009
  XkbOptionGroup *group = data;
rpm-build 18b009
rpm-build 18b009
  g_return_if_fail (group != NULL);
rpm-build 18b009
rpm-build 18b009
  g_free (group->id);
rpm-build 18b009
  g_free (group->description);
rpm-build 18b009
  g_hash_table_destroy (group->options_table);
rpm-build 18b009
  g_slice_free (XkbOptionGroup, group);
rpm-build 18b009
}
rpm-build 18b009
rpm-build 18b009
static gchar *
rpm-build 18b009
get_xml_rules_file_path (const gchar *suffix)
rpm-build 18b009
{
rpm-build 18b009
  gchar *rules_file;
rpm-build 18b009
  gchar *xml_rules_file;
rpm-build 18b009
rpm-build 18b009
  rules_file = g_build_filename (XKB_BASE, "rules", XKB_RULES_FILE, NULL);
rpm-build 18b009
  xml_rules_file = g_strdup_printf ("%s%s", rules_file, suffix);
rpm-build 18b009
  g_free (rules_file);
rpm-build 18b009
rpm-build 18b009
  return xml_rules_file;
rpm-build 18b009
}
rpm-build 18b009
rpm-build 18b009
static void
rpm-build 18b009
parse_start_element (GMarkupParseContext  *context,
rpm-build 18b009
                     const gchar          *element_name,
rpm-build 18b009
                     const gchar         **attribute_names,
rpm-build 18b009
                     const gchar         **attribute_values,
rpm-build 18b009
                     gpointer              data,
rpm-build 18b009
                     GError              **error)
rpm-build 18b009
{
rpm-build 18b009
  GnomeXkbInfoPrivate *priv = GNOME_XKB_INFO (data)->priv;
rpm-build 18b009
rpm-build 18b009
  if (priv->current_parser_text)
rpm-build 18b009
    {
rpm-build 18b009
      g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT,
rpm-build 18b009
                   "Expected character data but got element '%s'", element_name);
rpm-build 18b009
      return;
rpm-build 18b009
    }
rpm-build 18b009
rpm-build 18b009
  if (strcmp (element_name, "name") == 0)
rpm-build 18b009
    {
rpm-build 18b009
      if (priv->current_parser_variant)
rpm-build 18b009
        priv->current_parser_text = &priv->current_parser_variant->xkb_name;
rpm-build 18b009
      else if (priv->current_parser_layout)
rpm-build 18b009
        priv->current_parser_text = &priv->current_parser_layout->xkb_name;
rpm-build 18b009
      else if (priv->current_parser_option)
rpm-build 18b009
        priv->current_parser_text = &priv->current_parser_option->id;
rpm-build 18b009
      else if (priv->current_parser_group)
rpm-build 18b009
        priv->current_parser_text = &priv->current_parser_group->id;
rpm-build 18b009
    }
rpm-build 18b009
  else if (strcmp (element_name, "description") == 0)
rpm-build 18b009
    {
rpm-build 18b009
      if (priv->current_parser_variant)
rpm-build 18b009
        priv->current_parser_text = &priv->current_parser_variant->description;
rpm-build 18b009
      else if (priv->current_parser_layout)
rpm-build 18b009
        priv->current_parser_text = &priv->current_parser_layout->description;
rpm-build 18b009
      else if (priv->current_parser_option)
rpm-build 18b009
        priv->current_parser_text = &priv->current_parser_option->description;
rpm-build 18b009
      else if (priv->current_parser_group)
rpm-build 18b009
        priv->current_parser_text = &priv->current_parser_group->description;
rpm-build 18b009
    }
rpm-build 18b009
  else if (strcmp (element_name, "shortDescription") == 0)
rpm-build 18b009
    {
rpm-build 18b009
      if (priv->current_parser_variant)
rpm-build 18b009
        priv->current_parser_text = &priv->current_parser_variant->short_desc;
rpm-build 18b009
      else if (priv->current_parser_layout)
rpm-build 18b009
        priv->current_parser_text = &priv->current_parser_layout->short_desc;
rpm-build 18b009
    }
rpm-build 18b009
  else if (strcmp (element_name, "iso639Id") == 0)
rpm-build 18b009
    {
rpm-build 18b009
      priv->current_parser_text = &priv->current_parser_iso639Id;
rpm-build 18b009
    }
rpm-build 18b009
  else if (strcmp (element_name, "iso3166Id") == 0)
rpm-build 18b009
    {
rpm-build 18b009
      priv->current_parser_text = &priv->current_parser_iso3166Id;
rpm-build 18b009
    }
rpm-build 18b009
  else if (strcmp (element_name, "layout") == 0)
rpm-build 18b009
    {
rpm-build 18b009
      if (priv->current_parser_layout)
rpm-build 18b009
        {
rpm-build 18b009
          g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT,
rpm-build 18b009
                       "'layout' elements can't be nested");
rpm-build 18b009
          return;
rpm-build 18b009
        }
rpm-build 18b009
rpm-build 18b009
      priv->current_parser_layout = g_slice_new0 (Layout);
rpm-build 18b009
    }
rpm-build 18b009
  else if (strcmp (element_name, "variant") == 0)
rpm-build 18b009
    {
rpm-build 18b009
      Layout *layout;
rpm-build 18b009
rpm-build 18b009
      if (priv->current_parser_variant)
rpm-build 18b009
        {
rpm-build 18b009
          g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT,
rpm-build 18b009
                       "'variant' elements can't be nested");
rpm-build 18b009
          return;
rpm-build 18b009
        }
rpm-build 18b009
rpm-build 18b009
      if (!priv->current_parser_layout)
rpm-build 18b009
        {
rpm-build 18b009
          g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT,
rpm-build 18b009
                       "'variant' elements must be inside 'layout' elements");
rpm-build 18b009
          return;
rpm-build 18b009
        }
rpm-build 18b009
rpm-build 18b009
      if (!priv->current_parser_layout->xkb_name)
rpm-build 18b009
        {
rpm-build 18b009
          g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT,
rpm-build 18b009
                       "'variant' elements must be inside named 'layout' elements");
rpm-build 18b009
          return;
rpm-build 18b009
        }
rpm-build 18b009
rpm-build 18b009
      layout = g_hash_table_lookup (priv->layouts_table, priv->current_parser_layout->xkb_name);
rpm-build 18b009
      if (!layout)
rpm-build 18b009
        layout = priv->current_parser_layout;
rpm-build 18b009
rpm-build 18b009
      priv->current_parser_variant = g_slice_new0 (Layout);
rpm-build 18b009
      priv->current_parser_variant->is_variant = TRUE;
rpm-build 18b009
      priv->current_parser_variant->main_layout = layout;
rpm-build 18b009
    }
rpm-build 18b009
  else if (strcmp (element_name, "group") == 0)
rpm-build 18b009
    {
rpm-build 18b009
      if (priv->current_parser_group)
rpm-build 18b009
        {
rpm-build 18b009
          g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT,
rpm-build 18b009
                       "'group' elements can't be nested");
rpm-build 18b009
          return;
rpm-build 18b009
        }
rpm-build 18b009
rpm-build 18b009
      priv->current_parser_group = g_slice_new0 (XkbOptionGroup);
rpm-build 18b009
      /* Maps option ids to XkbOption structs. Owns the XkbOption structs. */
rpm-build 18b009
      priv->current_parser_group->options_table = g_hash_table_new_full (g_str_hash, g_str_equal,
rpm-build 18b009
                                                                         NULL, free_option);
rpm-build 18b009
      g_markup_collect_attributes (element_name,
rpm-build 18b009
                                   attribute_names,
rpm-build 18b009
                                   attribute_values,
rpm-build 18b009
                                   error,
rpm-build 18b009
                                   G_MARKUP_COLLECT_BOOLEAN | G_MARKUP_COLLECT_OPTIONAL,
rpm-build 18b009
                                   "allowMultipleSelection",
rpm-build 18b009
                                   &priv->current_parser_group->allow_multiple_selection,
rpm-build 18b009
                                   G_MARKUP_COLLECT_INVALID);
rpm-build 18b009
    }
rpm-build 18b009
  else if (strcmp (element_name, "option") == 0)
rpm-build 18b009
    {
rpm-build 18b009
      if (priv->current_parser_option)
rpm-build 18b009
        {
rpm-build 18b009
          g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT,
rpm-build 18b009
                       "'option' elements can't be nested");
rpm-build 18b009
          return;
rpm-build 18b009
        }
rpm-build 18b009
rpm-build 18b009
      if (!priv->current_parser_group)
rpm-build 18b009
        {
rpm-build 18b009
          g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT,
rpm-build 18b009
                       "'option' elements must be inside 'group' elements");
rpm-build 18b009
          return;
rpm-build 18b009
        }
rpm-build 18b009
rpm-build 18b009
      priv->current_parser_option = g_slice_new0 (XkbOption);
rpm-build 18b009
    }
rpm-build 18b009
}
rpm-build 18b009
rpm-build 18b009
static void
rpm-build 18b009
add_layout_to_table (GHashTable  *table,
rpm-build 18b009
                     const gchar *key,
rpm-build 18b009
                     Layout      *layout)
rpm-build 18b009
{
rpm-build 18b009
  GHashTable *set;
rpm-build 18b009
rpm-build 18b009
  if (!layout->id)
rpm-build 18b009
    return;
rpm-build 18b009
rpm-build 18b009
  set = g_hash_table_lookup (table, key);
rpm-build 18b009
  if (!set)
rpm-build 18b009
    {
rpm-build 18b009
      set = g_hash_table_new (g_str_hash, g_str_equal);
rpm-build 18b009
      g_hash_table_replace (table, g_strdup (key), set);
rpm-build 18b009
    }
rpm-build 18b009
  else
rpm-build 18b009
    {
rpm-build 18b009
      if (g_hash_table_contains (set, layout->id))
rpm-build 18b009
        return;
rpm-build 18b009
    }
rpm-build 18b009
  g_hash_table_replace (set, layout->id, layout);
rpm-build 18b009
}
rpm-build 18b009
rpm-build 18b009
static void
rpm-build 18b009
add_layout_to_locale_tables (Layout     *layout,
rpm-build 18b009
                             GHashTable *layouts_by_language,
rpm-build 18b009
                             GHashTable *layouts_by_country)
rpm-build 18b009
{
rpm-build 18b009
  GSList *l, *lang_codes, *country_codes;
rpm-build 18b009
  gchar *language, *country;
rpm-build 18b009
rpm-build 18b009
  lang_codes = layout->iso639Ids;
rpm-build 18b009
  country_codes = layout->iso3166Ids;
rpm-build 18b009
rpm-build 18b009
  if (layout->is_variant)
rpm-build 18b009
    {
rpm-build 18b009
      if (!lang_codes)
rpm-build 18b009
        lang_codes = layout->main_layout->iso639Ids;
rpm-build 18b009
      if (!country_codes)
rpm-build 18b009
        country_codes = layout->main_layout->iso3166Ids;
rpm-build 18b009
    }
rpm-build 18b009
rpm-build 18b009
  for (l = lang_codes; l; l = l->next)
rpm-build 18b009
    {
rpm-build 18b009
      language = gnome_get_language_from_code ((gchar *) l->data, NULL);
rpm-build 18b009
      if (language)
rpm-build 18b009
        {
rpm-build 18b009
          add_layout_to_table (layouts_by_language, language, layout);
rpm-build 18b009
          g_free (language);
rpm-build 18b009
        }
rpm-build 18b009
    }
rpm-build 18b009
rpm-build 18b009
  for (l = country_codes; l; l = l->next)
rpm-build 18b009
    {
rpm-build 18b009
      country = gnome_get_country_from_code ((gchar *) l->data, NULL);
rpm-build 18b009
      if (country)
rpm-build 18b009
        {
rpm-build 18b009
          add_layout_to_table (layouts_by_country, country, layout);
rpm-build 18b009
          g_free (country);
rpm-build 18b009
        }
rpm-build 18b009
    }
rpm-build 18b009
}
rpm-build 18b009
rpm-build 18b009
static void
rpm-build 18b009
add_iso639 (Layout *layout,
rpm-build 18b009
            gchar  *id)
rpm-build 18b009
{
rpm-build 18b009
  layout->iso639Ids = g_slist_prepend (layout->iso639Ids, id);
rpm-build 18b009
}
rpm-build 18b009
rpm-build 18b009
static void
rpm-build 18b009
add_iso3166 (Layout *layout,
rpm-build 18b009
             gchar  *id)
rpm-build 18b009
{
rpm-build 18b009
  layout->iso3166Ids = g_slist_prepend (layout->iso3166Ids, id);
rpm-build 18b009
}
rpm-build 18b009
rpm-build 18b009
static void
rpm-build 18b009
parse_end_element (GMarkupParseContext  *context,
rpm-build 18b009
                   const gchar          *element_name,
rpm-build 18b009
                   gpointer              data,
rpm-build 18b009
                   GError              **error)
rpm-build 18b009
{
rpm-build 18b009
  GnomeXkbInfoPrivate *priv = GNOME_XKB_INFO (data)->priv;
rpm-build 18b009
rpm-build 18b009
  if (strcmp (element_name, "layout") == 0)
rpm-build 18b009
    {
rpm-build 18b009
      if (!priv->current_parser_layout->description || !priv->current_parser_layout->xkb_name)
rpm-build 18b009
        {
rpm-build 18b009
          g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT,
rpm-build 18b009
                       "'layout' elements must enclose 'description' and 'name' elements");
rpm-build 18b009
          return;
rpm-build 18b009
        }
rpm-build 18b009
rpm-build 18b009
      priv->current_parser_layout->id = g_strdup (priv->current_parser_layout->xkb_name);
rpm-build 18b009
rpm-build 18b009
      if (g_hash_table_contains (priv->layouts_table, priv->current_parser_layout->id))
rpm-build 18b009
        {
rpm-build 18b009
          g_clear_pointer (&priv->current_parser_layout, free_layout);
rpm-build 18b009
          return;
rpm-build 18b009
        }
rpm-build 18b009
rpm-build 18b009
      g_hash_table_replace (priv->layouts_table,
rpm-build 18b009
                            priv->current_parser_layout->id,
rpm-build 18b009
                            priv->current_parser_layout);
rpm-build 18b009
      add_layout_to_locale_tables (priv->current_parser_layout,
rpm-build 18b009
                                   priv->layouts_by_language,
rpm-build 18b009
                                   priv->layouts_by_country);
rpm-build 18b009
      priv->current_parser_layout = NULL;
rpm-build 18b009
    }
rpm-build 18b009
  else if (strcmp (element_name, "variant") == 0)
rpm-build 18b009
    {
rpm-build 18b009
      if (!priv->current_parser_variant->description || !priv->current_parser_variant->xkb_name)
rpm-build 18b009
        {
rpm-build 18b009
          g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT,
rpm-build 18b009
                       "'variant' elements must enclose 'description' and 'name' elements");
rpm-build 18b009
          return;
rpm-build 18b009
        }
rpm-build 18b009
rpm-build 18b009
      priv->current_parser_variant->id = g_strjoin ("+",
rpm-build 18b009
                                                    priv->current_parser_layout->xkb_name,
rpm-build 18b009
                                                    priv->current_parser_variant->xkb_name,
rpm-build 18b009
                                                    NULL);
rpm-build 18b009
rpm-build 18b009
      if (g_hash_table_contains (priv->layouts_table, priv->current_parser_variant->id))
rpm-build 18b009
        {
rpm-build 18b009
          g_clear_pointer (&priv->current_parser_variant, free_layout);
rpm-build 18b009
          return;
rpm-build 18b009
        }
rpm-build 18b009
rpm-build 18b009
      g_hash_table_replace (priv->layouts_table,
rpm-build 18b009
                            priv->current_parser_variant->id,
rpm-build 18b009
                            priv->current_parser_variant);
rpm-build 18b009
      add_layout_to_locale_tables (priv->current_parser_variant,
rpm-build 18b009
                                   priv->layouts_by_language,
rpm-build 18b009
                                   priv->layouts_by_country);
rpm-build 18b009
      priv->current_parser_variant = NULL;
rpm-build 18b009
    }
rpm-build 18b009
  else if (strcmp (element_name, "iso639Id") == 0)
rpm-build 18b009
    {
rpm-build 18b009
      if (!priv->current_parser_iso639Id)
rpm-build 18b009
        {
rpm-build 18b009
          g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT,
rpm-build 18b009
                       "'iso639Id' elements must enclose text");
rpm-build 18b009
          return;
rpm-build 18b009
        }
rpm-build 18b009
rpm-build 18b009
      if (priv->current_parser_variant)
rpm-build 18b009
        add_iso639 (priv->current_parser_variant, priv->current_parser_iso639Id);
rpm-build 18b009
      else if (priv->current_parser_layout)
rpm-build 18b009
        add_iso639 (priv->current_parser_layout, priv->current_parser_iso639Id);
rpm-build 18b009
rpm-build 18b009
      priv->current_parser_iso639Id = NULL;
rpm-build 18b009
    }
rpm-build 18b009
  else if (strcmp (element_name, "iso3166Id") == 0)
rpm-build 18b009
    {
rpm-build 18b009
      if (!priv->current_parser_iso3166Id)
rpm-build 18b009
        {
rpm-build 18b009
          g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT,
rpm-build 18b009
                       "'iso3166Id' elements must enclose text");
rpm-build 18b009
          return;
rpm-build 18b009
        }
rpm-build 18b009
rpm-build 18b009
      if (priv->current_parser_variant)
rpm-build 18b009
        add_iso3166 (priv->current_parser_variant, priv->current_parser_iso3166Id);
rpm-build 18b009
      else if (priv->current_parser_layout)
rpm-build 18b009
        add_iso3166 (priv->current_parser_layout, priv->current_parser_iso3166Id);
rpm-build 18b009
rpm-build 18b009
      priv->current_parser_iso3166Id = NULL;
rpm-build 18b009
    }
rpm-build 18b009
  else if (strcmp (element_name, "group") == 0)
rpm-build 18b009
    {
rpm-build 18b009
      if (!priv->current_parser_group->description || !priv->current_parser_group->id)
rpm-build 18b009
        {
rpm-build 18b009
          g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT,
rpm-build 18b009
                       "'group' elements must enclose 'description' and 'name' elements");
rpm-build 18b009
          return;
rpm-build 18b009
        }
rpm-build 18b009
rpm-build 18b009
      g_hash_table_replace (priv->option_groups_table,
rpm-build 18b009
                            priv->current_parser_group->id,
rpm-build 18b009
                            priv->current_parser_group);
rpm-build 18b009
      priv->current_parser_group = NULL;
rpm-build 18b009
    }
rpm-build 18b009
  else if (strcmp (element_name, "option") == 0)
rpm-build 18b009
    {
rpm-build 18b009
      if (!priv->current_parser_option->description || !priv->current_parser_option->id)
rpm-build 18b009
        {
rpm-build 18b009
          g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT,
rpm-build 18b009
                       "'option' elements must enclose 'description' and 'name' elements");
rpm-build 18b009
          return;
rpm-build 18b009
        }
rpm-build 18b009
rpm-build 18b009
      g_hash_table_replace (priv->current_parser_group->options_table,
rpm-build 18b009
                            priv->current_parser_option->id,
rpm-build 18b009
                            priv->current_parser_option);
rpm-build 18b009
      priv->current_parser_option = NULL;
rpm-build 18b009
    }
rpm-build 18b009
}
rpm-build 18b009
rpm-build 18b009
static void
rpm-build 18b009
parse_text (GMarkupParseContext  *context,
rpm-build 18b009
            const gchar          *text,
rpm-build 18b009
            gsize                 text_len,
rpm-build 18b009
            gpointer              data,
rpm-build 18b009
            GError              **error)
rpm-build 18b009
{
rpm-build 18b009
  GnomeXkbInfoPrivate *priv = GNOME_XKB_INFO (data)->priv;
rpm-build 18b009
rpm-build 18b009
  if (priv->current_parser_text)
rpm-build 18b009
    {
rpm-build 18b009
      *priv->current_parser_text = g_strndup (text, text_len);
rpm-build 18b009
      priv->current_parser_text = NULL;
rpm-build 18b009
    }
rpm-build 18b009
}
rpm-build 18b009
rpm-build 18b009
static void
rpm-build 18b009
parse_error (GMarkupParseContext *context,
rpm-build 18b009
             GError              *error,
rpm-build 18b009
             gpointer             data)
rpm-build 18b009
{
rpm-build 18b009
  GnomeXkbInfoPrivate *priv = GNOME_XKB_INFO (data)->priv;
rpm-build 18b009
rpm-build 18b009
  free_option_group (priv->current_parser_group);
rpm-build 18b009
  free_option (priv->current_parser_option);
rpm-build 18b009
  free_layout (priv->current_parser_layout);
rpm-build 18b009
  free_layout (priv->current_parser_variant);
rpm-build 18b009
  g_free (priv->current_parser_iso639Id);
rpm-build 18b009
  g_free (priv->current_parser_iso3166Id);
rpm-build 18b009
}
rpm-build 18b009
rpm-build 18b009
static const GMarkupParser markup_parser = {
rpm-build 18b009
  parse_start_element,
rpm-build 18b009
  parse_end_element,
rpm-build 18b009
  parse_text,
rpm-build 18b009
  NULL,
rpm-build 18b009
  parse_error
rpm-build 18b009
};
rpm-build 18b009
rpm-build 18b009
static void
rpm-build 18b009
parse_rules_file (GnomeXkbInfo  *self,
rpm-build 18b009
                  const gchar   *path,
rpm-build 18b009
                  GError       **error)
rpm-build 18b009
{
rpm-build 18b009
  gchar *buffer;
rpm-build 18b009
  gsize length;
rpm-build 18b009
  GMarkupParseContext *context;
rpm-build 18b009
  GError *sub_error = NULL;
rpm-build 18b009
rpm-build 18b009
  g_file_get_contents (path, &buffer, &length, &sub_error);
rpm-build 18b009
  if (sub_error)
rpm-build 18b009
    {
rpm-build 18b009
      g_propagate_error (error, sub_error);
rpm-build 18b009
      return;
rpm-build 18b009
    }
rpm-build 18b009
rpm-build 18b009
  context = g_markup_parse_context_new (&markup_parser, 0, self, NULL);
rpm-build 18b009
  g_markup_parse_context_parse (context, buffer, length, &sub_error);
rpm-build 18b009
  g_markup_parse_context_free (context);
rpm-build 18b009
  g_free (buffer);
rpm-build 18b009
  if (sub_error)
rpm-build 18b009
    g_propagate_error (error, sub_error);
rpm-build 18b009
}
rpm-build 18b009
rpm-build 18b009
static void
rpm-build 18b009
parse_rules (GnomeXkbInfo *self)
rpm-build 18b009
{
rpm-build 18b009
  GnomeXkbInfoPrivate *priv = self->priv;
rpm-build 18b009
  GSettings *settings;
rpm-build 18b009
  gboolean show_all_sources;
rpm-build 18b009
  gchar *file_path;
rpm-build 18b009
  GError *error = NULL;
rpm-build 18b009
rpm-build 18b009
  /* Make sure the translated strings we get from XKEYBOARD_CONFIG() are
rpm-build 18b009
   * in UTF-8 and not in the current locale */
rpm-build 18b009
  bind_textdomain_codeset ("xkeyboard-config", "UTF-8");
rpm-build 18b009
rpm-build 18b009
  /* Maps option group ids to XkbOptionGroup structs. Owns the
rpm-build 18b009
     XkbOptionGroup structs. */
rpm-build 18b009
  priv->option_groups_table = g_hash_table_new_full (g_str_hash, g_str_equal,
rpm-build 18b009
                                                     NULL, free_option_group);
rpm-build 18b009
  /* Maps country strings to a GHashTable which is a set of Layout
rpm-build 18b009
     struct pointers into the Layout structs stored in
rpm-build 18b009
     layouts_table. */
rpm-build 18b009
  priv->layouts_by_country = g_hash_table_new_full (g_str_hash, g_str_equal,
rpm-build 18b009
                                                    g_free, (GDestroyNotify) g_hash_table_destroy);
rpm-build 18b009
  /* Maps language strings to a GHashTable which is a set of Layout
rpm-build 18b009
     struct pointers into the Layout structs stored in
rpm-build 18b009
     layouts_table. */
rpm-build 18b009
  priv->layouts_by_language = g_hash_table_new_full (g_str_hash, g_str_equal,
rpm-build 18b009
                                                     g_free, (GDestroyNotify) g_hash_table_destroy);
rpm-build 18b009
  /* Maps layout ids to Layout structs. Owns the Layout structs. */
rpm-build 18b009
  priv->layouts_table = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, free_layout);
rpm-build 18b009
rpm-build 18b009
  file_path = get_xml_rules_file_path (".xml");
rpm-build 18b009
  parse_rules_file (self, file_path, &error);
rpm-build 18b009
  if (error)
rpm-build 18b009
    goto cleanup;
rpm-build 18b009
  g_free (file_path);
rpm-build 18b009
rpm-build 18b009
  settings = g_settings_new ("org.gnome.desktop.input-sources");
rpm-build 18b009
  show_all_sources = g_settings_get_boolean (settings, "show-all-sources");
rpm-build 18b009
  g_object_unref (settings);
rpm-build 18b009
rpm-build 18b009
  if (!show_all_sources)
rpm-build 18b009
    return;
rpm-build 18b009
rpm-build 18b009
  file_path = get_xml_rules_file_path (".extras.xml");
rpm-build 18b009
  parse_rules_file (self, file_path, &error);
rpm-build 18b009
  if (error)
rpm-build 18b009
    goto cleanup;
rpm-build 18b009
  g_free (file_path);
rpm-build 18b009
rpm-build 18b009
  return;
rpm-build 18b009
rpm-build 18b009
 cleanup:
rpm-build 18b009
  g_warning ("Failed to load XKB rules file %s: %s", file_path, error->message);
rpm-build 18b009
  g_clear_pointer (&error, g_error_free);
rpm-build 18b009
  g_clear_pointer (&file_path, g_free);
rpm-build 18b009
  g_clear_pointer (&priv->option_groups_table, g_hash_table_destroy);
rpm-build 18b009
  g_clear_pointer (&priv->layouts_by_country, g_hash_table_destroy);
rpm-build 18b009
  g_clear_pointer (&priv->layouts_by_language, g_hash_table_destroy);
rpm-build 18b009
  g_clear_pointer (&priv->layouts_table, g_hash_table_destroy);
rpm-build 18b009
}
rpm-build 18b009
rpm-build 18b009
static gboolean
rpm-build 18b009
ensure_rules_are_parsed (GnomeXkbInfo *self)
rpm-build 18b009
{
rpm-build 18b009
  GnomeXkbInfoPrivate *priv = self->priv;
rpm-build 18b009
rpm-build 18b009
  if (!priv->layouts_table)
rpm-build 18b009
    parse_rules (self);
rpm-build 18b009
rpm-build 18b009
  return !!priv->layouts_table;
rpm-build 18b009
}
rpm-build 18b009
rpm-build 18b009
static void
rpm-build 18b009
gnome_xkb_info_init (GnomeXkbInfo *self)
rpm-build 18b009
{
rpm-build 18b009
  self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GNOME_TYPE_XKB_INFO, GnomeXkbInfoPrivate);
rpm-build 18b009
}
rpm-build 18b009
rpm-build 18b009
static void
rpm-build 18b009
gnome_xkb_info_finalize (GObject *self)
rpm-build 18b009
{
rpm-build 18b009
  GnomeXkbInfoPrivate *priv = GNOME_XKB_INFO (self)->priv;
rpm-build 18b009
rpm-build 18b009
  if (priv->option_groups_table)
rpm-build 18b009
    g_hash_table_destroy (priv->option_groups_table);
rpm-build 18b009
  if (priv->layouts_by_country)
rpm-build 18b009
    g_hash_table_destroy (priv->layouts_by_country);
rpm-build 18b009
  if (priv->layouts_by_language)
rpm-build 18b009
    g_hash_table_destroy (priv->layouts_by_language);
rpm-build 18b009
  if (priv->layouts_table)
rpm-build 18b009
    g_hash_table_destroy (priv->layouts_table);
rpm-build 18b009
rpm-build 18b009
  G_OBJECT_CLASS (gnome_xkb_info_parent_class)->finalize (self);
rpm-build 18b009
}
rpm-build 18b009
rpm-build 18b009
static void
rpm-build 18b009
gnome_xkb_info_class_init (GnomeXkbInfoClass *klass)
rpm-build 18b009
{
rpm-build 18b009
  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
rpm-build 18b009
rpm-build 18b009
  gobject_class->finalize = gnome_xkb_info_finalize;
rpm-build 18b009
rpm-build 18b009
  g_type_class_add_private (gobject_class, sizeof (GnomeXkbInfoPrivate));
rpm-build 18b009
}
rpm-build 18b009
rpm-build 18b009
/**
rpm-build 18b009
 * gnome_xkb_info_new:
rpm-build 18b009
 *
rpm-build 18b009
 * Returns: (transfer full): a new #GnomeXkbInfo instance.
rpm-build 18b009
 */
rpm-build 18b009
GnomeXkbInfo *
rpm-build 18b009
gnome_xkb_info_new (void)
rpm-build 18b009
{
rpm-build 18b009
  return g_object_new (GNOME_TYPE_XKB_INFO, NULL);
rpm-build 18b009
}
rpm-build 18b009
rpm-build 18b009
/**
rpm-build 18b009
 * gnome_xkb_info_get_all_layouts:
rpm-build 18b009
 * @self: a #GnomeXkbInfo
rpm-build 18b009
 *
rpm-build 18b009
 * Returns a list of all layout identifiers we know about.
rpm-build 18b009
 *
rpm-build 18b009
 * Return value: (transfer container) (element-type utf8): the list
rpm-build 18b009
 * of layout names. The caller takes ownership of the #GList but not
rpm-build 18b009
 * of the strings themselves, those are internally allocated and must
rpm-build 18b009
 * not be modified.
rpm-build 18b009
 *
rpm-build 18b009
 * Since: 3.6
rpm-build 18b009
 */
rpm-build 18b009
GList *
rpm-build 18b009
gnome_xkb_info_get_all_layouts (GnomeXkbInfo *self)
rpm-build 18b009
{
rpm-build 18b009
  GnomeXkbInfoPrivate *priv;
rpm-build 18b009
rpm-build 18b009
  g_return_val_if_fail (GNOME_IS_XKB_INFO (self), NULL);
rpm-build 18b009
rpm-build 18b009
  priv = self->priv;
rpm-build 18b009
rpm-build 18b009
  if (!ensure_rules_are_parsed (self))
rpm-build 18b009
    return NULL;
rpm-build 18b009
rpm-build 18b009
  return g_hash_table_get_keys (priv->layouts_table);
rpm-build 18b009
}
rpm-build 18b009
rpm-build 18b009
/**
rpm-build 18b009
 * gnome_xkb_info_get_all_option_groups:
rpm-build 18b009
 * @self: a #GnomeXkbInfo
rpm-build 18b009
 *
rpm-build 18b009
 * Returns a list of all option group identifiers we know about.
rpm-build 18b009
 *
rpm-build 18b009
 * Return value: (transfer container) (element-type utf8): the list
rpm-build 18b009
 * of option group ids. The caller takes ownership of the #GList but
rpm-build 18b009
 * not of the strings themselves, those are internally allocated and
rpm-build 18b009
 * must not be modified.
rpm-build 18b009
 *
rpm-build 18b009
 * Since: 3.6
rpm-build 18b009
 */
rpm-build 18b009
GList *
rpm-build 18b009
gnome_xkb_info_get_all_option_groups (GnomeXkbInfo *self)
rpm-build 18b009
{
rpm-build 18b009
  GnomeXkbInfoPrivate *priv;
rpm-build 18b009
rpm-build 18b009
  g_return_val_if_fail (GNOME_IS_XKB_INFO (self), NULL);
rpm-build 18b009
rpm-build 18b009
  priv = self->priv;
rpm-build 18b009
rpm-build 18b009
  if (!ensure_rules_are_parsed (self))
rpm-build 18b009
    return NULL;
rpm-build 18b009
rpm-build 18b009
  return g_hash_table_get_keys (priv->option_groups_table);
rpm-build 18b009
}
rpm-build 18b009
rpm-build 18b009
/**
rpm-build 18b009
 * gnome_xkb_info_description_for_group:
rpm-build 18b009
 * @self: a #GnomeXkbInfo
rpm-build 18b009
 * @group_id: identifier for group
rpm-build 18b009
 *
rpm-build 18b009
 * Return value: the translated description for the group @group_id.
rpm-build 18b009
 *
rpm-build 18b009
 * Since: 3.8
rpm-build 18b009
 */
rpm-build 18b009
const gchar *
rpm-build 18b009
gnome_xkb_info_description_for_group (GnomeXkbInfo *self,
rpm-build 18b009
                                      const gchar  *group_id)
rpm-build 18b009
{
rpm-build 18b009
  GnomeXkbInfoPrivate *priv;
rpm-build 18b009
  const XkbOptionGroup *group;
rpm-build 18b009
rpm-build 18b009
  g_return_val_if_fail (GNOME_IS_XKB_INFO (self), NULL);
rpm-build 18b009
rpm-build 18b009
  priv = self->priv;
rpm-build 18b009
rpm-build 18b009
  if (!ensure_rules_are_parsed (self))
rpm-build 18b009
    return NULL;
rpm-build 18b009
rpm-build 18b009
  group = g_hash_table_lookup (priv->option_groups_table, group_id);
rpm-build 18b009
  if (!group)
rpm-build 18b009
    return NULL;
rpm-build 18b009
rpm-build 18b009
  return XKEYBOARD_CONFIG_(group->description);
rpm-build 18b009
}
rpm-build 18b009
rpm-build 18b009
/**
rpm-build 18b009
 * gnome_xkb_info_get_options_for_group:
rpm-build 18b009
 * @self: a #GnomeXkbInfo
rpm-build 18b009
 * @group_id: group's identifier about which to retrieve the options
rpm-build 18b009
 *
rpm-build 18b009
 * Returns a list of all option identifiers we know about for group
rpm-build 18b009
 * @group_id.
rpm-build 18b009
 *
rpm-build 18b009
 * Return value: (transfer container) (element-type utf8): the list
rpm-build 18b009
 * of option ids. The caller takes ownership of the #GList but not of
rpm-build 18b009
 * the strings themselves, those are internally allocated and must not
rpm-build 18b009
 * be modified.
rpm-build 18b009
 *
rpm-build 18b009
 * Since: 3.6
rpm-build 18b009
 */
rpm-build 18b009
GList *
rpm-build 18b009
gnome_xkb_info_get_options_for_group (GnomeXkbInfo *self,
rpm-build 18b009
                                      const gchar  *group_id)
rpm-build 18b009
{
rpm-build 18b009
  GnomeXkbInfoPrivate *priv;
rpm-build 18b009
  const XkbOptionGroup *group;
rpm-build 18b009
rpm-build 18b009
  g_return_val_if_fail (GNOME_IS_XKB_INFO (self), NULL);
rpm-build 18b009
rpm-build 18b009
  priv = self->priv;
rpm-build 18b009
rpm-build 18b009
  if (!ensure_rules_are_parsed (self))
rpm-build 18b009
    return NULL;
rpm-build 18b009
rpm-build 18b009
  group = g_hash_table_lookup (priv->option_groups_table, group_id);
rpm-build 18b009
  if (!group)
rpm-build 18b009
    return NULL;
rpm-build 18b009
rpm-build 18b009
  return g_hash_table_get_keys (group->options_table);
rpm-build 18b009
}
rpm-build 18b009
rpm-build 18b009
/**
rpm-build 18b009
 * gnome_xkb_info_description_for_option:
rpm-build 18b009
 * @self: a #GnomeXkbInfo
rpm-build 18b009
 * @group_id: identifier for group containing the option
rpm-build 18b009
 * @id: option identifier
rpm-build 18b009
 *
rpm-build 18b009
 * Return value: the translated description for the option @id.
rpm-build 18b009
 *
rpm-build 18b009
 * Since: 3.6
rpm-build 18b009
 */
rpm-build 18b009
const gchar *
rpm-build 18b009
gnome_xkb_info_description_for_option (GnomeXkbInfo *self,
rpm-build 18b009
                                       const gchar  *group_id,
rpm-build 18b009
                                       const gchar  *id)
rpm-build 18b009
{
rpm-build 18b009
  GnomeXkbInfoPrivate *priv;
rpm-build 18b009
  const XkbOptionGroup *group;
rpm-build 18b009
  const XkbOption *option;
rpm-build 18b009
rpm-build 18b009
  g_return_val_if_fail (GNOME_IS_XKB_INFO (self), NULL);
rpm-build 18b009
rpm-build 18b009
  priv = self->priv;
rpm-build 18b009
rpm-build 18b009
  if (!ensure_rules_are_parsed (self))
rpm-build 18b009
    return NULL;
rpm-build 18b009
rpm-build 18b009
  group = g_hash_table_lookup (priv->option_groups_table, group_id);
rpm-build 18b009
  if (!group)
rpm-build 18b009
    return NULL;
rpm-build 18b009
rpm-build 18b009
  option = g_hash_table_lookup (group->options_table, id);
rpm-build 18b009
  if (!option)
rpm-build 18b009
    return NULL;
rpm-build 18b009
rpm-build 18b009
  return XKEYBOARD_CONFIG_(option->description);
rpm-build 18b009
}
rpm-build 18b009
rpm-build 18b009
/**
rpm-build 18b009
 * gnome_xkb_info_get_layout_info:
rpm-build 18b009
 * @self: a #GnomeXkbInfo
rpm-build 18b009
 * @id: layout's identifier about which to retrieve the info
rpm-build 18b009
 * @display_name: (out) (allow-none) (transfer none): location to store
rpm-build 18b009
 * the layout's display name, or %NULL
rpm-build 18b009
 * @short_name: (out) (allow-none) (transfer none): location to store
rpm-build 18b009
 * the layout's short name, or %NULL
rpm-build 18b009
 * @xkb_layout: (out) (allow-none) (transfer none): location to store
rpm-build 18b009
 * the layout's XKB name, or %NULL
rpm-build 18b009
 * @xkb_variant: (out) (allow-none) (transfer none): location to store
rpm-build 18b009
 * the layout's XKB variant, or %NULL
rpm-build 18b009
 *
rpm-build 18b009
 * Retrieves information about a layout. Both @display_name and
rpm-build 18b009
 * @short_name are suitable to show in UIs and might be localized if
rpm-build 18b009
 * translations are available.
rpm-build 18b009
 *
rpm-build 18b009
 * Some layouts don't provide a short name (2 or 3 letters) or don't
rpm-build 18b009
 * specify a XKB variant, in those cases @short_name or @xkb_variant
rpm-build 18b009
 * are empty strings, i.e. "".
rpm-build 18b009
 *
rpm-build 18b009
 * If the given layout doesn't exist the return value is %FALSE and
rpm-build 18b009
 * all the (out) parameters are set to %NULL.
rpm-build 18b009
 *
rpm-build 18b009
 * Return value: %TRUE if the layout exists or %FALSE otherwise.
rpm-build 18b009
 *
rpm-build 18b009
 * Since: 3.6
rpm-build 18b009
 */
rpm-build 18b009
gboolean
rpm-build 18b009
gnome_xkb_info_get_layout_info (GnomeXkbInfo *self,
rpm-build 18b009
                                const gchar  *id,
rpm-build 18b009
                                const gchar **display_name,
rpm-build 18b009
                                const gchar **short_name,
rpm-build 18b009
                                const gchar **xkb_layout,
rpm-build 18b009
                                const gchar **xkb_variant)
rpm-build 18b009
{
rpm-build 18b009
  GnomeXkbInfoPrivate *priv;
rpm-build 18b009
  const Layout *layout;
rpm-build 18b009
rpm-build 18b009
  if (display_name)
rpm-build 18b009
    *display_name = NULL;
rpm-build 18b009
  if (short_name)
rpm-build 18b009
    *short_name = NULL;
rpm-build 18b009
  if (xkb_layout)
rpm-build 18b009
    *xkb_layout = NULL;
rpm-build 18b009
  if (xkb_variant)
rpm-build 18b009
    *xkb_variant = NULL;
rpm-build 18b009
rpm-build 18b009
  g_return_val_if_fail (GNOME_IS_XKB_INFO (self), FALSE);
rpm-build 18b009
rpm-build 18b009
  priv = self->priv;
rpm-build 18b009
rpm-build 18b009
  if (!ensure_rules_are_parsed (self))
rpm-build 18b009
    return FALSE;
rpm-build 18b009
rpm-build 18b009
  if (!g_hash_table_lookup_extended (priv->layouts_table, id, NULL, (gpointer *)&layout))
rpm-build 18b009
    return FALSE;
rpm-build 18b009
rpm-build 18b009
  if (display_name)
rpm-build 18b009
    *display_name = XKEYBOARD_CONFIG_(layout->description);
rpm-build 18b009
rpm-build 18b009
  if (!layout->is_variant)
rpm-build 18b009
    {
rpm-build 18b009
      if (short_name)
rpm-build 18b009
        *short_name = XKEYBOARD_CONFIG_(layout->short_desc ? layout->short_desc : "");
rpm-build 18b009
      if (xkb_layout)
rpm-build 18b009
        *xkb_layout = layout->xkb_name;
rpm-build 18b009
      if (xkb_variant)
rpm-build 18b009
        *xkb_variant = "";
rpm-build 18b009
    }
rpm-build 18b009
  else
rpm-build 18b009
    {
rpm-build 18b009
      if (short_name)
rpm-build 18b009
        *short_name = XKEYBOARD_CONFIG_(layout->short_desc ? layout->short_desc :
rpm-build 18b009
                        layout->main_layout->short_desc ? layout->main_layout->short_desc : "");
rpm-build 18b009
      if (xkb_layout)
rpm-build 18b009
        *xkb_layout = layout->main_layout->xkb_name;
rpm-build 18b009
      if (xkb_variant)
rpm-build 18b009
        *xkb_variant = layout->xkb_name;
rpm-build 18b009
    }
rpm-build 18b009
rpm-build 18b009
  return TRUE;
rpm-build 18b009
}
rpm-build 18b009
rpm-build 18b009
static void
rpm-build 18b009
collect_layout_ids (gpointer key,
rpm-build 18b009
                    gpointer value,
rpm-build 18b009
                    gpointer data)
rpm-build 18b009
{
rpm-build 18b009
  Layout *layout = value;
rpm-build 18b009
  GList **list = data;
rpm-build 18b009
rpm-build 18b009
  *list = g_list_prepend (*list, layout->id);
rpm-build 18b009
}
rpm-build 18b009
rpm-build 18b009
/**
rpm-build 18b009
 * gnome_xkb_info_get_layouts_for_language:
rpm-build 18b009
 * @self: a #GnomeXkbInfo
rpm-build 18b009
 * @language_code: an ISO 639 code string
rpm-build 18b009
 *
rpm-build 18b009
 * Returns a list of all layout identifiers we know about for
rpm-build 18b009
 * @language_code.
rpm-build 18b009
 *
rpm-build 18b009
 * Return value: (transfer container) (element-type utf8): the list
rpm-build 18b009
 * of layout ids. The caller takes ownership of the #GList but not of
rpm-build 18b009
 * the strings themselves, those are internally allocated and must not
rpm-build 18b009
 * be modified.
rpm-build 18b009
 *
rpm-build 18b009
 * Since: 3.8
rpm-build 18b009
 */
rpm-build 18b009
GList *
rpm-build 18b009
gnome_xkb_info_get_layouts_for_language (GnomeXkbInfo *self,
rpm-build 18b009
                                         const gchar  *language_code)
rpm-build 18b009
{
rpm-build 18b009
  GnomeXkbInfoPrivate *priv;
rpm-build 18b009
  GHashTable *layouts_for_language;
rpm-build 18b009
  gchar *language;
rpm-build 18b009
  GList *list;
rpm-build 18b009
rpm-build 18b009
  g_return_val_if_fail (GNOME_IS_XKB_INFO (self), NULL);
rpm-build 18b009
rpm-build 18b009
  priv = self->priv;
rpm-build 18b009
rpm-build 18b009
  if (!ensure_rules_are_parsed (self))
rpm-build 18b009
    return NULL;
rpm-build 18b009
rpm-build 18b009
  language = gnome_get_language_from_code (language_code, NULL);
rpm-build 18b009
  if (!language)
rpm-build 18b009
    return NULL;
rpm-build 18b009
rpm-build 18b009
  layouts_for_language = g_hash_table_lookup (priv->layouts_by_language, language);
rpm-build 18b009
  g_free (language);
rpm-build 18b009
rpm-build 18b009
  if (!layouts_for_language)
rpm-build 18b009
    return NULL;
rpm-build 18b009
rpm-build 18b009
  list = NULL;
rpm-build 18b009
  g_hash_table_foreach (layouts_for_language, collect_layout_ids, &list);
rpm-build 18b009
rpm-build 18b009
  return list;
rpm-build 18b009
}
rpm-build 18b009
rpm-build 18b009
/**
rpm-build 18b009
 * gnome_xkb_info_get_layouts_for_country:
rpm-build 18b009
 * @self: a #GnomeXkbInfo
rpm-build 18b009
 * @country_code: an ISO 3166 code string
rpm-build 18b009
 *
rpm-build 18b009
 * Returns a list of all layout identifiers we know about for
rpm-build 18b009
 * @country_code.
rpm-build 18b009
 *
rpm-build 18b009
 * Return value: (transfer container) (element-type utf8): the list
rpm-build 18b009
 * of layout ids. The caller takes ownership of the #GList but not of
rpm-build 18b009
 * the strings themselves, those are internally allocated and must not
rpm-build 18b009
 * be modified.
rpm-build 18b009
 *
rpm-build 18b009
 * Since: 3.8
rpm-build 18b009
 */
rpm-build 18b009
GList *
rpm-build 18b009
gnome_xkb_info_get_layouts_for_country (GnomeXkbInfo *self,
rpm-build 18b009
                                        const gchar  *country_code)
rpm-build 18b009
{
rpm-build 18b009
  GnomeXkbInfoPrivate *priv;
rpm-build 18b009
  GHashTable *layouts_for_country;
rpm-build 18b009
  gchar *country;
rpm-build 18b009
  GList *list;
rpm-build 18b009
rpm-build 18b009
  g_return_val_if_fail (GNOME_IS_XKB_INFO (self), NULL);
rpm-build 18b009
rpm-build 18b009
  priv = self->priv;
rpm-build 18b009
rpm-build 18b009
  if (!ensure_rules_are_parsed (self))
rpm-build 18b009
    return NULL;
rpm-build 18b009
rpm-build 18b009
  country = gnome_get_country_from_code (country_code, NULL);
rpm-build 18b009
  if (!country)
rpm-build 18b009
    return NULL;
rpm-build 18b009
rpm-build 18b009
  layouts_for_country = g_hash_table_lookup (priv->layouts_by_country, country);
rpm-build 18b009
  g_free (country);
rpm-build 18b009
rpm-build 18b009
  if (!layouts_for_country)
rpm-build 18b009
    return NULL;
rpm-build 18b009
rpm-build 18b009
  list = NULL;
rpm-build 18b009
  g_hash_table_foreach (layouts_for_country, collect_layout_ids, &list);
rpm-build 18b009
rpm-build 18b009
  return list;
rpm-build 18b009
}
rpm-build 18b009
rpm-build 18b009
static void
rpm-build 18b009
collect_languages (gpointer value,
rpm-build 18b009
                   gpointer data)
rpm-build 18b009
{
rpm-build 18b009
  gchar *language = value;
rpm-build 18b009
  GList **list = data;
rpm-build 18b009
rpm-build 18b009
  *list = g_list_append (*list, language);
rpm-build 18b009
}
rpm-build 18b009
rpm-build 18b009
/**
rpm-build 18b009
 * gnome_xkb_info_get_languages_for_layout:
rpm-build 18b009
 * @self: a #GnomeXkbInfo
rpm-build 18b009
 * @layout_id: a layout identifier
rpm-build 18b009
 *
rpm-build 18b009
 * Returns a list of all languages supported by a layout, given by
rpm-build 18b009
 * @layout_id.
rpm-build 18b009
 *
rpm-build 18b009
 * Return value: (transfer container) (element-type utf8): the list of
rpm-build 18b009
 * ISO 639 code strings. The caller takes ownership of the #GList but
rpm-build 18b009
 * not of the strings themselves, those are internally allocated and
rpm-build 18b009
 * must not be modified.
rpm-build 18b009
 *
rpm-build 18b009
 * Since: 3.18
rpm-build 18b009
 */
rpm-build 18b009
GList *
rpm-build 18b009
gnome_xkb_info_get_languages_for_layout (GnomeXkbInfo *self,
rpm-build 18b009
                                         const gchar  *layout_id)
rpm-build 18b009
{
rpm-build 18b009
  GnomeXkbInfoPrivate *priv;
rpm-build 18b009
  Layout *layout;
rpm-build 18b009
  GList *list;
rpm-build 18b009
rpm-build 18b009
  g_return_val_if_fail (GNOME_IS_XKB_INFO (self), NULL);
rpm-build 18b009
rpm-build 18b009
  priv = self->priv;
rpm-build 18b009
rpm-build 18b009
  if (!ensure_rules_are_parsed (self))
rpm-build 18b009
    return NULL;
rpm-build 18b009
rpm-build 18b009
  layout = g_hash_table_lookup (priv->layouts_table, layout_id);
rpm-build 18b009
rpm-build 18b009
  if (!layout)
rpm-build 18b009
    return NULL;
rpm-build 18b009
rpm-build 18b009
  list = NULL;
rpm-build 18b009
  g_slist_foreach (layout->iso639Ids, collect_languages, &list);
rpm-build 18b009
rpm-build 18b009
  return list;
rpm-build 18b009
}