Add more features to the list, allow selecting script/language from the set that is supported by the font, indicate which features are present in the font for the selected script/language, and expand the default specimen to cover latin, cyrillic and greek.
		
			
				
	
	
		
			527 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			527 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/* Pango/Font Features
 | 
						|
 *
 | 
						|
 * This example demonstrates support for OpenType font features with
 | 
						|
 * Pango attributes. The attributes can be used manually or via Pango
 | 
						|
 * markup.
 | 
						|
 *
 | 
						|
 * It can also be used to explore available features in OpenType fonts
 | 
						|
 * and their effect.
 | 
						|
 */
 | 
						|
 | 
						|
#include <gtk/gtk.h>
 | 
						|
#include <pango/pangofc-font.h>
 | 
						|
#include <hb.h>
 | 
						|
#include <hb-ot.h>
 | 
						|
#include <hb-ft.h>
 | 
						|
 | 
						|
static GtkWidget *label;
 | 
						|
static GtkWidget *settings;
 | 
						|
static GtkWidget *font;
 | 
						|
static GtkWidget *script_lang;
 | 
						|
static GtkWidget *resetbutton;
 | 
						|
static GtkWidget *numcasedefault;
 | 
						|
static GtkWidget *numspacedefault;
 | 
						|
static GtkWidget *fractiondefault;
 | 
						|
static GtkWidget *stack;
 | 
						|
static GtkWidget *entry;
 | 
						|
 | 
						|
#define num_features 40
 | 
						|
 | 
						|
static GtkWidget *toggle[num_features];
 | 
						|
static GtkWidget *icon[num_features];
 | 
						|
static const char *feature_names[num_features] = {
 | 
						|
  "kern", "liga", "dlig", "hlig", "clig", "smcp", "c2sc", "pcap", "c2pc", "unic",
 | 
						|
  "cpsp", "case", "lnum", "onum", "pnum", "tnum", "frac", "afrc", "zero", "nalt",
 | 
						|
  "sinf", "swsh", "cswh", "locl", "calt", "hist", "salt", "titl", "rand", "subs",
 | 
						|
  "sups", "init", "medi", "fina", "isol", "ss01", "ss02", "ss03", "ss04", "ss05"
 | 
						|
};
 | 
						|
 | 
						|
static void
 | 
						|
update_display (void)
 | 
						|
{
 | 
						|
  GString *s;
 | 
						|
  char *font_desc;
 | 
						|
  char *font_settings;
 | 
						|
  const char *text;
 | 
						|
  gboolean has_feature;
 | 
						|
  int i;
 | 
						|
  hb_tag_t lang_tag;
 | 
						|
  GtkTreeModel *model;
 | 
						|
  GtkTreeIter iter;
 | 
						|
  const char *lang;
 | 
						|
 | 
						|
  text = gtk_entry_get_text (GTK_ENTRY (entry));
 | 
						|
 | 
						|
  font_desc = gtk_font_chooser_get_font (GTK_FONT_CHOOSER (font));
 | 
						|
 | 
						|
  s = g_string_new ("");
 | 
						|
 | 
						|
  has_feature = FALSE;
 | 
						|
  for (i = 0; i < num_features; i++)
 | 
						|
    {
 | 
						|
      if (!gtk_widget_is_sensitive (toggle[i]))
 | 
						|
        continue;
 | 
						|
 | 
						|
      if (GTK_IS_RADIO_BUTTON (toggle[i]))
 | 
						|
        {
 | 
						|
          if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (toggle[i])))
 | 
						|
            {
 | 
						|
              if (has_feature)
 | 
						|
                g_string_append (s, ", ");
 | 
						|
              g_string_append (s, gtk_buildable_get_name (GTK_BUILDABLE (toggle[i])));
 | 
						|
              g_string_append (s, " 1");
 | 
						|
              has_feature = TRUE;
 | 
						|
            }
 | 
						|
        }
 | 
						|
      else
 | 
						|
        {
 | 
						|
          if (has_feature)
 | 
						|
            g_string_append (s, ", ");
 | 
						|
          g_string_append (s, gtk_buildable_get_name (GTK_BUILDABLE (toggle[i])));
 | 
						|
          if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (toggle[i])))
 | 
						|
            g_string_append (s, " 1");
 | 
						|
          else
 | 
						|
            g_string_append (s, " 0");
 | 
						|
          has_feature = TRUE;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
  font_settings = g_string_free (s, FALSE);
 | 
						|
 | 
						|
  gtk_label_set_text (GTK_LABEL (settings), font_settings);
 | 
						|
 | 
						|
 | 
						|
  if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (script_lang), &iter))
 | 
						|
    {
 | 
						|
      model = gtk_combo_box_get_model (GTK_COMBO_BOX (script_lang));
 | 
						|
      gtk_tree_model_get (model, &iter,
 | 
						|
                          3, &lang_tag,
 | 
						|
                          -1);
 | 
						|
 | 
						|
      lang = hb_language_to_string (hb_ot_tag_to_language (lang_tag));
 | 
						|
    }
 | 
						|
  else
 | 
						|
    lang = NULL;
 | 
						|
 | 
						|
  s = g_string_new ("");
 | 
						|
  g_string_append_printf (s, "<span font_desc='%s' font_features='%s'", font_desc, font_settings);
 | 
						|
  if (lang)
 | 
						|
    g_string_append_printf (s, " lang='%s'", lang);
 | 
						|
  g_string_append_printf (s, ">%s</span>", text);
 | 
						|
 | 
						|
  gtk_label_set_markup (GTK_LABEL (label), s->str);
 | 
						|
 | 
						|
  g_string_free (s, TRUE);
 | 
						|
 | 
						|
  g_free (font_desc);
 | 
						|
  g_free (font_settings);
 | 
						|
}
 | 
						|
 | 
						|
static PangoFont *
 | 
						|
get_pango_font (void)
 | 
						|
{
 | 
						|
  PangoFontDescription *desc;
 | 
						|
  PangoContext *context;
 | 
						|
  PangoFontMap *map;
 | 
						|
 | 
						|
  desc = gtk_font_chooser_get_font_desc (GTK_FONT_CHOOSER (font));
 | 
						|
  context = gtk_widget_get_pango_context (font);
 | 
						|
  map = pango_context_get_font_map (context);
 | 
						|
 | 
						|
  return pango_font_map_load_font (map, context, desc);
 | 
						|
}
 | 
						|
 | 
						|
static struct { const char *name; hb_script_t script; } script_names[] = {
 | 
						|
  { "Common", HB_SCRIPT_COMMON },
 | 
						|
  { "Inherited", HB_SCRIPT_INHERITED },
 | 
						|
  { "Unknown", HB_SCRIPT_UNKNOWN },
 | 
						|
  { "Arabic", HB_SCRIPT_ARABIC },
 | 
						|
  { "Armenian", HB_SCRIPT_ARMENIAN },
 | 
						|
  { "Bengali", HB_SCRIPT_BENGALI },
 | 
						|
  { "Cyrillic", HB_SCRIPT_CYRILLIC },
 | 
						|
  { "Devanagari", HB_SCRIPT_DEVANAGARI },
 | 
						|
  { "Georgian", HB_SCRIPT_GEORGIAN },
 | 
						|
  { "Greek", HB_SCRIPT_GREEK },
 | 
						|
  { "Gujarati", HB_SCRIPT_GUJARATI },
 | 
						|
  { "Gurmukhi", HB_SCRIPT_GURMUKHI },
 | 
						|
  { "Hangul", HB_SCRIPT_HANGUL },
 | 
						|
  { "Han", HB_SCRIPT_HAN },
 | 
						|
  { "Hebrew", HB_SCRIPT_HEBREW },
 | 
						|
  { "Hiragana", HB_SCRIPT_HIRAGANA },
 | 
						|
  { "Kannada", HB_SCRIPT_KANNADA },
 | 
						|
  { "Katakana", HB_SCRIPT_KATAKANA },
 | 
						|
  { "Lao", HB_SCRIPT_LAO },
 | 
						|
  { "Latin", HB_SCRIPT_LATIN },
 | 
						|
  { "Malayalam", HB_SCRIPT_MALAYALAM },
 | 
						|
  { "Oriya", HB_SCRIPT_ORIYA },
 | 
						|
  { "Tamil", HB_SCRIPT_TAMIL },
 | 
						|
  { "Telugu", HB_SCRIPT_TELUGU },
 | 
						|
  { "Thai", HB_SCRIPT_THAI },
 | 
						|
  { "Tibetan", HB_SCRIPT_TIBETAN },
 | 
						|
  { "Bopomofo", HB_SCRIPT_BOPOMOFO }
 | 
						|
  /* FIXME: complete */
 | 
						|
};
 | 
						|
 | 
						|
static struct { const char *name; hb_tag_t tag; } language_names[] = {
 | 
						|
  { "Arabic", HB_TAG ('A','R','A',' ') },
 | 
						|
  { "Romanian", HB_TAG ('R','O','M',' ') },
 | 
						|
  { "Skolt Sami", HB_TAG ('S','K','S',' ') },
 | 
						|
  { "Northern Sami", HB_TAG ('N','S','M',' ') },
 | 
						|
  { "Kildin Sami", HB_TAG ('K','S','M',' ') },
 | 
						|
  { "Moldavian", HB_TAG ('M','O','L',' ') },
 | 
						|
  { "Turkish", HB_TAG ('T','R','K',' ') },
 | 
						|
  { "Azerbaijani", HB_TAG ('A','Z','E',' ') },
 | 
						|
  { "Crimean Tatar", HB_TAG ('C','R','T',' ') },
 | 
						|
  { "Serbian", HB_TAG ('S','R','B',' ') },
 | 
						|
  { "German", HB_TAG ('D','E','U',' ') }
 | 
						|
  /* FIXME: complete */
 | 
						|
};
 | 
						|
 | 
						|
typedef struct {
 | 
						|
  hb_tag_t script_tag;
 | 
						|
  hb_tag_t lang_tag;
 | 
						|
  unsigned int script_index;
 | 
						|
  unsigned int lang_index;
 | 
						|
} TagPair;
 | 
						|
 | 
						|
static guint
 | 
						|
tag_pair_hash (gconstpointer data)
 | 
						|
{
 | 
						|
  const TagPair *pair = data;
 | 
						|
 | 
						|
  return pair->script_tag + pair->lang_tag;
 | 
						|
}
 | 
						|
 | 
						|
static gboolean
 | 
						|
tag_pair_equal (gconstpointer a, gconstpointer b)
 | 
						|
{
 | 
						|
  const TagPair *pair_a = a;
 | 
						|
  const TagPair *pair_b = b;
 | 
						|
 | 
						|
  return pair_a->script_tag == pair_b->script_tag && pair_a->lang_tag == pair_b->lang_tag;
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
update_script_combo (void)
 | 
						|
{
 | 
						|
  GtkListStore *store;
 | 
						|
  hb_font_t *hb_font;
 | 
						|
  gint i, j, k, l;
 | 
						|
  FT_Face ft_face;
 | 
						|
  PangoFont *pango_font;
 | 
						|
  GHashTable *tags;
 | 
						|
  GHashTableIter iter;
 | 
						|
  TagPair *pair;
 | 
						|
 | 
						|
  store = gtk_list_store_new (4, G_TYPE_STRING, G_TYPE_UINT, G_TYPE_UINT, G_TYPE_UINT);
 | 
						|
 | 
						|
  pango_font = get_pango_font ();
 | 
						|
  ft_face = pango_fc_font_lock_face (PANGO_FC_FONT (pango_font)),
 | 
						|
  hb_font = hb_ft_font_create (ft_face, NULL);
 | 
						|
 | 
						|
  tags = g_hash_table_new_full (tag_pair_hash, tag_pair_equal, g_free, NULL);
 | 
						|
 | 
						|
  pair = g_new (TagPair, 1);
 | 
						|
  pair->script_tag = HB_OT_TAG_DEFAULT_SCRIPT;
 | 
						|
  pair->lang_tag = HB_OT_TAG_DEFAULT_LANGUAGE;
 | 
						|
  g_hash_table_insert (tags, pair, g_strdup ("Default"));
 | 
						|
 | 
						|
  if (hb_font)
 | 
						|
    {
 | 
						|
      hb_tag_t tables[2] = { HB_OT_TAG_GSUB, HB_OT_TAG_GPOS };
 | 
						|
      hb_face_t *hb_face;
 | 
						|
 | 
						|
      hb_face = hb_font_get_face (hb_font);
 | 
						|
 | 
						|
      for (i= 0; i < 2; i++)
 | 
						|
        {
 | 
						|
          hb_tag_t scripts[80];
 | 
						|
          unsigned int script_count = G_N_ELEMENTS (scripts);
 | 
						|
 | 
						|
          hb_ot_layout_table_get_script_tags (hb_face, tables[i], 0, &script_count, scripts);
 | 
						|
          for (j = 0; j < script_count; j++)
 | 
						|
            {
 | 
						|
              hb_tag_t languages[80];
 | 
						|
              unsigned int language_count = G_N_ELEMENTS (languages);
 | 
						|
 | 
						|
              pair = g_new (TagPair, 1);
 | 
						|
              pair->script_tag = scripts[j];
 | 
						|
              pair->lang_tag = HB_OT_TAG_DEFAULT_LANGUAGE;
 | 
						|
              pair->script_index = j;
 | 
						|
              pair->lang_index = HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX;
 | 
						|
              g_hash_table_add (tags, pair);
 | 
						|
 | 
						|
              hb_ot_layout_script_get_language_tags (hb_face, tables[i], j, 0, &language_count, languages);
 | 
						|
              for (k = 0; k < language_count; k++)
 | 
						|
                {
 | 
						|
                  pair = g_new (TagPair, 1);
 | 
						|
                  pair->script_tag = scripts[j];
 | 
						|
                  pair->lang_tag = languages[k];
 | 
						|
                  pair->script_index = j;
 | 
						|
                  pair->lang_index = k;
 | 
						|
                  g_hash_table_add (tags, pair);
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
      hb_face_destroy (hb_face);
 | 
						|
    }
 | 
						|
 | 
						|
  pango_fc_font_unlock_face (PANGO_FC_FONT (pango_font));
 | 
						|
  g_object_unref (pango_font);
 | 
						|
 | 
						|
  g_hash_table_iter_init (&iter, tags);
 | 
						|
  while (g_hash_table_iter_next (&iter, (gpointer *)&pair, NULL))
 | 
						|
    {
 | 
						|
      const char *scriptname;
 | 
						|
      char scriptbuf[5];
 | 
						|
      const char *langname;
 | 
						|
      char langbuf[5];
 | 
						|
      char *name;
 | 
						|
 | 
						|
      if (pair->script_tag == HB_OT_TAG_DEFAULT_SCRIPT)
 | 
						|
        scriptname = "Default";
 | 
						|
      else if (pair->script_tag == HB_TAG ('m','a','t','h'))
 | 
						|
        scriptname = "Math";
 | 
						|
      else
 | 
						|
        {
 | 
						|
          hb_script_t script;
 | 
						|
 | 
						|
          hb_tag_to_string (pair->script_tag, scriptbuf);
 | 
						|
          scriptbuf[4] = 0;
 | 
						|
          scriptname = scriptbuf;
 | 
						|
 | 
						|
          script = hb_script_from_iso15924_tag (pair->script_tag);
 | 
						|
          for (k = 0; k < G_N_ELEMENTS (script_names); k++)
 | 
						|
            {
 | 
						|
              if (script == script_names[k].script)
 | 
						|
                {
 | 
						|
                  scriptname = script_names[k].name;
 | 
						|
                  break;
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
      if (pair->lang_tag == HB_OT_TAG_DEFAULT_LANGUAGE)
 | 
						|
        langname = "Default";
 | 
						|
      else
 | 
						|
        {
 | 
						|
          hb_tag_to_string (pair->lang_tag, langbuf);
 | 
						|
          langbuf[4] = 0;
 | 
						|
          langname = langbuf;
 | 
						|
 | 
						|
          for (l = 0; l < G_N_ELEMENTS (language_names); l++)
 | 
						|
            {
 | 
						|
              if (pair->lang_tag == language_names[l].tag)
 | 
						|
                {
 | 
						|
                  langname = language_names[l].name;
 | 
						|
                  break;
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
      name = g_strdup_printf ("%s - %s", scriptname, langname);
 | 
						|
 | 
						|
      gtk_list_store_insert_with_values (store, NULL, -1,
 | 
						|
                                         0, name,
 | 
						|
                                         1, pair->script_index,
 | 
						|
                                         2, pair->lang_index,
 | 
						|
                                         3, pair->lang_tag,
 | 
						|
                                         -1);
 | 
						|
 | 
						|
      g_free (name);
 | 
						|
    }
 | 
						|
 | 
						|
  g_hash_table_destroy (tags);
 | 
						|
 | 
						|
  gtk_combo_box_set_model (GTK_COMBO_BOX (script_lang), GTK_TREE_MODEL (store));
 | 
						|
  gtk_combo_box_set_active (GTK_COMBO_BOX (script_lang), 0);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
update_features (void)
 | 
						|
{
 | 
						|
  gint i, j, k;
 | 
						|
  GtkTreeModel *model;
 | 
						|
  GtkTreeIter iter;
 | 
						|
  guint script_index, lang_index;
 | 
						|
  PangoFont *pango_font;
 | 
						|
  FT_Face ft_face;
 | 
						|
  hb_font_t *hb_font;
 | 
						|
 | 
						|
  for (i = 0; i < num_features; i++)
 | 
						|
    gtk_widget_set_opacity (icon[i], 0);
 | 
						|
 | 
						|
  /* set feature presence checks from the font features */
 | 
						|
 | 
						|
  if (!gtk_combo_box_get_active_iter (GTK_COMBO_BOX (script_lang), &iter))
 | 
						|
    return;
 | 
						|
 | 
						|
  model = gtk_combo_box_get_model (GTK_COMBO_BOX (script_lang));
 | 
						|
  gtk_tree_model_get (model, &iter,
 | 
						|
                      1, &script_index,
 | 
						|
                      2, &lang_index,
 | 
						|
                      -1);
 | 
						|
 | 
						|
  pango_font = get_pango_font ();
 | 
						|
  ft_face = pango_fc_font_lock_face (PANGO_FC_FONT (pango_font)),
 | 
						|
  hb_font = hb_ft_font_create (ft_face, NULL);
 | 
						|
 | 
						|
  if (hb_font)
 | 
						|
    {
 | 
						|
      hb_tag_t tables[2] = { HB_OT_TAG_GSUB, HB_OT_TAG_GPOS };
 | 
						|
      hb_face_t *hb_face;
 | 
						|
 | 
						|
      hb_face = hb_font_get_face (hb_font);
 | 
						|
 | 
						|
      for (i = 0; i < 2; i++)
 | 
						|
        {
 | 
						|
          hb_tag_t features[80];
 | 
						|
          unsigned int count = G_N_ELEMENTS(features);
 | 
						|
 | 
						|
          hb_ot_layout_language_get_feature_tags (hb_face,
 | 
						|
                                                  tables[i],
 | 
						|
                                                  script_index,
 | 
						|
                                                  lang_index,
 | 
						|
                                                  0,
 | 
						|
                                                  &count,
 | 
						|
                                                  features);
 | 
						|
 | 
						|
          for (j = 0; j < count; j++)
 | 
						|
            {
 | 
						|
              for (k = 0; k < num_features; k++)
 | 
						|
                {
 | 
						|
                  if (hb_tag_from_string (feature_names[k], -1) == features[j])
 | 
						|
                    gtk_widget_set_opacity (icon[k], 0.5);
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
      hb_face_destroy (hb_face);
 | 
						|
    }
 | 
						|
 | 
						|
  pango_fc_font_unlock_face (PANGO_FC_FONT (pango_font));
 | 
						|
  g_object_unref (pango_font);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
font_changed (void)
 | 
						|
{
 | 
						|
  update_script_combo ();
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
script_changed (void)
 | 
						|
{
 | 
						|
  update_features ();
 | 
						|
  update_display ();
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
reset_features (void)
 | 
						|
{
 | 
						|
  int i;
 | 
						|
 | 
						|
  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (numcasedefault), TRUE);
 | 
						|
  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (numspacedefault), TRUE);
 | 
						|
  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fractiondefault), TRUE);
 | 
						|
  for (i = 0; i < num_features; i++)
 | 
						|
    {
 | 
						|
      if (!GTK_IS_RADIO_BUTTON (toggle[i]))
 | 
						|
        {
 | 
						|
          gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle[i]), FALSE);
 | 
						|
          gtk_widget_set_sensitive (toggle[i], FALSE);
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
static char *text;
 | 
						|
 | 
						|
static void
 | 
						|
switch_to_entry (void)
 | 
						|
{
 | 
						|
  text = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry)));
 | 
						|
  gtk_stack_set_visible_child_name (GTK_STACK (stack), "entry");
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
switch_to_label (void)
 | 
						|
{
 | 
						|
  g_free (text);
 | 
						|
  text = NULL;
 | 
						|
  gtk_stack_set_visible_child_name (GTK_STACK (stack), "label");
 | 
						|
  update_display ();
 | 
						|
}
 | 
						|
 | 
						|
static gboolean
 | 
						|
entry_key_press (GtkEntry *entry, GdkEventKey *event)
 | 
						|
{
 | 
						|
  if (event->keyval == GDK_KEY_Escape)
 | 
						|
    {
 | 
						|
      gtk_entry_set_text (GTK_ENTRY (entry), text);
 | 
						|
      switch_to_label ();
 | 
						|
      return GDK_EVENT_STOP;
 | 
						|
    }
 | 
						|
 | 
						|
  return GDK_EVENT_PROPAGATE;
 | 
						|
}
 | 
						|
 | 
						|
GtkWidget *
 | 
						|
do_font_features (GtkWidget *do_widget)
 | 
						|
{
 | 
						|
  static GtkWidget *window = NULL;
 | 
						|
 | 
						|
  if (!window)
 | 
						|
    {
 | 
						|
      GtkBuilder *builder;
 | 
						|
      int i;
 | 
						|
 | 
						|
      builder = gtk_builder_new_from_resource ("/font_features/font-features.ui");
 | 
						|
 | 
						|
      gtk_builder_add_callback_symbol (builder, "update_display", update_display);
 | 
						|
      gtk_builder_add_callback_symbol (builder, "font_changed", font_changed);
 | 
						|
      gtk_builder_add_callback_symbol (builder, "script_changed", script_changed);
 | 
						|
      gtk_builder_add_callback_symbol (builder, "reset", reset_features);
 | 
						|
      gtk_builder_add_callback_symbol (builder, "switch_to_entry", switch_to_entry);
 | 
						|
      gtk_builder_add_callback_symbol (builder, "switch_to_label", switch_to_label);
 | 
						|
      gtk_builder_add_callback_symbol (builder, "entry_key_press", G_CALLBACK (entry_key_press));
 | 
						|
      gtk_builder_connect_signals (builder, NULL);
 | 
						|
 | 
						|
      window = GTK_WIDGET (gtk_builder_get_object (builder, "window"));
 | 
						|
      label = GTK_WIDGET (gtk_builder_get_object (builder, "label"));
 | 
						|
      settings = GTK_WIDGET (gtk_builder_get_object (builder, "settings"));
 | 
						|
      resetbutton = GTK_WIDGET (gtk_builder_get_object (builder, "reset"));
 | 
						|
      font = GTK_WIDGET (gtk_builder_get_object (builder, "font"));
 | 
						|
      script_lang = GTK_WIDGET (gtk_builder_get_object (builder, "script_lang"));
 | 
						|
      numcasedefault = GTK_WIDGET (gtk_builder_get_object (builder, "numcasedefault"));
 | 
						|
      numspacedefault = GTK_WIDGET (gtk_builder_get_object (builder, "numspacedefault"));
 | 
						|
      fractiondefault = GTK_WIDGET (gtk_builder_get_object (builder, "fractiondefault"));
 | 
						|
      stack = GTK_WIDGET (gtk_builder_get_object (builder, "stack"));
 | 
						|
      entry = GTK_WIDGET (gtk_builder_get_object (builder, "entry"));
 | 
						|
 | 
						|
      for (i = 0; i < num_features; i++)
 | 
						|
        {
 | 
						|
          char *iname;
 | 
						|
 | 
						|
          toggle[i] = GTK_WIDGET (gtk_builder_get_object (builder, feature_names[i]));
 | 
						|
          iname = g_strconcat (feature_names[i], "_pres", NULL);
 | 
						|
          icon[i] = GTK_WIDGET (gtk_builder_get_object (builder, iname));
 | 
						|
          g_free (iname);
 | 
						|
        }
 | 
						|
 | 
						|
      font_changed ();
 | 
						|
 | 
						|
      g_signal_connect (window, "destroy",
 | 
						|
                        G_CALLBACK (gtk_widget_destroyed), &window);
 | 
						|
 | 
						|
      g_object_unref (builder);
 | 
						|
    }
 | 
						|
 | 
						|
  if (!gtk_widget_get_visible (window))
 | 
						|
    gtk_window_present (GTK_WINDOW (window));
 | 
						|
  else
 | 
						|
    gtk_widget_destroy (window);
 | 
						|
 | 
						|
  return window;
 | 
						|
}
 |