]> Pileus Git - ~andy/gtk/blob - gtk/gtkfontsel.c
Various cleanups. (#315360, Kjartan Maraas)
[~andy/gtk] / gtk / gtkfontsel.c
1 /* GTK - The GIMP Toolkit
2  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3  *
4  * Massively updated for Pango by Owen Taylor, May 2000
5  * GtkFontSelection widget for Gtk+, by Damon Chaplin, May 1998.
6  * Based on the GnomeFontSelector widget, by Elliot Lee, but major changes.
7  * The GnomeFontSelector was derived from app/text_tool.c in the GIMP.
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the
21  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
22  * Boston, MA 02111-1307, USA.
23  */
24
25 /*
26  * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
27  * file for a list of people on the GTK+ Team.  See the ChangeLog
28  * files for a list of changes.  These files are distributed with
29  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
30  */
31
32 #include <config.h>
33 #include <stdlib.h>
34 #include <glib/gprintf.h>
35 #include <string.h>
36
37 #include <atk/atk.h>
38
39 #include "gdk/gdk.h"
40 #include "gdk/gdkkeysyms.h"
41
42 #include "gtkfontsel.h"
43
44 #include "gtkbutton.h"
45 #include "gtkcellrenderertext.h"
46 #include "gtkentry.h"
47 #include "gtkframe.h"
48 #include "gtkhbbox.h"
49 #include "gtkhbox.h"
50 #include "gtklabel.h"
51 #include "gtkliststore.h"
52 #include "gtkrc.h"
53 #include "gtkstock.h"
54 #include "gtktable.h"
55 #include "gtktreeselection.h"
56 #include "gtktreeview.h"
57 #include "gtkvbox.h"
58 #include "gtkscrolledwindow.h"
59 #include "gtkintl.h"
60 #include "gtkaccessible.h"
61 #include "gtkprivate.h"
62 #include "gtkalias.h"
63
64 /* We don't enable the font and style entries because they don't add
65  * much in terms of visible effect and have a weird effect on keynav.
66  * the Windows font selector has entries similarly positioned but they
67  * act in conjunction with the associated lists to form a single focus
68  * location.
69  */
70 #undef INCLUDE_FONT_ENTRIES
71
72 /* This is the default text shown in the preview entry, though the user
73    can set it. Remember that some fonts only have capital letters. */
74 #define PREVIEW_TEXT N_("abcdefghijk ABCDEFGHIJK")
75
76 /* This is the initial and maximum height of the preview entry (it expands
77    when large font sizes are selected). Initial height is also the minimum. */
78 #define INITIAL_PREVIEW_HEIGHT 44
79 #define MAX_PREVIEW_HEIGHT 300
80
81 /* These are the sizes of the font, style & size lists. */
82 #define FONT_LIST_HEIGHT        136
83 #define FONT_LIST_WIDTH         190
84 #define FONT_STYLE_LIST_WIDTH   170
85 #define FONT_SIZE_LIST_WIDTH    60
86
87 /* These are what we use as the standard font sizes, for the size list.
88  */
89 static const guint16 font_sizes[] = {
90   8, 9, 10, 11, 12, 13, 14, 16, 18, 20, 22, 24, 26, 28,
91   32, 36, 40, 48, 56, 64, 72
92 };
93
94 enum {
95    PROP_0,
96    PROP_FONT_NAME,
97    PROP_FONT,
98    PROP_PREVIEW_TEXT
99 };
100
101
102 enum {
103   FAMILY_COLUMN,
104   FAMILY_NAME_COLUMN
105 };
106
107 enum {
108   FACE_COLUMN,
109   FACE_NAME_COLUMN
110 };
111
112 enum {
113   SIZE_COLUMN
114 };
115
116 static void    gtk_font_selection_class_init         (GtkFontSelectionClass *klass);
117 static void    gtk_font_selection_set_property       (GObject         *object,
118                                                       guint            prop_id,
119                                                       const GValue    *value,
120                                                       GParamSpec      *pspec);
121 static void    gtk_font_selection_get_property       (GObject         *object,
122                                                       guint            prop_id,
123                                                       GValue          *value,
124                                                       GParamSpec      *pspec);
125 static void    gtk_font_selection_init               (GtkFontSelection      *fontsel);
126 static void    gtk_font_selection_finalize           (GObject               *object);
127 static void    gtk_font_selection_screen_changed     (GtkWidget             *widget,
128                                                       GdkScreen             *previous_screen);
129
130 /* These are the callbacks & related functions. */
131 static void     gtk_font_selection_select_font           (GtkTreeSelection *selection,
132                                                           gpointer          data);
133 static void     gtk_font_selection_show_available_fonts  (GtkFontSelection *fs);
134
135 static void     gtk_font_selection_show_available_styles (GtkFontSelection *fs);
136 static void     gtk_font_selection_select_best_style     (GtkFontSelection *fs,
137                                                           gboolean          use_first);
138 static void     gtk_font_selection_select_style          (GtkTreeSelection *selection,
139                                                           gpointer          data);
140
141 static void     gtk_font_selection_select_best_size      (GtkFontSelection *fs);
142 static void     gtk_font_selection_show_available_sizes  (GtkFontSelection *fs,
143                                                           gboolean          first_time);
144 static void     gtk_font_selection_size_activate         (GtkWidget        *w,
145                                                           gpointer          data);
146 static gboolean gtk_font_selection_size_focus_out        (GtkWidget        *w,
147                                                           GdkEventFocus    *event,
148                                                           gpointer          data);
149 static void     gtk_font_selection_select_size           (GtkTreeSelection *selection,
150                                                           gpointer          data);
151
152 static void     gtk_font_selection_scroll_on_map         (GtkWidget        *w,
153                                                           gpointer          data);
154
155 static void     gtk_font_selection_preview_changed       (GtkWidget        *entry,
156                                                           GtkFontSelection *fontsel);
157
158 /* Misc. utility functions. */
159 static void    gtk_font_selection_load_font          (GtkFontSelection *fs);
160 static void    gtk_font_selection_update_preview     (GtkFontSelection *fs);
161
162 static GdkFont* gtk_font_selection_get_font_internal (GtkFontSelection *fontsel);
163
164 /* FontSelectionDialog */
165 static void    gtk_font_selection_dialog_class_init  (GtkFontSelectionDialogClass *klass);
166 static void    gtk_font_selection_dialog_init        (GtkFontSelectionDialog *fontseldiag);
167
168 static GtkVBoxClass *font_selection_parent_class = NULL;
169 static GtkWindowClass *font_selection_dialog_parent_class = NULL;
170
171
172 GType
173 gtk_font_selection_get_type (void)
174 {
175   static GType font_selection_type = 0;
176   
177   if (!font_selection_type)
178     {
179       static const GTypeInfo fontsel_type_info =
180       {
181         sizeof (GtkFontSelectionClass),
182         NULL,           /* base_init */
183         NULL,           /* base_finalize */
184         (GClassInitFunc) gtk_font_selection_class_init,
185         NULL,           /* class_finalize */
186         NULL,           /* class_data */
187         sizeof (GtkFontSelection),
188         0,              /* n_preallocs */
189         (GInstanceInitFunc) gtk_font_selection_init,
190       };
191       
192       font_selection_type =
193         g_type_register_static (GTK_TYPE_VBOX, I_("GtkFontSelection"),
194                                 &fontsel_type_info, 0);
195     }
196   
197   return font_selection_type;
198 }
199
200 static void
201 gtk_font_selection_class_init (GtkFontSelectionClass *klass)
202 {
203   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
204   GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
205   
206   font_selection_parent_class = g_type_class_peek_parent (klass);
207   
208   gobject_class->set_property = gtk_font_selection_set_property;
209   gobject_class->get_property = gtk_font_selection_get_property;
210
211   widget_class->screen_changed = gtk_font_selection_screen_changed;
212    
213   g_object_class_install_property (gobject_class,
214                                    PROP_FONT_NAME,
215                                    g_param_spec_string ("font-name",
216                                                         P_("Font name"),
217                                                         P_("The X string that represents this font"),
218                                                         NULL,
219                                                         GTK_PARAM_READWRITE));
220   g_object_class_install_property (gobject_class,
221                                    PROP_FONT,
222                                    g_param_spec_boxed ("font",
223                                                        P_("Font"),
224                                                        P_("The GdkFont that is currently selected"),
225                                                        GDK_TYPE_FONT,
226                                                        GTK_PARAM_READABLE));
227   g_object_class_install_property (gobject_class,
228                                    PROP_PREVIEW_TEXT,
229                                    g_param_spec_string ("preview-text",
230                                                         P_("Preview text"),
231                                                         P_("The text to display in order to demonstrate the selected font"),
232                                                         PREVIEW_TEXT,
233                                                         GTK_PARAM_READWRITE));
234   gobject_class->finalize = gtk_font_selection_finalize;
235 }
236
237 static void 
238 gtk_font_selection_set_property (GObject         *object,
239                                  guint            prop_id,
240                                  const GValue    *value,
241                                  GParamSpec      *pspec)
242 {
243   GtkFontSelection *fontsel;
244
245   fontsel = GTK_FONT_SELECTION (object);
246
247   switch (prop_id)
248     {
249     case PROP_FONT_NAME:
250       gtk_font_selection_set_font_name (fontsel, g_value_get_string (value));
251       break;
252     case PROP_PREVIEW_TEXT:
253       gtk_font_selection_set_preview_text (fontsel, g_value_get_string (value));
254       break;
255     default:
256       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
257       break;
258     }
259 }
260
261 static void gtk_font_selection_get_property (GObject         *object,
262                                              guint            prop_id,
263                                              GValue          *value,
264                                              GParamSpec      *pspec)
265 {
266   GtkFontSelection *fontsel;
267
268   fontsel = GTK_FONT_SELECTION (object);
269
270   switch (prop_id)
271     {
272     case PROP_FONT_NAME:
273       g_value_set_string (value, gtk_font_selection_get_font_name (fontsel));
274       break;
275     case PROP_FONT:
276       g_value_set_object (value, gtk_font_selection_get_font_internal (fontsel));
277       break;
278     case PROP_PREVIEW_TEXT:
279       g_value_set_string (value, gtk_font_selection_get_preview_text (fontsel));
280       break;
281     default:
282       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
283       break;
284     }
285 }
286
287 /* Handles key press events on the lists, so that we can trap Enter to
288  * activate the default button on our own.
289  */
290 static gboolean
291 list_row_activated (GtkWidget *widget)
292 {
293   GtkWindow *window;
294   
295   window = GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (widget)));
296   if (!GTK_WIDGET_TOPLEVEL (window))
297     window = NULL;
298   
299   if (window
300       && widget != window->default_widget
301       && !(widget == window->focus_widget &&
302            (!window->default_widget || !GTK_WIDGET_SENSITIVE (window->default_widget))))
303     {
304       gtk_window_activate_default (window);
305     }
306   
307   return TRUE;
308 }
309
310 static void
311 gtk_font_selection_init (GtkFontSelection *fontsel)
312 {
313   GtkWidget *scrolled_win;
314   GtkWidget *text_frame;
315   GtkWidget *text_box;
316   GtkWidget *table, *label;
317   GtkWidget *font_label, *style_label;
318   GtkListStore *model;
319   GtkTreeViewColumn *column;
320   GList *focus_chain = NULL;
321   AtkObject *atk_obj;
322
323   gtk_widget_push_composite_child ();
324
325   fontsel->size = 12 * PANGO_SCALE;
326   
327   /* Create the table of font, style & size. */
328   table = gtk_table_new (3, 3, FALSE);
329   gtk_widget_show (table);
330   gtk_table_set_col_spacings (GTK_TABLE (table), 8);
331   gtk_box_pack_start (GTK_BOX (fontsel), table, TRUE, TRUE, 0);
332
333 #ifdef INCLUDE_FONT_ENTRIES
334   fontsel->font_entry = gtk_entry_new ();
335   gtk_editable_set_editable (GTK_EDITABLE (fontsel->font_entry), FALSE);
336   gtk_widget_set_size_request (fontsel->font_entry, 20, -1);
337   gtk_widget_show (fontsel->font_entry);
338   gtk_table_attach (GTK_TABLE (table), fontsel->font_entry, 0, 1, 1, 2,
339                     GTK_FILL, 0, 0, 0);
340   
341   fontsel->font_style_entry = gtk_entry_new ();
342   gtk_editable_set_editable (GTK_EDITABLE (fontsel->font_style_entry), FALSE);
343   gtk_widget_set_size_request (fontsel->font_style_entry, 20, -1);
344   gtk_widget_show (fontsel->font_style_entry);
345   gtk_table_attach (GTK_TABLE (table), fontsel->font_style_entry, 1, 2, 1, 2,
346                     GTK_FILL, 0, 0, 0);
347 #endif /* INCLUDE_FONT_ENTRIES */
348   
349   fontsel->size_entry = gtk_entry_new ();
350   gtk_widget_set_size_request (fontsel->size_entry, 20, -1);
351   gtk_widget_show (fontsel->size_entry);
352   gtk_table_attach (GTK_TABLE (table), fontsel->size_entry, 2, 3, 1, 2,
353                     GTK_FILL, 0, 0, 0);
354   g_signal_connect (fontsel->size_entry, "activate",
355                     G_CALLBACK (gtk_font_selection_size_activate),
356                     fontsel);
357   g_signal_connect_after (fontsel->size_entry, "focus_out_event",
358                           G_CALLBACK (gtk_font_selection_size_focus_out),
359                           fontsel);
360   
361   font_label = gtk_label_new_with_mnemonic (_("_Family:"));
362   gtk_misc_set_alignment (GTK_MISC (font_label), 0.0, 0.5);
363   gtk_widget_show (font_label);
364   gtk_table_attach (GTK_TABLE (table), font_label, 0, 1, 0, 1,
365                     GTK_FILL, 0, 0, 0);  
366
367   style_label = gtk_label_new_with_mnemonic (_("_Style:"));
368   gtk_misc_set_alignment (GTK_MISC (style_label), 0.0, 0.5);
369   gtk_widget_show (style_label);
370   gtk_table_attach (GTK_TABLE (table), style_label, 1, 2, 0, 1,
371                     GTK_FILL, 0, 0, 0);
372   
373   label = gtk_label_new_with_mnemonic (_("Si_ze:"));
374   gtk_label_set_mnemonic_widget (GTK_LABEL (label),
375                                  fontsel->size_entry);
376   gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
377   gtk_widget_show (label);
378   gtk_table_attach (GTK_TABLE (table), label, 2, 3, 0, 1,
379                     GTK_FILL, 0, 0, 0);
380   
381   
382   /* Create the lists  */
383
384   model = gtk_list_store_new (2,
385                               G_TYPE_OBJECT,  /* FAMILY_COLUMN */
386                               G_TYPE_STRING); /* FAMILY_NAME_COLUMN */
387   fontsel->family_list = gtk_tree_view_new_with_model (GTK_TREE_MODEL (model));
388   g_object_unref (model);
389
390   g_signal_connect (fontsel->family_list, "row-activated",
391                     G_CALLBACK (list_row_activated), fontsel);
392
393   column = gtk_tree_view_column_new_with_attributes ("Family",
394                                                      gtk_cell_renderer_text_new (),
395                                                      "text", FAMILY_NAME_COLUMN,
396                                                      NULL);
397   gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
398   gtk_tree_view_append_column (GTK_TREE_VIEW (fontsel->family_list), column);
399
400   gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (fontsel->family_list), FALSE);
401   gtk_tree_selection_set_mode (gtk_tree_view_get_selection (GTK_TREE_VIEW (fontsel->family_list)),
402                                GTK_SELECTION_BROWSE);
403   
404   gtk_label_set_mnemonic_widget (GTK_LABEL (font_label), fontsel->family_list);
405
406   scrolled_win = gtk_scrolled_window_new (NULL, NULL);
407   gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_win), GTK_SHADOW_IN);
408   gtk_widget_set_size_request (scrolled_win,
409                                FONT_LIST_WIDTH, FONT_LIST_HEIGHT);
410   gtk_container_add (GTK_CONTAINER (scrolled_win), fontsel->family_list);
411   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
412                                   GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
413   gtk_widget_show (fontsel->family_list);
414   gtk_widget_show (scrolled_win);
415
416   gtk_table_attach (GTK_TABLE (table), scrolled_win, 0, 1, 1, 3,
417                     GTK_EXPAND | GTK_FILL,
418                     GTK_EXPAND | GTK_FILL, 0, 0);
419   focus_chain = g_list_append (focus_chain, scrolled_win);
420   
421   model = gtk_list_store_new (2,
422                               G_TYPE_OBJECT,  /* FACE_COLUMN */
423                               G_TYPE_STRING); /* FACE_NAME_COLUMN */
424   fontsel->face_list = gtk_tree_view_new_with_model (GTK_TREE_MODEL (model));
425   g_object_unref (model);
426   g_signal_connect (fontsel->face_list, "row-activated",
427                     G_CALLBACK (list_row_activated), fontsel);
428
429   gtk_label_set_mnemonic_widget (GTK_LABEL (style_label), fontsel->face_list);
430
431   column = gtk_tree_view_column_new_with_attributes ("Face",
432                                                      gtk_cell_renderer_text_new (),
433                                                      "text", FACE_NAME_COLUMN,
434                                                      NULL);
435   gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
436   gtk_tree_view_append_column (GTK_TREE_VIEW (fontsel->face_list), column);
437
438   gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (fontsel->face_list), FALSE);
439   gtk_tree_selection_set_mode (gtk_tree_view_get_selection (GTK_TREE_VIEW (fontsel->face_list)),
440                                GTK_SELECTION_BROWSE);
441   
442   scrolled_win = gtk_scrolled_window_new (NULL, NULL);
443   gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_win), GTK_SHADOW_IN);
444   gtk_widget_set_size_request (scrolled_win,
445                                FONT_STYLE_LIST_WIDTH, FONT_LIST_HEIGHT);
446   gtk_container_add (GTK_CONTAINER (scrolled_win), fontsel->face_list);
447   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
448                                   GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
449   gtk_widget_show (fontsel->face_list);
450   gtk_widget_show (scrolled_win);
451   gtk_table_attach (GTK_TABLE (table), scrolled_win, 1, 2, 1, 3,
452                     GTK_EXPAND | GTK_FILL,
453                     GTK_EXPAND | GTK_FILL, 0, 0);
454   focus_chain = g_list_append (focus_chain, scrolled_win);
455   
456   focus_chain = g_list_append (focus_chain, fontsel->size_entry);
457
458   model = gtk_list_store_new (1, G_TYPE_INT);
459   fontsel->size_list = gtk_tree_view_new_with_model (GTK_TREE_MODEL (model));
460   g_object_unref (model);
461   g_signal_connect (fontsel->size_list, "row-activated",
462                     G_CALLBACK (list_row_activated), fontsel);
463
464   column = gtk_tree_view_column_new_with_attributes ("Size",
465                                                      gtk_cell_renderer_text_new (),
466                                                      "text", SIZE_COLUMN,
467                                                      NULL);
468   gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
469   gtk_tree_view_append_column (GTK_TREE_VIEW (fontsel->size_list), column);
470
471   gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (fontsel->size_list), FALSE);
472   gtk_tree_selection_set_mode (gtk_tree_view_get_selection (GTK_TREE_VIEW (fontsel->size_list)),
473                                GTK_SELECTION_BROWSE);
474   
475   scrolled_win = gtk_scrolled_window_new (NULL, NULL);
476   gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_win), GTK_SHADOW_IN);
477   gtk_container_add (GTK_CONTAINER (scrolled_win), fontsel->size_list);
478   gtk_widget_set_size_request (scrolled_win, -1, FONT_LIST_HEIGHT);
479   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
480                                   GTK_POLICY_NEVER, GTK_POLICY_ALWAYS);
481   gtk_widget_show (fontsel->size_list);
482   gtk_widget_show (scrolled_win);
483   gtk_table_attach (GTK_TABLE (table), scrolled_win, 2, 3, 2, 3,
484                     GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
485   focus_chain = g_list_append (focus_chain, scrolled_win);
486
487   gtk_container_set_focus_chain (GTK_CONTAINER (table), focus_chain);
488   g_list_free (focus_chain);
489   
490   /* Insert the fonts. */
491   g_signal_connect (gtk_tree_view_get_selection (GTK_TREE_VIEW (fontsel->family_list)), "changed",
492                     G_CALLBACK (gtk_font_selection_select_font), fontsel);
493
494   g_signal_connect_after (fontsel->family_list, "map",
495                           G_CALLBACK (gtk_font_selection_scroll_on_map),
496                           fontsel);
497   
498   g_signal_connect (gtk_tree_view_get_selection (GTK_TREE_VIEW (fontsel->face_list)), "changed",
499                     G_CALLBACK (gtk_font_selection_select_style), fontsel);
500
501   g_signal_connect (gtk_tree_view_get_selection (GTK_TREE_VIEW (fontsel->size_list)), "changed",
502                     G_CALLBACK (gtk_font_selection_select_size), fontsel);
503   atk_obj = gtk_widget_get_accessible (fontsel->size_list);
504   if (GTK_IS_ACCESSIBLE (atk_obj))
505     {
506       /* Accessibility support is enabled.
507        * Make the label ATK_RELATON_LABEL_FOR for the size list as well.
508        */
509       AtkObject *atk_label;
510       AtkRelationSet *relation_set;
511       AtkRelation *relation;
512       AtkObject *obj_array[1];
513       GPtrArray *array;
514
515       atk_label = gtk_widget_get_accessible (label);
516       relation_set = atk_object_ref_relation_set (atk_obj);
517       relation = atk_relation_set_get_relation_by_type (relation_set, ATK_RELATION_LABELLED_BY);
518       if (relation)
519         {
520           array = atk_relation_get_target (relation);
521           g_ptr_array_add (array, atk_label);
522         }
523       else 
524         {
525           obj_array[0] = atk_label;
526           relation = atk_relation_new (obj_array, 1, ATK_RELATION_LABELLED_BY);
527           atk_relation_set_add (relation_set, relation);
528         }
529       g_object_unref (relation_set);
530
531       relation_set = atk_object_ref_relation_set (atk_label);
532       relation = atk_relation_set_get_relation_by_type (relation_set, ATK_RELATION_LABEL_FOR);
533       if (relation)
534         {
535           array = atk_relation_get_target (relation);
536           g_ptr_array_add (array, atk_obj);
537         }
538       else 
539         {
540           obj_array[0] = atk_obj;
541           relation = atk_relation_new (obj_array, 1, ATK_RELATION_LABEL_FOR);
542           atk_relation_set_add (relation_set, relation);
543         }
544       g_object_unref (relation_set);
545     }    
546       
547
548   /* create the text entry widget */
549   label = gtk_label_new_with_mnemonic (_("_Preview:"));
550   gtk_widget_show (label);
551   
552   text_frame = gtk_frame_new (NULL);
553   gtk_frame_set_label_widget (GTK_FRAME (text_frame), label);
554   
555   gtk_widget_show (text_frame);
556   gtk_frame_set_shadow_type (GTK_FRAME (text_frame), GTK_SHADOW_ETCHED_IN);
557   gtk_box_pack_start (GTK_BOX (fontsel), text_frame,
558                       FALSE, TRUE, 0);
559   
560   /* This is just used to get a 4-pixel space around the preview entry. */
561   text_box = gtk_hbox_new (FALSE, 0);
562   gtk_widget_show (text_box);
563   gtk_container_add (GTK_CONTAINER (text_frame), text_box);
564   gtk_container_set_border_width (GTK_CONTAINER (text_box), 4);
565   
566   fontsel->preview_entry = gtk_entry_new ();
567   gtk_label_set_mnemonic_widget (GTK_LABEL (label), fontsel->preview_entry);
568   
569   gtk_widget_show (fontsel->preview_entry);
570   g_signal_connect (fontsel->preview_entry, "changed",
571                     G_CALLBACK (gtk_font_selection_preview_changed), fontsel);
572   gtk_widget_set_size_request (fontsel->preview_entry,
573                                -1, INITIAL_PREVIEW_HEIGHT);
574   gtk_box_pack_start (GTK_BOX (text_box), fontsel->preview_entry,
575                       TRUE, TRUE, 0);
576
577   gtk_widget_pop_composite_child();
578 }
579
580 GtkWidget *
581 gtk_font_selection_new (void)
582 {
583   GtkFontSelection *fontsel;
584   
585   fontsel = g_object_new (GTK_TYPE_FONT_SELECTION, NULL);
586   
587   return GTK_WIDGET (fontsel);
588 }
589
590 static void
591 gtk_font_selection_finalize (GObject *object)
592 {
593   GtkFontSelection *fontsel;
594   
595   g_return_if_fail (GTK_IS_FONT_SELECTION (object));
596   
597   fontsel = GTK_FONT_SELECTION (object);
598
599   if (fontsel->font)
600     gdk_font_unref (fontsel->font);
601   
602   (* G_OBJECT_CLASS (font_selection_parent_class)->finalize) (object);
603 }
604
605 static void
606 gtk_font_selection_screen_changed (GtkWidget *widget,
607                                    GdkScreen *previous_screen)
608 {
609   GtkFontSelection *fontsel = GTK_FONT_SELECTION (widget);
610
611   if (gtk_widget_has_screen (GTK_WIDGET (fontsel)))
612     {
613       gtk_font_selection_show_available_fonts (fontsel);
614       gtk_font_selection_show_available_sizes (fontsel, TRUE);
615       gtk_font_selection_show_available_styles (fontsel);
616     }
617 }
618
619 static void
620 gtk_font_selection_preview_changed (GtkWidget        *entry,
621                                     GtkFontSelection *fontsel)
622 {
623   g_object_notify (G_OBJECT (fontsel), "preview_text");
624 }
625
626 static void
627 scroll_to_selection (GtkTreeView *tree_view)
628 {
629   GtkTreeSelection *selection = gtk_tree_view_get_selection (tree_view);
630   GtkTreeModel *model;
631   GtkTreeIter iter;
632
633   if (gtk_tree_selection_get_selected (selection, &model, &iter))
634     {
635       GtkTreePath *path = gtk_tree_model_get_path (model, &iter);
636       gtk_tree_view_scroll_to_cell (tree_view, path, NULL, TRUE, 0.5, 0.5);
637       gtk_tree_path_free (path);
638     }
639 }
640
641 static void
642 set_cursor_to_iter (GtkTreeView *view,
643                     GtkTreeIter *iter)
644 {
645   GtkTreeModel *model = gtk_tree_view_get_model (view);
646   GtkTreePath *path = gtk_tree_model_get_path (model, iter);
647   
648   gtk_tree_view_set_cursor (view, path, NULL, FALSE);
649
650   gtk_tree_path_free (path);
651 }
652
653 /* This is called when the list is mapped. Here we scroll to the current
654    font if necessary. */
655 static void
656 gtk_font_selection_scroll_on_map (GtkWidget             *widget,
657                                   gpointer               data)
658 {
659   GtkFontSelection *fontsel;
660   
661 #ifdef FONTSEL_DEBUG
662   g_message ("In expose_list\n");
663 #endif
664   fontsel = GTK_FONT_SELECTION (data);
665   
666   /* Try to scroll the font family list to the selected item */
667   scroll_to_selection (GTK_TREE_VIEW (fontsel->family_list));
668       
669   /* Try to scroll the font family list to the selected item */
670   scroll_to_selection (GTK_TREE_VIEW (fontsel->face_list));
671       
672   /* Try to scroll the font family list to the selected item */
673   scroll_to_selection (GTK_TREE_VIEW (fontsel->size_list));
674 }
675
676 /* This is called when a family is selected in the list. */
677 static void
678 gtk_font_selection_select_font (GtkTreeSelection *selection,
679                                 gpointer          data)
680 {
681   GtkFontSelection *fontsel;
682   GtkTreeModel *model;
683   GtkTreeIter iter;
684 #ifdef INCLUDE_FONT_ENTRIES
685   const gchar *family_name;
686 #endif
687
688   fontsel = GTK_FONT_SELECTION (data);
689
690   if (gtk_tree_selection_get_selected (selection, &model, &iter))
691     {
692       PangoFontFamily *family;
693       
694       gtk_tree_model_get (model, &iter, FAMILY_COLUMN, &family, -1);
695       if (fontsel->family != family)
696         {
697           fontsel->family = family;
698           
699 #ifdef INCLUDE_FONT_ENTRIES
700           family_name = pango_font_family_get_name (fontsel->family);
701           gtk_entry_set_text (GTK_ENTRY (fontsel->font_entry), family_name);
702 #endif
703           
704           gtk_font_selection_show_available_styles (fontsel);
705           gtk_font_selection_select_best_style (fontsel, TRUE);
706         }
707
708       g_object_unref (family);
709     }
710 }
711
712 static int
713 cmp_families (const void *a, const void *b)
714 {
715   const char *a_name = pango_font_family_get_name (*(PangoFontFamily **)a);
716   const char *b_name = pango_font_family_get_name (*(PangoFontFamily **)b);
717   
718   return g_utf8_collate (a_name, b_name);
719 }
720
721 static void
722 gtk_font_selection_show_available_fonts (GtkFontSelection *fontsel)
723 {
724   GtkListStore *model;
725   PangoFontFamily **families;
726   PangoFontFamily *match_family = NULL;
727   gint n_families, i;
728   GtkTreeIter match_row;
729   
730   model = GTK_LIST_STORE (gtk_tree_view_get_model (GTK_TREE_VIEW (fontsel->family_list)));
731   
732   pango_context_list_families (gtk_widget_get_pango_context (GTK_WIDGET (fontsel)),
733                                &families, &n_families);
734   qsort (families, n_families, sizeof (PangoFontFamily *), cmp_families);
735
736   gtk_list_store_clear (model);
737
738   for (i=0; i<n_families; i++)
739     {
740       const gchar *name = pango_font_family_get_name (families[i]);
741       GtkTreeIter iter;
742
743       gtk_list_store_append (model, &iter);
744       gtk_list_store_set (model, &iter,
745                           FAMILY_COLUMN, families[i],
746                           FAMILY_NAME_COLUMN, name,
747                           -1);
748       
749       if (i == 0 || !g_ascii_strcasecmp (name, "sans"))
750         {
751           match_family = families[i];
752           match_row = iter;
753         }
754     }
755
756   fontsel->family = match_family;
757   if (match_family)
758     {
759       set_cursor_to_iter (GTK_TREE_VIEW (fontsel->family_list), &match_row);
760 #ifdef INCLUDE_FONT_ENTRIES
761       gtk_entry_set_text (GTK_ENTRY (fontsel->font_entry), 
762                           pango_font_family_get_name (match_family));
763 #endif /* INCLUDE_FONT_ENTRIES */
764     }
765
766   g_free (families);
767 }
768
769 static int
770 compare_font_descriptions (const PangoFontDescription *a, const PangoFontDescription *b)
771 {
772   int val = strcmp (pango_font_description_get_family (a), pango_font_description_get_family (b));
773   if (val != 0)
774     return val;
775
776   if (pango_font_description_get_weight (a) != pango_font_description_get_weight (b))
777     return pango_font_description_get_weight (a) - pango_font_description_get_weight (b);
778
779   if (pango_font_description_get_style (a) != pango_font_description_get_style (b))
780     return pango_font_description_get_style (a) - pango_font_description_get_style (b);
781   
782   if (pango_font_description_get_stretch (a) != pango_font_description_get_stretch (b))
783     return pango_font_description_get_stretch (a) - pango_font_description_get_stretch (b);
784
785   if (pango_font_description_get_variant (a) != pango_font_description_get_variant (b))
786     return pango_font_description_get_variant (a) - pango_font_description_get_variant (b);
787
788   return 0;
789 }
790
791 static int
792 faces_sort_func (const void *a, const void *b)
793 {
794   PangoFontDescription *desc_a = pango_font_face_describe (*(PangoFontFace **)a);
795   PangoFontDescription *desc_b = pango_font_face_describe (*(PangoFontFace **)b);
796   
797   int ord = compare_font_descriptions (desc_a, desc_b);
798
799   pango_font_description_free (desc_a);
800   pango_font_description_free (desc_b);
801
802   return ord;
803 }
804
805 static gboolean
806 font_description_style_equal (const PangoFontDescription *a,
807                               const PangoFontDescription *b)
808 {
809   return (pango_font_description_get_weight (a) == pango_font_description_get_weight (b) &&
810           pango_font_description_get_style (a) == pango_font_description_get_style (b) &&
811           pango_font_description_get_stretch (a) == pango_font_description_get_stretch (b) &&
812           pango_font_description_get_variant (a) == pango_font_description_get_variant (b));
813 }
814
815 /* This fills the font style list with all the possible style combinations
816    for the current font family. */
817 static void
818 gtk_font_selection_show_available_styles (GtkFontSelection *fontsel)
819 {
820   gint n_faces, i;
821   PangoFontFace **faces;
822   PangoFontDescription *old_desc;
823   GtkListStore *model;
824   GtkTreeIter match_row;
825   PangoFontFace *match_face = NULL;
826   
827   model = GTK_LIST_STORE (gtk_tree_view_get_model (GTK_TREE_VIEW (fontsel->face_list)));
828   
829   if (fontsel->face)
830     old_desc = pango_font_face_describe (fontsel->face);
831   else
832     old_desc= NULL;
833
834   pango_font_family_list_faces (fontsel->family, &faces, &n_faces);
835   qsort (faces, n_faces, sizeof (PangoFontFace *), faces_sort_func);
836
837   gtk_list_store_clear (model);
838
839   for (i=0; i < n_faces; i++)
840     {
841       GtkTreeIter iter;
842       const gchar *str = pango_font_face_get_face_name (faces[i]);
843
844       gtk_list_store_append (model, &iter);
845       gtk_list_store_set (model, &iter,
846                           FACE_COLUMN, faces[i],
847                           FACE_NAME_COLUMN, str,
848                           -1);
849
850       if (i == 0)
851         {
852           match_row = iter;
853           match_face = faces[i];
854         }
855       else if (old_desc)
856         {
857           PangoFontDescription *tmp_desc = pango_font_face_describe (faces[i]);
858           
859           if (font_description_style_equal (tmp_desc, old_desc))
860             {
861               match_row = iter;
862               match_face = faces[i];
863             }
864       
865           pango_font_description_free (tmp_desc);
866         }
867     }
868
869   if (old_desc)
870     pango_font_description_free (old_desc);
871
872   fontsel->face = match_face;
873   if (match_face)
874     {
875 #ifdef INCLUDE_FONT_ENTRIES
876       const gchar *str = pango_font_face_get_face_name (fontsel->face);
877
878       gtk_entry_set_text (GTK_ENTRY (fontsel->font_style_entry), str);
879 #endif      
880       set_cursor_to_iter (GTK_TREE_VIEW (fontsel->face_list), &match_row);
881     }
882
883   g_free (faces);
884 }
885
886 /* This selects a style when the user selects a font. It just uses the first
887    available style at present. I was thinking of trying to maintain the
888    selected style, e.g. bold italic, when the user selects different fonts.
889    However, the interface is so easy to use now I'm not sure it's worth it.
890    Note: This will load a font. */
891 static void
892 gtk_font_selection_select_best_style (GtkFontSelection *fontsel,
893                                       gboolean          use_first)
894 {
895   GtkTreeIter iter;
896   GtkTreeModel *model;
897
898   model = gtk_tree_view_get_model (GTK_TREE_VIEW (fontsel->face_list));
899
900   if (gtk_tree_model_get_iter_first (model, &iter))
901     {
902       set_cursor_to_iter (GTK_TREE_VIEW (fontsel->face_list), &iter);
903       scroll_to_selection (GTK_TREE_VIEW (fontsel->face_list));
904     }
905
906   gtk_font_selection_show_available_sizes (fontsel, FALSE);
907   gtk_font_selection_select_best_size (fontsel);
908 }
909
910
911 /* This is called when a style is selected in the list. */
912 static void
913 gtk_font_selection_select_style (GtkTreeSelection *selection,
914                                  gpointer          data)
915 {
916   GtkFontSelection *fontsel = GTK_FONT_SELECTION (data);
917   GtkTreeModel *model;
918   GtkTreeIter iter;
919   
920   if (gtk_tree_selection_get_selected (selection, &model, &iter))
921     {
922       PangoFontFace *face;
923       
924       gtk_tree_model_get (model, &iter, FACE_COLUMN, &face, -1);
925       fontsel->face = face;
926
927       g_object_unref (face);
928     }
929
930   gtk_font_selection_show_available_sizes (fontsel, FALSE);
931   gtk_font_selection_select_best_size (fontsel);
932 }
933
934 static void
935 gtk_font_selection_show_available_sizes (GtkFontSelection *fontsel,
936                                          gboolean          first_time)
937 {
938   gint i;
939   GtkListStore *model;
940   gchar buffer[128];
941   gchar *p;
942       
943   model = GTK_LIST_STORE (gtk_tree_view_get_model (GTK_TREE_VIEW (fontsel->size_list)));
944
945   /* Insert the standard font sizes */
946   if (first_time)
947     {
948       gtk_list_store_clear (model);
949
950       for (i = 0; i < G_N_ELEMENTS (font_sizes); i++)
951         {
952           GtkTreeIter iter;
953           
954           gtk_list_store_append (model, &iter);
955           gtk_list_store_set (model, &iter, SIZE_COLUMN, font_sizes[i], -1);
956           
957           if (font_sizes[i] * PANGO_SCALE == fontsel->size)
958             set_cursor_to_iter (GTK_TREE_VIEW (fontsel->size_list), &iter);
959         }
960     }
961   else
962     {
963       GtkTreeIter iter;
964       gboolean found = FALSE;
965       
966       gtk_tree_model_get_iter_first (GTK_TREE_MODEL (model), &iter);
967       for (i = 0; i < G_N_ELEMENTS (font_sizes) && !found; i++)
968         {
969           if (font_sizes[i] * PANGO_SCALE == fontsel->size)
970             {
971               set_cursor_to_iter (GTK_TREE_VIEW (fontsel->size_list), &iter);
972               found = TRUE;
973             }
974
975           gtk_tree_model_iter_next (GTK_TREE_MODEL (model), &iter);
976         }
977
978       if (!found)
979         {
980           GtkTreeSelection *selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (fontsel->size_list));
981           gtk_tree_selection_unselect_all (selection);
982         }
983     }
984
985   /* Set the entry to the new size, rounding to 1 digit,
986    * trimming of trailing 0's and a trailing period
987    */
988   g_snprintf (buffer, sizeof (buffer), "%.1f", fontsel->size / (1.0 * PANGO_SCALE));
989   if (strchr (buffer, '.'))
990     {
991       p = buffer + strlen (buffer) - 1;
992       while (*p == '0')
993         p--;
994       if (*p == '.')
995         p--;
996       p[1] = '\0';
997     }
998
999   /* Compare, to avoid moving the cursor unecessarily */
1000   if (strcmp (gtk_entry_get_text (GTK_ENTRY (fontsel->size_entry)), buffer) != 0)
1001     gtk_entry_set_text (GTK_ENTRY (fontsel->size_entry), buffer);
1002 }
1003
1004 static void
1005 gtk_font_selection_select_best_size (GtkFontSelection *fontsel)
1006 {
1007   gtk_font_selection_load_font (fontsel);  
1008 }
1009
1010 static void
1011 gtk_font_selection_set_size (GtkFontSelection *fontsel,
1012                              gint              new_size)
1013 {
1014   if (fontsel->size != new_size)
1015     {
1016       fontsel->size = new_size;
1017
1018       gtk_font_selection_show_available_sizes (fontsel, FALSE);      
1019       gtk_font_selection_load_font (fontsel);
1020     }
1021 }
1022
1023 /* If the user hits return in the font size entry, we change to the new font
1024    size. */
1025 static void
1026 gtk_font_selection_size_activate (GtkWidget   *w,
1027                                   gpointer     data)
1028 {
1029   GtkFontSelection *fontsel;
1030   gint new_size;
1031   const gchar *text;
1032   
1033   fontsel = GTK_FONT_SELECTION (data);
1034
1035   text = gtk_entry_get_text (GTK_ENTRY (fontsel->size_entry));
1036   new_size = MAX (0.1, atof (text) * PANGO_SCALE + 0.5);
1037
1038   if (fontsel->size != new_size)
1039     gtk_font_selection_set_size (fontsel, new_size);
1040   else 
1041     list_row_activated (w);
1042 }
1043
1044 static gboolean
1045 gtk_font_selection_size_focus_out (GtkWidget     *w,
1046                                    GdkEventFocus *event,
1047                                    gpointer       data)
1048 {
1049   GtkFontSelection *fontsel;
1050   gint new_size;
1051   const gchar *text;
1052   
1053   fontsel = GTK_FONT_SELECTION (data);
1054
1055   text = gtk_entry_get_text (GTK_ENTRY (fontsel->size_entry));
1056   new_size = MAX (0.1, atof (text) * PANGO_SCALE + 0.5);
1057
1058   gtk_font_selection_set_size (fontsel, new_size);
1059   
1060   return TRUE;
1061 }
1062
1063 /* This is called when a size is selected in the list. */
1064 static void
1065 gtk_font_selection_select_size (GtkTreeSelection *selection,
1066                                 gpointer          data)
1067 {
1068   GtkFontSelection *fontsel;
1069   GtkTreeModel *model;
1070   GtkTreeIter iter;
1071   gint new_size;
1072   
1073   fontsel = GTK_FONT_SELECTION (data);
1074   
1075   if (gtk_tree_selection_get_selected (selection, &model, &iter))
1076     {
1077       gtk_tree_model_get (model, &iter, SIZE_COLUMN, &new_size, -1);
1078       gtk_font_selection_set_size (fontsel, new_size * PANGO_SCALE);
1079     }
1080 }
1081
1082 static void
1083 gtk_font_selection_load_font (GtkFontSelection *fontsel)
1084 {
1085   if (fontsel->font)
1086     gdk_font_unref (fontsel->font);
1087   fontsel->font = NULL;
1088
1089   gtk_font_selection_update_preview (fontsel);
1090 }
1091
1092 static PangoFontDescription *
1093 gtk_font_selection_get_font_description (GtkFontSelection *fontsel)
1094 {
1095   PangoFontDescription *font_desc;
1096
1097   if (fontsel->face)
1098     {
1099       font_desc = pango_font_face_describe (fontsel->face);
1100       pango_font_description_set_size (font_desc, fontsel->size);
1101     }
1102   else
1103     font_desc = pango_font_description_from_string ("Sans 10");
1104
1105   return font_desc;
1106 }
1107
1108 /* This sets the font in the preview entry to the selected font, and tries to
1109    make sure that the preview entry is a reasonable size, i.e. so that the
1110    text can be seen with a bit of space to spare. But it tries to avoid
1111    resizing the entry every time the font changes.
1112    This also used to shrink the preview if the font size was decreased, but
1113    that made it awkward if the user wanted to resize the window themself. */
1114 static void
1115 gtk_font_selection_update_preview (GtkFontSelection *fontsel)
1116 {
1117   GtkRcStyle *rc_style;
1118   gint new_height;
1119   GtkRequisition old_requisition;
1120   GtkWidget *preview_entry = fontsel->preview_entry;
1121   const gchar *text;
1122
1123   gtk_widget_get_child_requisition (preview_entry, &old_requisition);
1124   
1125   rc_style = gtk_rc_style_new ();
1126   rc_style->font_desc = gtk_font_selection_get_font_description (fontsel);
1127   
1128   gtk_widget_modify_style (preview_entry, rc_style);
1129   gtk_rc_style_unref (rc_style);
1130
1131   gtk_widget_size_request (preview_entry, NULL);
1132   
1133   /* We don't ever want to be over MAX_PREVIEW_HEIGHT pixels high. */
1134   new_height = CLAMP (preview_entry->requisition.height, INITIAL_PREVIEW_HEIGHT, MAX_PREVIEW_HEIGHT);
1135
1136   if (new_height > old_requisition.height || new_height < old_requisition.height - 30)
1137     gtk_widget_set_size_request (preview_entry, -1, new_height);
1138   
1139   /* This sets the preview text, if it hasn't been set already. */
1140   text = gtk_entry_get_text (GTK_ENTRY (preview_entry));
1141   if (strlen (text) == 0)
1142     gtk_entry_set_text (GTK_ENTRY (preview_entry), _(PREVIEW_TEXT));
1143   gtk_editable_set_position (GTK_EDITABLE (preview_entry), 0);
1144 }
1145
1146 static GdkFont*
1147 gtk_font_selection_get_font_internal (GtkFontSelection *fontsel)
1148 {
1149   if (!fontsel->font)
1150     {
1151       PangoFontDescription *font_desc = gtk_font_selection_get_font_description (fontsel);
1152       fontsel->font = gdk_font_from_description_for_display (gtk_widget_get_display (GTK_WIDGET (fontsel)), font_desc);
1153       pango_font_description_free (font_desc);
1154     }
1155   
1156   return fontsel->font;
1157 }
1158
1159
1160 /*****************************************************************************
1161  * These functions are the main public interface for getting/setting the font.
1162  *****************************************************************************/
1163
1164 GdkFont*
1165 gtk_font_selection_get_font (GtkFontSelection *fontsel)
1166 {
1167   return gtk_font_selection_get_font_internal (fontsel);
1168 }
1169
1170 gchar *
1171 gtk_font_selection_get_font_name (GtkFontSelection *fontsel)
1172 {
1173   gchar *result;
1174   
1175   PangoFontDescription *font_desc = gtk_font_selection_get_font_description (fontsel);
1176   result = pango_font_description_to_string (font_desc);
1177   pango_font_description_free (font_desc);
1178
1179   return result;
1180 }
1181
1182
1183 /* This sets the current font, selecting the appropriate list rows.
1184    First we check the fontname is valid and try to find the font family
1185    - i.e. the name in the main list. If we can't find that, then just return.
1186    Next we try to set each of the properties according to the fontname.
1187    Finally we select the font family & style in the lists. */
1188 gboolean
1189 gtk_font_selection_set_font_name (GtkFontSelection *fontsel,
1190                                   const gchar      *fontname)
1191 {
1192   PangoFontFamily *new_family = NULL;
1193   PangoFontFace *new_face = NULL;
1194   PangoFontFace *fallback_face = NULL;
1195   PangoFontDescription *new_desc;
1196   GtkTreeModel *model;
1197   GtkTreeIter iter;
1198   GtkTreeIter match_iter;
1199   gboolean valid;
1200   const gchar *new_family_name;
1201   
1202   g_return_val_if_fail (GTK_IS_FONT_SELECTION (fontsel), FALSE);
1203   
1204   new_desc = pango_font_description_from_string (fontname);
1205   new_family_name = pango_font_description_get_family (new_desc);
1206
1207   if (!new_family_name)
1208     return FALSE;
1209
1210   /* Check to make sure that this is in the list of allowed fonts 
1211    */
1212   model = gtk_tree_view_get_model (GTK_TREE_VIEW (fontsel->family_list));
1213   for (valid = gtk_tree_model_get_iter_first (model, &iter);
1214        valid;
1215        valid = gtk_tree_model_iter_next (model, &iter))
1216     {
1217       PangoFontFamily *family;
1218       
1219       gtk_tree_model_get (model, &iter, FAMILY_COLUMN, &family, -1);
1220       
1221       if (g_ascii_strcasecmp (pango_font_family_get_name (family),
1222                               new_family_name) == 0)
1223         new_family = family;
1224       
1225       g_object_unref (family);
1226       
1227       if (new_family)
1228         break;
1229     }
1230
1231   if (!new_family)
1232     return FALSE;
1233
1234   fontsel->family = new_family;
1235   set_cursor_to_iter (GTK_TREE_VIEW (fontsel->family_list), &iter);
1236   gtk_font_selection_show_available_styles (fontsel);
1237
1238   model = gtk_tree_view_get_model (GTK_TREE_VIEW (fontsel->face_list));
1239   for (valid = gtk_tree_model_get_iter_first (model, &iter);
1240        valid;
1241        valid = gtk_tree_model_iter_next (model, &iter))
1242     {
1243       PangoFontFace *face;
1244       PangoFontDescription *tmp_desc;
1245       
1246       gtk_tree_model_get (model, &iter, FACE_COLUMN, &face, -1);
1247       tmp_desc = pango_font_face_describe (face);
1248       
1249       if (font_description_style_equal (tmp_desc, new_desc))
1250         new_face = face;
1251       
1252       if (!fallback_face)
1253         {
1254           fallback_face = face;
1255           match_iter = iter;
1256         }
1257       
1258       pango_font_description_free (tmp_desc);
1259       g_object_unref (face);
1260       
1261       if (new_face)
1262         {
1263           match_iter = iter;
1264           break;
1265         }
1266     }
1267
1268   if (!new_face)
1269     new_face = fallback_face;
1270
1271   fontsel->face = new_face;
1272   set_cursor_to_iter (GTK_TREE_VIEW (fontsel->face_list), &match_iter);  
1273
1274   gtk_font_selection_set_size (fontsel, pango_font_description_get_size (new_desc));
1275   
1276   g_object_freeze_notify (G_OBJECT (fontsel));
1277   g_object_notify (G_OBJECT (fontsel), "font_name");
1278   g_object_notify (G_OBJECT (fontsel), "font");
1279   g_object_thaw_notify (G_OBJECT (fontsel));
1280
1281   pango_font_description_free (new_desc);
1282
1283   return TRUE;
1284 }
1285
1286
1287 /* This returns the text in the preview entry. You should copy the returned
1288    text if you need it. */
1289 G_CONST_RETURN gchar*
1290 gtk_font_selection_get_preview_text  (GtkFontSelection *fontsel)
1291 {
1292   return gtk_entry_get_text (GTK_ENTRY (fontsel->preview_entry));
1293 }
1294
1295
1296 /* This sets the text in the preview entry. */
1297 void
1298 gtk_font_selection_set_preview_text  (GtkFontSelection *fontsel,
1299                                       const gchar         *text)
1300 {
1301   gtk_entry_set_text (GTK_ENTRY (fontsel->preview_entry), text);
1302 }
1303
1304 /*****************************************************************************
1305  * GtkFontSelectionDialog
1306  *****************************************************************************/
1307
1308 GType
1309 gtk_font_selection_dialog_get_type (void)
1310 {
1311   static GType font_selection_dialog_type = 0;
1312   
1313   if (!font_selection_dialog_type)
1314     {
1315       static const GTypeInfo fontsel_diag_info =
1316       {
1317         sizeof (GtkFontSelectionDialogClass),
1318         NULL,           /* base_init */
1319         NULL,           /* base_finalize */
1320         (GClassInitFunc) gtk_font_selection_dialog_class_init,
1321         NULL,           /* class_finalize */
1322         NULL,           /* class_data */
1323         sizeof (GtkFontSelectionDialog),
1324         0,              /* n_preallocs */
1325         (GInstanceInitFunc) gtk_font_selection_dialog_init,
1326       };
1327       
1328       font_selection_dialog_type =
1329         g_type_register_static (GTK_TYPE_DIALOG, I_("GtkFontSelectionDialog"),
1330                                 &fontsel_diag_info, 0);
1331     }
1332   
1333   return font_selection_dialog_type;
1334 }
1335
1336 static void
1337 gtk_font_selection_dialog_class_init (GtkFontSelectionDialogClass *klass)
1338 {
1339   font_selection_dialog_parent_class = g_type_class_peek_parent (klass);
1340 }
1341
1342 static void
1343 gtk_font_selection_dialog_init (GtkFontSelectionDialog *fontseldiag)
1344 {
1345   GtkDialog *dialog;
1346
1347   gtk_widget_push_composite_child ();
1348
1349   dialog = GTK_DIALOG (fontseldiag);
1350   
1351   gtk_container_set_border_width (GTK_CONTAINER (fontseldiag), 4);
1352   gtk_window_set_resizable (GTK_WINDOW (fontseldiag), TRUE);
1353   
1354   fontseldiag->main_vbox = dialog->vbox;
1355   
1356   fontseldiag->fontsel = gtk_font_selection_new ();
1357   gtk_container_set_border_width (GTK_CONTAINER (fontseldiag->fontsel), 4);
1358   gtk_widget_show (fontseldiag->fontsel);
1359   gtk_box_pack_start (GTK_BOX (fontseldiag->main_vbox),
1360                       fontseldiag->fontsel, TRUE, TRUE, 0);
1361   
1362   /* Create the action area */
1363   fontseldiag->action_area = dialog->action_area;
1364
1365   fontseldiag->cancel_button = gtk_dialog_add_button (dialog,
1366                                                       GTK_STOCK_CANCEL,
1367                                                       GTK_RESPONSE_CANCEL);
1368
1369   fontseldiag->apply_button = gtk_dialog_add_button (dialog,
1370                                                      GTK_STOCK_APPLY,
1371                                                      GTK_RESPONSE_APPLY);
1372   gtk_widget_hide (fontseldiag->apply_button);
1373
1374   fontseldiag->ok_button = gtk_dialog_add_button (dialog,
1375                                                   GTK_STOCK_OK,
1376                                                   GTK_RESPONSE_OK);
1377   gtk_widget_grab_default (fontseldiag->ok_button);
1378   
1379   gtk_dialog_set_alternative_button_order (GTK_DIALOG (fontseldiag),
1380                                            GTK_RESPONSE_OK,
1381                                            GTK_RESPONSE_APPLY,
1382                                            GTK_RESPONSE_CANCEL,
1383                                            -1);
1384
1385
1386   gtk_window_set_title (GTK_WINDOW (fontseldiag),
1387                         _("Font Selection"));
1388
1389   gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE);
1390   
1391   gtk_widget_pop_composite_child ();
1392 }
1393
1394 GtkWidget*
1395 gtk_font_selection_dialog_new (const gchar *title)
1396 {
1397   GtkFontSelectionDialog *fontseldiag;
1398   
1399   fontseldiag = g_object_new (GTK_TYPE_FONT_SELECTION_DIALOG, NULL);
1400
1401   if (title)
1402     gtk_window_set_title (GTK_WINDOW (fontseldiag), title);
1403   
1404   return GTK_WIDGET (fontseldiag);
1405 }
1406
1407 gchar*
1408 gtk_font_selection_dialog_get_font_name (GtkFontSelectionDialog *fsd)
1409 {
1410   return gtk_font_selection_get_font_name (GTK_FONT_SELECTION (fsd->fontsel));
1411 }
1412
1413 GdkFont*
1414 gtk_font_selection_dialog_get_font (GtkFontSelectionDialog *fsd)
1415 {
1416   return gtk_font_selection_get_font (GTK_FONT_SELECTION (fsd->fontsel));
1417 }
1418
1419 gboolean
1420 gtk_font_selection_dialog_set_font_name (GtkFontSelectionDialog *fsd,
1421                                          const gchar      *fontname)
1422 {
1423   return gtk_font_selection_set_font_name (GTK_FONT_SELECTION (fsd->fontsel), fontname);
1424 }
1425
1426 G_CONST_RETURN gchar*
1427 gtk_font_selection_dialog_get_preview_text (GtkFontSelectionDialog *fsd)
1428 {
1429   return gtk_font_selection_get_preview_text (GTK_FONT_SELECTION (fsd->fontsel));
1430 }
1431
1432 void
1433 gtk_font_selection_dialog_set_preview_text (GtkFontSelectionDialog *fsd,
1434                                             const gchar            *text)
1435 {
1436   gtk_font_selection_set_preview_text (GTK_FONT_SELECTION (fsd->fontsel), text);
1437 }
1438
1439 #define __GTK_FONTSEL_C__
1440 #include "gtkaliasdef.c"