+static void
+clear_font_data (GtkFontButton *font_button)
+{
+ GtkFontButtonPrivate *priv = font_button->priv;
+
+ if (priv->font_family)
+ g_object_unref (priv->font_family);
+ priv->font_family = NULL;
+
+ if (priv->font_face)
+ g_object_unref (priv->font_face);
+ priv->font_face = NULL;
+
+ if (priv->font_desc)
+ pango_font_description_free (priv->font_desc);
+ priv->font_desc = NULL;
+
+ g_free (priv->fontname);
+ priv->fontname = NULL;
+}
+
+static void
+clear_font_filter_data (GtkFontButton *font_button)
+{
+ GtkFontButtonPrivate *priv = font_button->priv;
+
+ if (priv->font_filter_data_destroy)
+ priv->font_filter_data_destroy (priv->font_filter_data);
+ priv->font_filter = NULL;
+ priv->font_filter_data = NULL;
+ priv->font_filter_data_destroy = NULL;
+}
+
+static gboolean
+font_description_style_equal (const PangoFontDescription *a,
+ const PangoFontDescription *b)
+{
+ return (pango_font_description_get_weight (a) == pango_font_description_get_weight (b) &&
+ pango_font_description_get_style (a) == pango_font_description_get_style (b) &&
+ pango_font_description_get_stretch (a) == pango_font_description_get_stretch (b) &&
+ pango_font_description_get_variant (a) == pango_font_description_get_variant (b));
+}
+
+static void
+gtk_font_button_update_font_data (GtkFontButton *font_button)
+{
+ GtkFontButtonPrivate *priv = font_button->priv;
+ PangoFontFamily **families;
+ PangoFontFace **faces;
+ gint n_families, n_faces, i;
+ const gchar *family;
+
+ g_assert (priv->font_desc != NULL);
+
+ priv->fontname = pango_font_description_to_string (priv->font_desc);
+
+ family = pango_font_description_get_family (priv->font_desc);
+ if (family == NULL)
+ return;
+
+ n_families = 0;
+ families = NULL;
+ pango_context_list_families (gtk_widget_get_pango_context (GTK_WIDGET (font_button)),
+ &families, &n_families);
+ n_faces = 0;
+ faces = NULL;
+ for (i = 0; i < n_families; i++)
+ {
+ const gchar *name = pango_font_family_get_name (families[i]);
+
+ if (!g_ascii_strcasecmp (name, family))
+ {
+ priv->font_family = g_object_ref (families[i]);
+
+ pango_font_family_list_faces (families[i], &faces, &n_faces);
+ break;
+ }
+ }
+ g_free (families);
+
+ for (i = 0; i < n_faces; i++)
+ {
+ PangoFontDescription *tmp_desc = pango_font_face_describe (faces[i]);
+
+ if (font_description_style_equal (tmp_desc, priv->font_desc))
+ {
+ priv->font_face = g_object_ref (faces[i]);
+
+ pango_font_description_free (tmp_desc);
+ break;
+ }
+ else
+ pango_font_description_free (tmp_desc);
+ }
+
+ g_free (faces);
+}
+
+static gchar *
+gtk_font_button_get_preview_text (GtkFontButton *font_button)
+{
+ GtkFontButtonPrivate *priv = font_button->priv;
+
+ if (priv->font_dialog)
+ return gtk_font_chooser_get_preview_text (GTK_FONT_CHOOSER (priv->font_dialog));
+
+ return g_strdup (priv->preview_text);
+}
+
+static void
+gtk_font_button_set_preview_text (GtkFontButton *font_button,
+ const gchar *preview_text)
+{
+ GtkFontButtonPrivate *priv = font_button->priv;
+
+ if (priv->font_dialog)
+ {
+ gtk_font_chooser_set_preview_text (GTK_FONT_CHOOSER (priv->font_dialog),
+ preview_text);
+ return;
+ }
+
+ g_free (priv->preview_text);
+ priv->preview_text = g_strdup (preview_text);
+}
+
+
+static gboolean
+gtk_font_button_get_show_preview_entry (GtkFontButton *font_button)
+{
+ GtkFontButtonPrivate *priv = font_button->priv;
+
+ if (priv->font_dialog)
+ return gtk_font_chooser_get_show_preview_entry (GTK_FONT_CHOOSER (priv->font_dialog));
+
+ return priv->show_preview_entry;
+}
+
+static void
+gtk_font_button_set_show_preview_entry (GtkFontButton *font_button,
+ gboolean show)
+{
+ GtkFontButtonPrivate *priv = font_button->priv;
+
+ if (priv->font_dialog)
+ gtk_font_chooser_set_show_preview_entry (GTK_FONT_CHOOSER (priv->font_dialog), show);
+ else
+ priv->show_preview_entry = show != FALSE;
+}
+
+static PangoFontFamily *
+gtk_font_button_font_chooser_get_font_family (GtkFontChooser *chooser)
+{
+ GtkFontButton *font_button = GTK_FONT_BUTTON (chooser);
+ GtkFontButtonPrivate *priv = font_button->priv;
+
+ return priv->font_family;
+}
+
+static PangoFontFace *
+gtk_font_button_font_chooser_get_font_face (GtkFontChooser *chooser)
+{
+ GtkFontButton *font_button = GTK_FONT_BUTTON (chooser);
+ GtkFontButtonPrivate *priv = font_button->priv;
+
+ return priv->font_face;
+}
+
+static int
+gtk_font_button_font_chooser_get_font_size (GtkFontChooser *chooser)
+{
+ GtkFontButton *font_button = GTK_FONT_BUTTON (chooser);
+ GtkFontButtonPrivate *priv = font_button->priv;
+
+ return priv->font_size;
+}
+
+static void
+gtk_font_button_font_chooser_set_filter_func (GtkFontChooser *chooser,
+ GtkFontFilterFunc filter_func,
+ gpointer filter_data,
+ GDestroyNotify data_destroy)
+{
+ GtkFontButton *font_button = GTK_FONT_BUTTON (chooser);
+ GtkFontButtonPrivate *priv = font_button->priv;
+
+ if (priv->font_dialog)
+ {
+ gtk_font_chooser_set_filter_func (GTK_FONT_CHOOSER (priv->font_dialog),
+ filter_func,
+ filter_data,
+ data_destroy);
+ return;
+ }
+
+ clear_font_filter_data (font_button);
+ priv->font_filter = filter_func;
+ priv->font_filter_data = filter_data;
+ priv->font_filter_data_destroy = data_destroy;
+}
+
+static void
+gtk_font_button_take_font_desc (GtkFontButton *font_button,
+ PangoFontDescription *font_desc)
+{
+ GtkFontButtonPrivate *priv = font_button->priv;
+ GObject *object = G_OBJECT (font_button);
+
+ if (priv->font_desc && font_desc &&
+ pango_font_description_equal (priv->font_desc, font_desc))
+ {
+ pango_font_description_free (font_desc);
+ return;
+ }
+
+ g_object_freeze_notify (object);
+
+ clear_font_data (font_button);
+
+ if (font_desc)
+ priv->font_desc = font_desc; /* adopted */
+ else
+ priv->font_desc = pango_font_description_from_string (_("Sans 12"));
+
+ if (pango_font_description_get_size_is_absolute (priv->font_desc))
+ priv->font_size = pango_font_description_get_size (priv->font_desc);
+ else
+ priv->font_size = pango_font_description_get_size (priv->font_desc) / PANGO_SCALE;
+
+ gtk_font_button_update_font_data (font_button);
+ gtk_font_button_update_font_info (font_button);
+
+ if (priv->font_dialog)
+ gtk_font_chooser_set_font_desc (GTK_FONT_CHOOSER (priv->font_dialog),
+ priv->font_desc);
+
+ g_object_notify (G_OBJECT (font_button), "font");
+ g_object_notify (G_OBJECT (font_button), "font-desc");
+ g_object_notify (G_OBJECT (font_button), "font-name");
+
+ g_object_thaw_notify (object);
+}
+
+static const PangoFontDescription *
+gtk_font_button_get_font_desc (GtkFontButton *font_button)
+{
+ return font_button->priv->font_desc;
+}
+
+static void
+gtk_font_button_font_chooser_notify (GObject *object,
+ GParamSpec *pspec,
+ gpointer user_data)
+{
+ /* We do not forward the notification of the "font" property to the dialog! */
+ if (pspec->name == I_("preview-text") ||
+ pspec->name == I_("show-preview-entry"))
+ g_object_notify_by_pspec (user_data, pspec);
+}
+
+static void
+gtk_font_button_font_chooser_iface_init (GtkFontChooserIface *iface)
+{
+ iface->get_font_family = gtk_font_button_font_chooser_get_font_family;
+ iface->get_font_face = gtk_font_button_font_chooser_get_font_face;
+ iface->get_font_size = gtk_font_button_font_chooser_get_font_size;
+ iface->set_filter_func = gtk_font_button_font_chooser_set_filter_func;
+}
+
+G_DEFINE_TYPE_WITH_CODE (GtkFontButton, gtk_font_button, GTK_TYPE_BUTTON,
+ G_IMPLEMENT_INTERFACE (GTK_TYPE_FONT_CHOOSER,
+ gtk_font_button_font_chooser_iface_init))