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