]> Pileus Git - ~andy/gtk/blob - gtk/gtkfontsel.c
Intern some more strings.
[~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   const gchar *family_name;
685   
686   fontsel = GTK_FONT_SELECTION (data);
687
688   if (gtk_tree_selection_get_selected (selection, &model, &iter))
689     {
690       PangoFontFamily *family;
691       
692       gtk_tree_model_get (model, &iter, FAMILY_COLUMN, &family, -1);
693       if (fontsel->family != family)
694         {
695           fontsel->family = family;
696           
697           family_name = pango_font_family_get_name (fontsel->family);
698           
699 #ifdef INCLUDE_FONT_ENTRIES
700           gtk_entry_set_text (GTK_ENTRY (fontsel->font_entry), family_name);
701 #endif
702           
703           gtk_font_selection_show_available_styles (fontsel);
704           gtk_font_selection_select_best_style (fontsel, TRUE);
705         }
706
707       g_object_unref (family);
708     }
709 }
710
711 static int
712 cmp_families (const void *a, const void *b)
713 {
714   const char *a_name = pango_font_family_get_name (*(PangoFontFamily **)a);
715   const char *b_name = pango_font_family_get_name (*(PangoFontFamily **)b);
716   
717   return g_utf8_collate (a_name, b_name);
718 }
719
720 static void
721 gtk_font_selection_show_available_fonts (GtkFontSelection *fontsel)
722 {
723   GtkListStore *model;
724   PangoFontFamily **families;
725   PangoFontFamily *match_family = NULL;
726   gint n_families, i;
727   GtkTreeIter match_row;
728   
729   model = GTK_LIST_STORE (gtk_tree_view_get_model (GTK_TREE_VIEW (fontsel->family_list)));
730   
731   pango_context_list_families (gtk_widget_get_pango_context (GTK_WIDGET (fontsel)),
732                                &families, &n_families);
733   qsort (families, n_families, sizeof (PangoFontFamily *), cmp_families);
734
735   gtk_list_store_clear (model);
736
737   for (i=0; i<n_families; i++)
738     {
739       const gchar *name = pango_font_family_get_name (families[i]);
740       GtkTreeIter iter;
741
742       gtk_list_store_append (model, &iter);
743       gtk_list_store_set (model, &iter,
744                           FAMILY_COLUMN, families[i],
745                           FAMILY_NAME_COLUMN, name,
746                           -1);
747       
748       if (i == 0 || !g_ascii_strcasecmp (name, "sans"))
749         {
750           match_family = families[i];
751           match_row = iter;
752         }
753     }
754
755   fontsel->family = match_family;
756   if (match_family)
757     {
758       set_cursor_to_iter (GTK_TREE_VIEW (fontsel->family_list), &match_row);
759 #ifdef INCLUDE_FONT_ENTRIES
760       gtk_entry_set_text (GTK_ENTRY (fontsel->font_entry), 
761                           pango_font_family_get_name (match_family));
762 #endif /* INCLUDE_FONT_ENTRIES */
763     }
764
765   g_free (families);
766 }
767
768 static int
769 compare_font_descriptions (const PangoFontDescription *a, const PangoFontDescription *b)
770 {
771   int val = strcmp (pango_font_description_get_family (a), pango_font_description_get_family (b));
772   if (val != 0)
773     return val;
774
775   if (pango_font_description_get_weight (a) != pango_font_description_get_weight (b))
776     return pango_font_description_get_weight (a) - pango_font_description_get_weight (b);
777
778   if (pango_font_description_get_style (a) != pango_font_description_get_style (b))
779     return pango_font_description_get_style (a) - pango_font_description_get_style (b);
780   
781   if (pango_font_description_get_stretch (a) != pango_font_description_get_stretch (b))
782     return pango_font_description_get_stretch (a) - pango_font_description_get_stretch (b);
783
784   if (pango_font_description_get_variant (a) != pango_font_description_get_variant (b))
785     return pango_font_description_get_variant (a) - pango_font_description_get_variant (b);
786
787   return 0;
788 }
789
790 static int
791 faces_sort_func (const void *a, const void *b)
792 {
793   PangoFontDescription *desc_a = pango_font_face_describe (*(PangoFontFace **)a);
794   PangoFontDescription *desc_b = pango_font_face_describe (*(PangoFontFace **)b);
795   
796   int ord = compare_font_descriptions (desc_a, desc_b);
797
798   pango_font_description_free (desc_a);
799   pango_font_description_free (desc_b);
800
801   return ord;
802 }
803
804 static gboolean
805 font_description_style_equal (const PangoFontDescription *a,
806                               const PangoFontDescription *b)
807 {
808   return (pango_font_description_get_weight (a) == pango_font_description_get_weight (b) &&
809           pango_font_description_get_style (a) == pango_font_description_get_style (b) &&
810           pango_font_description_get_stretch (a) == pango_font_description_get_stretch (b) &&
811           pango_font_description_get_variant (a) == pango_font_description_get_variant (b));
812 }
813
814 /* This fills the font style list with all the possible style combinations
815    for the current font family. */
816 static void
817 gtk_font_selection_show_available_styles (GtkFontSelection *fontsel)
818 {
819   gint n_faces, i;
820   PangoFontFace **faces;
821   PangoFontDescription *old_desc;
822   GtkListStore *model;
823   GtkTreeIter match_row;
824   PangoFontFace *match_face = NULL;
825   
826   model = GTK_LIST_STORE (gtk_tree_view_get_model (GTK_TREE_VIEW (fontsel->face_list)));
827   
828   if (fontsel->face)
829     old_desc = pango_font_face_describe (fontsel->face);
830   else
831     old_desc= NULL;
832
833   pango_font_family_list_faces (fontsel->family, &faces, &n_faces);
834   qsort (faces, n_faces, sizeof (PangoFontFace *), faces_sort_func);
835
836   gtk_list_store_clear (model);
837
838   for (i=0; i < n_faces; i++)
839     {
840       GtkTreeIter iter;
841       const gchar *str = pango_font_face_get_face_name (faces[i]);
842
843       gtk_list_store_append (model, &iter);
844       gtk_list_store_set (model, &iter,
845                           FACE_COLUMN, faces[i],
846                           FACE_NAME_COLUMN, str,
847                           -1);
848
849       if (i == 0)
850         {
851           match_row = iter;
852           match_face = faces[i];
853         }
854       else if (old_desc)
855         {
856           PangoFontDescription *tmp_desc = pango_font_face_describe (faces[i]);
857           
858           if (font_description_style_equal (tmp_desc, old_desc))
859             {
860               match_row = iter;
861               match_face = faces[i];
862             }
863       
864           pango_font_description_free (tmp_desc);
865         }
866     }
867
868   if (old_desc)
869     pango_font_description_free (old_desc);
870
871   fontsel->face = match_face;
872   if (match_face)
873     {
874 #ifdef INCLUDE_FONT_ENTRIES
875       const gchar *str = pango_font_face_get_face_name (fontsel->face);
876
877       gtk_entry_set_text (GTK_ENTRY (fontsel->font_style_entry), str);
878 #endif      
879       set_cursor_to_iter (GTK_TREE_VIEW (fontsel->face_list), &match_row);
880     }
881
882   g_free (faces);
883 }
884
885 /* This selects a style when the user selects a font. It just uses the first
886    available style at present. I was thinking of trying to maintain the
887    selected style, e.g. bold italic, when the user selects different fonts.
888    However, the interface is so easy to use now I'm not sure it's worth it.
889    Note: This will load a font. */
890 static void
891 gtk_font_selection_select_best_style (GtkFontSelection *fontsel,
892                                       gboolean          use_first)
893 {
894   GtkTreeIter iter;
895   GtkTreeModel *model;
896
897   model = gtk_tree_view_get_model (GTK_TREE_VIEW (fontsel->face_list));
898
899   if (gtk_tree_model_get_iter_first (model, &iter))
900     {
901       set_cursor_to_iter (GTK_TREE_VIEW (fontsel->face_list), &iter);
902       scroll_to_selection (GTK_TREE_VIEW (fontsel->face_list));
903     }
904
905   gtk_font_selection_show_available_sizes (fontsel, FALSE);
906   gtk_font_selection_select_best_size (fontsel);
907 }
908
909
910 /* This is called when a style is selected in the list. */
911 static void
912 gtk_font_selection_select_style (GtkTreeSelection *selection,
913                                  gpointer          data)
914 {
915   GtkFontSelection *fontsel = GTK_FONT_SELECTION (data);
916   GtkTreeModel *model;
917   GtkTreeIter iter;
918   
919   if (gtk_tree_selection_get_selected (selection, &model, &iter))
920     {
921       PangoFontFace *face;
922       
923       gtk_tree_model_get (model, &iter, FACE_COLUMN, &face, -1);
924       fontsel->face = face;
925
926       g_object_unref (face);
927     }
928
929   gtk_font_selection_show_available_sizes (fontsel, FALSE);
930   gtk_font_selection_select_best_size (fontsel);
931 }
932
933 static void
934 gtk_font_selection_show_available_sizes (GtkFontSelection *fontsel,
935                                          gboolean          first_time)
936 {
937   gint i;
938   GtkListStore *model;
939   GtkTreeSelection *selection;
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   selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (fontsel->size_list));
945
946   /* Insert the standard font sizes */
947   if (first_time)
948     {
949       gtk_list_store_clear (model);
950
951       for (i = 0; i < G_N_ELEMENTS (font_sizes); i++)
952         {
953           GtkTreeIter iter;
954           
955           gtk_list_store_append (model, &iter);
956           gtk_list_store_set (model, &iter, SIZE_COLUMN, font_sizes[i], -1);
957           
958           if (font_sizes[i] * PANGO_SCALE == fontsel->size)
959             set_cursor_to_iter (GTK_TREE_VIEW (fontsel->size_list), &iter);
960         }
961     }
962   else
963     {
964       GtkTreeIter iter;
965       gboolean found = FALSE;
966       
967       gtk_tree_model_get_iter_first (GTK_TREE_MODEL (model), &iter);
968       for (i = 0; i < G_N_ELEMENTS (font_sizes) && !found; i++)
969         {
970           if (font_sizes[i] * PANGO_SCALE == fontsel->size)
971             {
972               set_cursor_to_iter (GTK_TREE_VIEW (fontsel->size_list), &iter);
973               found = TRUE;
974             }
975
976           gtk_tree_model_iter_next (GTK_TREE_MODEL (model), &iter);
977         }
978
979       if (!found)
980         {
981           GtkTreeSelection *selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (fontsel->size_list));
982           gtk_tree_selection_unselect_all (selection);
983         }
984     }
985
986   /* Set the entry to the new size, rounding to 1 digit,
987    * trimming of trailing 0's and a trailing period
988    */
989   g_snprintf (buffer, sizeof (buffer), "%.1f", fontsel->size / (1.0 * PANGO_SCALE));
990   if (strchr (buffer, '.'))
991     {
992       p = buffer + strlen (buffer) - 1;
993       while (*p == '0')
994         p--;
995       if (*p == '.')
996         p--;
997       p[1] = '\0';
998     }
999
1000   /* Compare, to avoid moving the cursor unecessarily */
1001   if (strcmp (gtk_entry_get_text (GTK_ENTRY (fontsel->size_entry)), buffer) != 0)
1002     gtk_entry_set_text (GTK_ENTRY (fontsel->size_entry), buffer);
1003 }
1004
1005 static void
1006 gtk_font_selection_select_best_size (GtkFontSelection *fontsel)
1007 {
1008   gtk_font_selection_load_font (fontsel);  
1009 }
1010
1011 static void
1012 gtk_font_selection_set_size (GtkFontSelection *fontsel,
1013                              gint              new_size)
1014 {
1015   if (fontsel->size != new_size)
1016     {
1017       fontsel->size = new_size;
1018
1019       gtk_font_selection_show_available_sizes (fontsel, FALSE);      
1020       gtk_font_selection_load_font (fontsel);
1021     }
1022 }
1023
1024 /* If the user hits return in the font size entry, we change to the new font
1025    size. */
1026 static void
1027 gtk_font_selection_size_activate (GtkWidget   *w,
1028                                   gpointer     data)
1029 {
1030   GtkFontSelection *fontsel;
1031   gint new_size;
1032   const gchar *text;
1033   
1034   fontsel = GTK_FONT_SELECTION (data);
1035
1036   text = gtk_entry_get_text (GTK_ENTRY (fontsel->size_entry));
1037   new_size = MAX (0.1, atof (text) * PANGO_SCALE + 0.5);
1038
1039   if (fontsel->size != new_size)
1040     gtk_font_selection_set_size (fontsel, new_size);
1041   else 
1042     list_row_activated (w);
1043 }
1044
1045 static gboolean
1046 gtk_font_selection_size_focus_out (GtkWidget     *w,
1047                                    GdkEventFocus *event,
1048                                    gpointer       data)
1049 {
1050   GtkFontSelection *fontsel;
1051   gint new_size;
1052   const gchar *text;
1053   
1054   fontsel = GTK_FONT_SELECTION (data);
1055
1056   text = gtk_entry_get_text (GTK_ENTRY (fontsel->size_entry));
1057   new_size = MAX (0.1, atof (text) * PANGO_SCALE + 0.5);
1058
1059   gtk_font_selection_set_size (fontsel, new_size);
1060   
1061   return TRUE;
1062 }
1063
1064 /* This is called when a size is selected in the list. */
1065 static void
1066 gtk_font_selection_select_size (GtkTreeSelection *selection,
1067                                 gpointer          data)
1068 {
1069   GtkFontSelection *fontsel;
1070   GtkTreeModel *model;
1071   GtkTreeIter iter;
1072   gint new_size;
1073   
1074   fontsel = GTK_FONT_SELECTION (data);
1075   
1076   if (gtk_tree_selection_get_selected (selection, &model, &iter))
1077     {
1078       gtk_tree_model_get (model, &iter, SIZE_COLUMN, &new_size, -1);
1079       gtk_font_selection_set_size (fontsel, new_size * PANGO_SCALE);
1080     }
1081 }
1082
1083 static void
1084 gtk_font_selection_load_font (GtkFontSelection *fontsel)
1085 {
1086   if (fontsel->font)
1087     gdk_font_unref (fontsel->font);
1088   fontsel->font = NULL;
1089
1090   gtk_font_selection_update_preview (fontsel);
1091 }
1092
1093 static PangoFontDescription *
1094 gtk_font_selection_get_font_description (GtkFontSelection *fontsel)
1095 {
1096   PangoFontDescription *font_desc;
1097
1098   if (fontsel->face)
1099     {
1100       font_desc = pango_font_face_describe (fontsel->face);
1101       pango_font_description_set_size (font_desc, fontsel->size);
1102     }
1103   else
1104     font_desc = pango_font_description_from_string ("Sans 10");
1105
1106   return font_desc;
1107 }
1108
1109 /* This sets the font in the preview entry to the selected font, and tries to
1110    make sure that the preview entry is a reasonable size, i.e. so that the
1111    text can be seen with a bit of space to spare. But it tries to avoid
1112    resizing the entry every time the font changes.
1113    This also used to shrink the preview if the font size was decreased, but
1114    that made it awkward if the user wanted to resize the window themself. */
1115 static void
1116 gtk_font_selection_update_preview (GtkFontSelection *fontsel)
1117 {
1118   GtkRcStyle *rc_style;
1119   gint new_height;
1120   GtkRequisition old_requisition;
1121   GtkWidget *preview_entry = fontsel->preview_entry;
1122   const gchar *text;
1123
1124   gtk_widget_get_child_requisition (preview_entry, &old_requisition);
1125   
1126   rc_style = gtk_rc_style_new ();
1127   rc_style->font_desc = gtk_font_selection_get_font_description (fontsel);
1128   
1129   gtk_widget_modify_style (preview_entry, rc_style);
1130   gtk_rc_style_unref (rc_style);
1131
1132   gtk_widget_size_request (preview_entry, NULL);
1133   
1134   /* We don't ever want to be over MAX_PREVIEW_HEIGHT pixels high. */
1135   new_height = CLAMP (preview_entry->requisition.height, INITIAL_PREVIEW_HEIGHT, MAX_PREVIEW_HEIGHT);
1136
1137   if (new_height > old_requisition.height || new_height < old_requisition.height - 30)
1138     gtk_widget_set_size_request (preview_entry, -1, new_height);
1139   
1140   /* This sets the preview text, if it hasn't been set already. */
1141   text = gtk_entry_get_text (GTK_ENTRY (preview_entry));
1142   if (strlen (text) == 0)
1143     gtk_entry_set_text (GTK_ENTRY (preview_entry), _(PREVIEW_TEXT));
1144   gtk_editable_set_position (GTK_EDITABLE (preview_entry), 0);
1145 }
1146
1147 static GdkFont*
1148 gtk_font_selection_get_font_internal (GtkFontSelection *fontsel)
1149 {
1150   if (!fontsel->font)
1151     {
1152       PangoFontDescription *font_desc = gtk_font_selection_get_font_description (fontsel);
1153       fontsel->font = gdk_font_from_description_for_display (gtk_widget_get_display (GTK_WIDGET (fontsel)), font_desc);
1154       pango_font_description_free (font_desc);
1155     }
1156   
1157   return fontsel->font;
1158 }
1159
1160
1161 /*****************************************************************************
1162  * These functions are the main public interface for getting/setting the font.
1163  *****************************************************************************/
1164
1165 GdkFont*
1166 gtk_font_selection_get_font (GtkFontSelection *fontsel)
1167 {
1168   return gtk_font_selection_get_font_internal (fontsel);
1169 }
1170
1171 gchar *
1172 gtk_font_selection_get_font_name (GtkFontSelection *fontsel)
1173 {
1174   gchar *result;
1175   
1176   PangoFontDescription *font_desc = gtk_font_selection_get_font_description (fontsel);
1177   result = pango_font_description_to_string (font_desc);
1178   pango_font_description_free (font_desc);
1179
1180   return result;
1181 }
1182
1183
1184 /* This sets the current font, selecting the appropriate list rows.
1185    First we check the fontname is valid and try to find the font family
1186    - i.e. the name in the main list. If we can't find that, then just return.
1187    Next we try to set each of the properties according to the fontname.
1188    Finally we select the font family & style in the lists. */
1189 gboolean
1190 gtk_font_selection_set_font_name (GtkFontSelection *fontsel,
1191                                   const gchar      *fontname)
1192 {
1193   PangoFontFamily *new_family = NULL;
1194   PangoFontFace *new_face = NULL;
1195   PangoFontFace *fallback_face = NULL;
1196   PangoFontDescription *new_desc;
1197   GtkTreeModel *model;
1198   GtkTreeIter iter;
1199   GtkTreeIter match_iter;
1200   gboolean valid;
1201   
1202   g_return_val_if_fail (GTK_IS_FONT_SELECTION (fontsel), FALSE);
1203   
1204   new_desc = pango_font_description_from_string (fontname);
1205
1206   /* Check to make sure that this is in the list of allowed fonts */
1207
1208   model = gtk_tree_view_get_model (GTK_TREE_VIEW (fontsel->family_list));
1209   for (valid = gtk_tree_model_get_iter_first (model, &iter);
1210        valid;
1211        valid = gtk_tree_model_iter_next (model, &iter))
1212     {
1213       PangoFontFamily *family;
1214       
1215       gtk_tree_model_get (model, &iter, FAMILY_COLUMN, &family, -1);
1216       
1217       if (g_ascii_strcasecmp (pango_font_family_get_name (family),
1218                               pango_font_description_get_family (new_desc)) == 0)
1219         new_family = family;
1220       
1221       g_object_unref (family);
1222       
1223       if (new_family)
1224         break;
1225     }
1226
1227   if (!new_family)
1228     return FALSE;
1229
1230   fontsel->family = new_family;
1231   set_cursor_to_iter (GTK_TREE_VIEW (fontsel->family_list), &iter);
1232   gtk_font_selection_show_available_styles (fontsel);
1233
1234   model = gtk_tree_view_get_model (GTK_TREE_VIEW (fontsel->face_list));
1235   for (valid = gtk_tree_model_get_iter_first (model, &iter);
1236        valid;
1237        valid = gtk_tree_model_iter_next (model, &iter))
1238     {
1239       PangoFontFace *face;
1240       PangoFontDescription *tmp_desc;
1241       
1242       gtk_tree_model_get (model, &iter, FACE_COLUMN, &face, -1);
1243       tmp_desc = pango_font_face_describe (face);
1244       
1245       if (font_description_style_equal (tmp_desc, new_desc))
1246         new_face = face;
1247       
1248       if (!fallback_face)
1249         {
1250           fallback_face = face;
1251           match_iter = iter;
1252         }
1253       
1254       pango_font_description_free (tmp_desc);
1255       g_object_unref (face);
1256       
1257       if (new_face)
1258         {
1259           match_iter = iter;
1260           break;
1261         }
1262     }
1263
1264   if (!new_face)
1265     new_face = fallback_face;
1266
1267   fontsel->face = new_face;
1268   set_cursor_to_iter (GTK_TREE_VIEW (fontsel->face_list), &match_iter);  
1269
1270   gtk_font_selection_set_size (fontsel, pango_font_description_get_size (new_desc));
1271   
1272   g_object_freeze_notify (G_OBJECT (fontsel));
1273   g_object_notify (G_OBJECT (fontsel), "font_name");
1274   g_object_notify (G_OBJECT (fontsel), "font");
1275   g_object_thaw_notify (G_OBJECT (fontsel));
1276
1277   pango_font_description_free (new_desc);
1278
1279   return TRUE;
1280 }
1281
1282
1283 /* This returns the text in the preview entry. You should copy the returned
1284    text if you need it. */
1285 G_CONST_RETURN gchar*
1286 gtk_font_selection_get_preview_text  (GtkFontSelection *fontsel)
1287 {
1288   return gtk_entry_get_text (GTK_ENTRY (fontsel->preview_entry));
1289 }
1290
1291
1292 /* This sets the text in the preview entry. */
1293 void
1294 gtk_font_selection_set_preview_text  (GtkFontSelection *fontsel,
1295                                       const gchar         *text)
1296 {
1297   gtk_entry_set_text (GTK_ENTRY (fontsel->preview_entry), text);
1298 }
1299
1300 /*****************************************************************************
1301  * GtkFontSelectionDialog
1302  *****************************************************************************/
1303
1304 GType
1305 gtk_font_selection_dialog_get_type (void)
1306 {
1307   static GType font_selection_dialog_type = 0;
1308   
1309   if (!font_selection_dialog_type)
1310     {
1311       static const GTypeInfo fontsel_diag_info =
1312       {
1313         sizeof (GtkFontSelectionDialogClass),
1314         NULL,           /* base_init */
1315         NULL,           /* base_finalize */
1316         (GClassInitFunc) gtk_font_selection_dialog_class_init,
1317         NULL,           /* class_finalize */
1318         NULL,           /* class_data */
1319         sizeof (GtkFontSelectionDialog),
1320         0,              /* n_preallocs */
1321         (GInstanceInitFunc) gtk_font_selection_dialog_init,
1322       };
1323       
1324       font_selection_dialog_type =
1325         g_type_register_static (GTK_TYPE_DIALOG, I_("GtkFontSelectionDialog"),
1326                                 &fontsel_diag_info, 0);
1327     }
1328   
1329   return font_selection_dialog_type;
1330 }
1331
1332 static void
1333 gtk_font_selection_dialog_class_init (GtkFontSelectionDialogClass *klass)
1334 {
1335   font_selection_dialog_parent_class = g_type_class_peek_parent (klass);
1336 }
1337
1338 static void
1339 gtk_font_selection_dialog_init (GtkFontSelectionDialog *fontseldiag)
1340 {
1341   GtkDialog *dialog;
1342
1343   gtk_widget_push_composite_child ();
1344
1345   dialog = GTK_DIALOG (fontseldiag);
1346   
1347   gtk_container_set_border_width (GTK_CONTAINER (fontseldiag), 4);
1348   gtk_window_set_resizable (GTK_WINDOW (fontseldiag), TRUE);
1349   
1350   fontseldiag->main_vbox = dialog->vbox;
1351   
1352   fontseldiag->fontsel = gtk_font_selection_new ();
1353   gtk_container_set_border_width (GTK_CONTAINER (fontseldiag->fontsel), 4);
1354   gtk_widget_show (fontseldiag->fontsel);
1355   gtk_box_pack_start (GTK_BOX (fontseldiag->main_vbox),
1356                       fontseldiag->fontsel, TRUE, TRUE, 0);
1357   
1358   /* Create the action area */
1359   fontseldiag->action_area = dialog->action_area;
1360
1361   fontseldiag->cancel_button = gtk_dialog_add_button (dialog,
1362                                                       GTK_STOCK_CANCEL,
1363                                                       GTK_RESPONSE_CANCEL);
1364
1365   fontseldiag->apply_button = gtk_dialog_add_button (dialog,
1366                                                      GTK_STOCK_APPLY,
1367                                                      GTK_RESPONSE_APPLY);
1368   gtk_widget_hide (fontseldiag->apply_button);
1369
1370   fontseldiag->ok_button = gtk_dialog_add_button (dialog,
1371                                                   GTK_STOCK_OK,
1372                                                   GTK_RESPONSE_OK);
1373   gtk_widget_grab_default (fontseldiag->ok_button);
1374   
1375   gtk_dialog_set_alternative_button_order (GTK_DIALOG (fontseldiag),
1376                                            GTK_RESPONSE_OK,
1377                                            GTK_RESPONSE_APPLY,
1378                                            GTK_RESPONSE_CANCEL,
1379                                            -1);
1380
1381
1382   gtk_window_set_title (GTK_WINDOW (fontseldiag),
1383                         _("Font Selection"));
1384
1385   gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE);
1386   
1387   gtk_widget_pop_composite_child ();
1388 }
1389
1390 GtkWidget*
1391 gtk_font_selection_dialog_new (const gchar *title)
1392 {
1393   GtkFontSelectionDialog *fontseldiag;
1394   
1395   fontseldiag = g_object_new (GTK_TYPE_FONT_SELECTION_DIALOG, NULL);
1396
1397   if (title)
1398     gtk_window_set_title (GTK_WINDOW (fontseldiag), title);
1399   
1400   return GTK_WIDGET (fontseldiag);
1401 }
1402
1403 gchar*
1404 gtk_font_selection_dialog_get_font_name (GtkFontSelectionDialog *fsd)
1405 {
1406   return gtk_font_selection_get_font_name (GTK_FONT_SELECTION (fsd->fontsel));
1407 }
1408
1409 GdkFont*
1410 gtk_font_selection_dialog_get_font (GtkFontSelectionDialog *fsd)
1411 {
1412   return gtk_font_selection_get_font (GTK_FONT_SELECTION (fsd->fontsel));
1413 }
1414
1415 gboolean
1416 gtk_font_selection_dialog_set_font_name (GtkFontSelectionDialog *fsd,
1417                                          const gchar      *fontname)
1418 {
1419   return gtk_font_selection_set_font_name (GTK_FONT_SELECTION (fsd->fontsel), fontname);
1420 }
1421
1422 G_CONST_RETURN gchar*
1423 gtk_font_selection_dialog_get_preview_text (GtkFontSelectionDialog *fsd)
1424 {
1425   return gtk_font_selection_get_preview_text (GTK_FONT_SELECTION (fsd->fontsel));
1426 }
1427
1428 void
1429 gtk_font_selection_dialog_set_preview_text (GtkFontSelectionDialog *fsd,
1430                                             const gchar            *text)
1431 {
1432   gtk_font_selection_set_preview_text (GTK_FONT_SELECTION (fsd->fontsel), text);
1433 }
1434
1435 #define __GTK_FONTSEL_C__
1436 #include "gtkaliasdef.c"