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