1 /* GTK - The GIMP Toolkit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
4 * GtkFontSelection widget for Gtk+, by Damon Chaplin, May 1998.
5 * Based on the GnomeFontSelector widget, by Elliot Lee, but major changes.
6 * The GnomeFontSelector was derived from app/text_tool.c in the GIMP.
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Library General Public License for more details.
18 * You should have received a copy of the GNU Library General Public
19 * License along with this library; if not, write to the
20 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21 * Boston, MA 02111-1307, USA.
25 * Modified by the GTK+ Team and others 1997-1999. See the AUTHORS
26 * file for a list of people on the GTK+ Team. See the ChangeLog
27 * files for a list of changes. These files are distributed with
28 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
34 * Fontnames - A maximum of MAX_FONTS (32767) fontnames will be retrieved
35 * from X Windows with XListFonts(). Any more are ignored.
36 * I think this limit may have been set because of a limit in
37 * GtkList. It could possibly be increased since we are using
38 * GtkClists now, but I'd be surprised if it was reached.
39 * Field length - XLFD_MAX_FIELD_LEN is the maximum length that any field of a
40 * fontname can be for it to be considered valid. Others are
42 * Properties - Maximum of 65535 choices for each font property - guint16's
43 * are used as indices, e.g. in the FontInfo struct.
44 * Combinations - Maximum of 65535 combinations of properties for each font
45 * family - a guint16 is used in the FontInfo struct.
46 * Font size - Minimum font size of 2 pixels/points, since trying to load
47 * some fonts with a size of 1 can cause X to hang.
48 * (e.g. the Misc Fixed fonts).
52 * Possible Improvements:
54 * Font Styles - could sort the styles into a reasonable order - regular
55 * first, then bold, bold italic etc.
57 * I18N - the default preview text is not useful for international
58 * fonts. Maybe the first few characters of the font could be
60 * - fontsets? should these be handled by the font dialog?
64 * Debugging: compile with -DFONTSEL_DEBUG for lots of debugging output.
74 #include "gdk/gdkkeysyms.h"
76 #include "gtkbutton.h"
77 #include "gtkcheckbutton.h"
80 #include "gtkfontsel.h"
85 #include "gtknotebook.h"
86 #include "gtkradiobutton.h"
87 #include "gtksignal.h"
90 #include "gtkscrolledwindow.h"
93 /* The maximum number of fontnames requested with XListFonts(). */
94 #define MAX_FONTS 32767
96 /* This is the largest field length we will accept. If a fontname has a field
97 larger than this we will skip it. */
98 #define XLFD_MAX_FIELD_LEN 64
100 /* These are what we use as the standard font sizes, for the size clist.
101 Note that when using points we still show these integer point values but
102 we work internally in decipoints (and decipoint values can be typed in). */
103 static const guint16 font_sizes[] = {
104 8, 9, 10, 11, 12, 13, 14, 16, 18, 20, 22, 24, 26, 28,
105 32, 36, 40, 48, 56, 64, 72
108 /* Initial font metric & size (Remember point sizes are in decipoints).
109 The font size should match one of those in the font_sizes array. */
110 #define INITIAL_METRIC GTK_FONT_METRIC_POINTS
111 #define INITIAL_FONT_SIZE 140
113 /* This is the default text shown in the preview entry, though the user
114 can set it. Remember that some fonts only have capital letters. */
115 #define PREVIEW_TEXT "abcdefghijk ABCDEFGHIJK"
117 /* This is the initial and maximum height of the preview entry (it expands
118 when large font sizes are selected). Initial height is also the minimum. */
119 #define INITIAL_PREVIEW_HEIGHT 44
120 #define MAX_PREVIEW_HEIGHT 300
122 /* These are the sizes of the font, style & size clists. */
123 #define FONT_LIST_HEIGHT 136
124 #define FONT_LIST_WIDTH 190
125 #define FONT_STYLE_LIST_WIDTH 170
126 #define FONT_SIZE_LIST_WIDTH 60
128 /* This is the number of fields in an X Logical Font Description font name.
129 Note that we count the registry & encoding as 1. */
130 #define GTK_XLFD_NUM_FIELDS 13
132 typedef struct _GtkFontSelInfo GtkFontSelInfo;
133 typedef struct _FontInfo FontInfo;
134 typedef struct _FontStyle FontStyle;
136 /* This struct represents one family of fonts (with one foundry), e.g. adobe
137 courier or sony fixed. It stores the family name, the index of the foundry
138 name, and the index of and number of available styles. */
147 /* This represents one style, as displayed in the Font Style clist. It can
148 have a number of available pixel sizes and point sizes. The indexes point
149 into the two big fontsel_info->pixel_sizes & fontsel_info->point_sizes
150 arrays. The displayed flag is used when displaying styles to remember which
151 styles have already been displayed. Note that it is combined with the
152 GtkFontType in the flags field. */
153 #define GTK_FONT_DISPLAYED (1 << 7)
156 guint16 properties[GTK_NUM_STYLE_PROPERTIES];
157 gint pixel_sizes_index;
158 guint16 npixel_sizes;
159 gint point_sizes_index;
160 guint16 npoint_sizes;
164 struct _GtkFontSelInfo {
166 /* This is a table with each FontInfo representing one font family+foundry */
170 /* This stores all the valid combinations of properties for every family.
171 Each FontInfo holds an index into its own space in this one big array. */
172 FontStyle *font_styles;
175 /* This stores all the font sizes available for every style.
176 Each style holds an index into these arrays. */
177 guint16 *pixel_sizes;
178 guint16 *point_sizes;
180 /* These are the arrays of strings of all possible weights, slants,
181 set widths, spacings, charsets & foundries, and the amount of space
182 allocated for each array. */
183 gchar **properties[GTK_NUM_FONT_PROPERTIES];
184 guint16 nproperties[GTK_NUM_FONT_PROPERTIES];
185 guint16 space_allocated[GTK_NUM_FONT_PROPERTIES];
188 /* These are the field numbers in the X Logical Font Description fontnames,
189 e.g. -adobe-courier-bold-o-normal--25-180-100-100-m-150-iso8859-1 */
200 XLFD_RESOLUTION_X = 8,
201 XLFD_RESOLUTION_Y = 9,
203 XLFD_AVERAGE_WIDTH = 11,
207 /* These are the names of the fields, used on the info & filter page. */
208 static const gchar* xlfd_field_names[GTK_XLFD_NUM_FIELDS] = {
220 N_("Average Width:"),
224 /* These are the array indices of the font properties used in several arrays,
225 and should match the xlfd_index array below. */
236 /* This is used to look up a field in a fontname given one of the above
238 static const FontField xlfd_index[GTK_NUM_FONT_PROPERTIES] = {
247 /* These are the positions of the properties in the filter table - x, y. */
248 static const gint filter_positions[GTK_NUM_FONT_PROPERTIES][2] = {
249 { 1, 0 }, { 0, 2 }, { 1, 2 }, { 2, 2 }, { 2, 0 }, { 0, 0 }
251 static const gint filter_heights[GTK_NUM_FONT_PROPERTIES] = {
252 100, 70, 70, 40, 100, 100
255 /* This is returned by gtk_font_selection_filter_state to describe if a
256 property value is filtered. e.g. if 'bold' has been selected on the filter
257 page, then that will return 'FILTERED' and 'black' will be 'NOT_FILTERED'.
258 If none of the weight values are selected, they all return 'NOT_SET'. */
264 } GtkFontPropertyFilterState;
266 static GtkFontSelInfo *fontsel_info = NULL;
268 /* The initial size and increment of each of the arrays of property values. */
269 #define PROPERTY_ARRAY_INCREMENT 16
271 static void gtk_font_selection_class_init (GtkFontSelectionClass *klass);
272 static void gtk_font_selection_init (GtkFontSelection *fontsel);
273 static void gtk_font_selection_destroy (GtkObject *object);
275 /* These are all used for class initialization - loading in the fonts etc. */
276 static void gtk_font_selection_get_fonts (void);
277 static void gtk_font_selection_insert_font (GSList *fontnames[],
280 static gint gtk_font_selection_insert_field (gchar *fontname,
283 /* These are the callbacks & related functions. */
284 static void gtk_font_selection_select_font (GtkWidget *w,
287 GdkEventButton *bevent,
289 static gint gtk_font_selection_on_clist_key_press (GtkWidget *clist,
291 GtkFontSelection *fs);
292 static gboolean gtk_font_selection_select_next (GtkFontSelection *fs,
295 static void gtk_font_selection_show_available_styles
296 (GtkFontSelection *fs);
297 static void gtk_font_selection_select_best_style (GtkFontSelection *fs,
300 static void gtk_font_selection_select_style (GtkWidget *w,
303 GdkEventButton *bevent,
305 static void gtk_font_selection_show_available_sizes
306 (GtkFontSelection *fs);
307 static gint gtk_font_selection_size_key_press (GtkWidget *w,
310 static void gtk_font_selection_select_best_size (GtkFontSelection *fs);
311 static void gtk_font_selection_select_size (GtkWidget *w,
314 GdkEventButton *bevent,
317 static void gtk_font_selection_metric_callback (GtkWidget *w,
319 static void gtk_font_selection_expose_list (GtkWidget *w,
320 GdkEventExpose *event,
322 static void gtk_font_selection_realize_list (GtkWidget *widget,
325 static void gtk_font_selection_switch_page (GtkWidget *w,
326 GtkNotebookPage *page,
329 static void gtk_font_selection_show_font_info (GtkFontSelection *fs);
331 static void gtk_font_selection_select_filter (GtkWidget *w,
334 GdkEventButton *bevent,
335 GtkFontSelection *fs);
336 static void gtk_font_selection_unselect_filter (GtkWidget *w,
339 GdkEventButton *bevent,
340 GtkFontSelection *fs);
341 static void gtk_font_selection_update_filter (GtkFontSelection *fs);
342 static gboolean gtk_font_selection_style_visible (GtkFontSelection *fs,
345 static void gtk_font_selection_reset_filter (GtkWidget *w,
346 GtkFontSelection *fs);
347 static void gtk_font_selection_on_clear_filter (GtkWidget *w,
348 GtkFontSelection *fs);
349 static void gtk_font_selection_show_available_fonts
350 (GtkFontSelection *fs);
351 static void gtk_font_selection_clear_filter (GtkFontSelection *fs);
352 static void gtk_font_selection_update_filter_lists(GtkFontSelection *fs);
353 static GtkFontPropertyFilterState gtk_font_selection_filter_state
354 (GtkFontSelection *fs,
355 GtkFontFilterType filter_type,
359 /* Misc. utility functions. */
360 static gboolean gtk_font_selection_load_font (GtkFontSelection *fs);
361 static void gtk_font_selection_update_preview (GtkFontSelection *fs);
363 static gint gtk_font_selection_find_font (GtkFontSelection *fs,
366 static guint16 gtk_font_selection_field_to_index (gchar **table,
370 static gchar* gtk_font_selection_expand_slant_code (gchar *slant);
371 static gchar* gtk_font_selection_expand_spacing_code(gchar *spacing);
373 /* Functions for handling X Logical Font Description fontnames. */
374 static gboolean gtk_font_selection_is_xlfd_font_name (const gchar *fontname);
375 static char* gtk_font_selection_get_xlfd_field (const gchar *fontname,
378 static gchar * gtk_font_selection_create_xlfd (gint size,
379 GtkFontMetricType metric,
389 /* FontSelectionDialog */
390 static void gtk_font_selection_dialog_class_init (GtkFontSelectionDialogClass *klass);
391 static void gtk_font_selection_dialog_init (GtkFontSelectionDialog *fontseldiag);
393 static gint gtk_font_selection_dialog_on_configure(GtkWidget *widget,
394 GdkEventConfigure *event,
395 GtkFontSelectionDialog *fsd);
397 #if GDK_WINDOWING == GDK_WINDOWING_WIN32
398 static char *logfont_to_xlfd (const LOGFONT *lfp,
404 static GtkWindowClass *font_selection_parent_class = NULL;
405 static GtkNotebookClass *font_selection_dialog_parent_class = NULL;
408 gtk_font_selection_get_type()
410 static GtkType font_selection_type = 0;
412 if(!font_selection_type)
414 static const GtkTypeInfo fontsel_type_info =
417 sizeof (GtkFontSelection),
418 sizeof (GtkFontSelectionClass),
419 (GtkClassInitFunc) gtk_font_selection_class_init,
420 (GtkObjectInitFunc) gtk_font_selection_init,
421 /* reserved_1 */ NULL,
422 /* reserved_2 */ NULL,
423 (GtkClassInitFunc) NULL,
426 font_selection_type = gtk_type_unique (GTK_TYPE_NOTEBOOK,
430 return font_selection_type;
434 gtk_font_selection_class_init(GtkFontSelectionClass *klass)
436 GtkObjectClass *object_class;
438 object_class = (GtkObjectClass *) klass;
440 font_selection_parent_class = gtk_type_class (GTK_TYPE_NOTEBOOK);
442 object_class->destroy = gtk_font_selection_destroy;
444 gtk_font_selection_get_fonts ();
448 gtk_font_selection_init(GtkFontSelection *fontsel)
450 GtkWidget *scrolled_win;
451 GtkWidget *text_frame;
452 GtkWidget *text_box, *frame;
453 GtkWidget *table, *label, *hbox, *hbox2, *clist, *button, *vbox, *alignment;
455 gchar *titles[] = { NULL, NULL, NULL };
460 gchar *property, *text;
463 /* Number of internationalized titles here must match number
464 of NULL initializers above */
465 titles[0] = _("Font Property");
466 titles[1] = _("Requested Value");
467 titles[2] = _("Actual Value");
469 /* Initialize the GtkFontSelection struct. We do this here in case any
470 callbacks are triggered while creating the interface. */
471 fontsel->font = NULL;
472 fontsel->font_index = -1;
474 fontsel->metric = INITIAL_METRIC;
475 fontsel->size = INITIAL_FONT_SIZE;
476 fontsel->selected_size = INITIAL_FONT_SIZE;
478 fontsel->filters[GTK_FONT_FILTER_BASE].font_type = GTK_FONT_ALL;
479 fontsel->filters[GTK_FONT_FILTER_USER].font_type = GTK_FONT_BITMAP
483 for (prop = 0; prop < GTK_NUM_FONT_PROPERTIES; prop++)
485 fontsel->filters[GTK_FONT_FILTER_BASE].property_filters[prop] = NULL;
486 fontsel->filters[GTK_FONT_FILTER_BASE].property_nfilters[prop] = 0;
487 fontsel->filters[GTK_FONT_FILTER_USER].property_filters[prop] = NULL;
488 fontsel->filters[GTK_FONT_FILTER_USER].property_nfilters[prop] = 0;
491 for (prop = 0; prop < GTK_NUM_STYLE_PROPERTIES; prop++)
492 fontsel->property_values[prop] = 0;
494 /* Create the main notebook page. */
495 gtk_notebook_set_homogeneous_tabs (GTK_NOTEBOOK (fontsel), TRUE);
496 gtk_notebook_set_tab_hborder (GTK_NOTEBOOK (fontsel), 8);
497 fontsel->main_vbox = gtk_vbox_new (FALSE, 4);
498 gtk_widget_show (fontsel->main_vbox);
499 gtk_container_set_border_width (GTK_CONTAINER (fontsel->main_vbox), 6);
500 label = gtk_label_new(_("Font"));
501 gtk_notebook_append_page (GTK_NOTEBOOK (fontsel),
502 fontsel->main_vbox, label);
504 /* Create the table of font, style & size. */
505 table = gtk_table_new (3, 3, FALSE);
506 gtk_widget_show (table);
507 gtk_table_set_col_spacings(GTK_TABLE(table), 8);
508 gtk_box_pack_start (GTK_BOX (fontsel->main_vbox), table, TRUE, TRUE, 0);
510 fontsel->font_label = gtk_label_new(_("Font:"));
511 gtk_misc_set_alignment (GTK_MISC (fontsel->font_label), 0.0, 0.5);
512 gtk_widget_show (fontsel->font_label);
513 gtk_table_attach (GTK_TABLE (table), fontsel->font_label, 0, 1, 0, 1,
515 label = gtk_label_new(_("Font Style:"));
516 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
517 gtk_widget_show (label);
518 gtk_table_attach (GTK_TABLE (table), label, 1, 2, 0, 1,
520 label = gtk_label_new(_("Size:"));
521 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
522 gtk_widget_show (label);
523 gtk_table_attach (GTK_TABLE (table), label, 2, 3, 0, 1,
526 fontsel->font_entry = gtk_entry_new();
527 gtk_entry_set_editable(GTK_ENTRY(fontsel->font_entry), FALSE);
528 gtk_widget_set_usize (fontsel->font_entry, 20, -1);
529 gtk_widget_show (fontsel->font_entry);
530 gtk_table_attach (GTK_TABLE (table), fontsel->font_entry, 0, 1, 1, 2,
532 fontsel->font_style_entry = gtk_entry_new();
533 gtk_entry_set_editable(GTK_ENTRY(fontsel->font_style_entry), FALSE);
534 gtk_widget_set_usize (fontsel->font_style_entry, 20, -1);
535 gtk_widget_show (fontsel->font_style_entry);
536 gtk_table_attach (GTK_TABLE (table), fontsel->font_style_entry, 1, 2, 1, 2,
538 fontsel->size_entry = gtk_entry_new();
539 gtk_widget_set_usize (fontsel->size_entry, 20, -1);
540 gtk_widget_show (fontsel->size_entry);
541 gtk_table_attach (GTK_TABLE (table), fontsel->size_entry, 2, 3, 1, 2,
543 gtk_signal_connect (GTK_OBJECT (fontsel->size_entry), "key_press_event",
544 (GtkSignalFunc) gtk_font_selection_size_key_press,
547 /* Create the clists */
548 fontsel->font_clist = gtk_clist_new(1);
549 gtk_clist_column_titles_hide (GTK_CLIST(fontsel->font_clist));
550 gtk_clist_set_column_auto_resize (GTK_CLIST (fontsel->font_clist), 0, TRUE);
551 scrolled_win = gtk_scrolled_window_new (NULL, NULL);
552 gtk_widget_set_usize (scrolled_win, FONT_LIST_WIDTH, FONT_LIST_HEIGHT);
553 gtk_container_add (GTK_CONTAINER (scrolled_win), fontsel->font_clist);
554 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
555 GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
556 gtk_widget_show(fontsel->font_clist);
557 gtk_widget_show(scrolled_win);
559 gtk_table_attach (GTK_TABLE (table), scrolled_win, 0, 1, 2, 3,
560 GTK_EXPAND | GTK_FILL,
561 GTK_EXPAND | GTK_FILL, 0, 0);
563 fontsel->font_style_clist = gtk_clist_new(1);
564 gtk_clist_column_titles_hide (GTK_CLIST(fontsel->font_style_clist));
565 gtk_clist_set_column_auto_resize (GTK_CLIST (fontsel->font_style_clist),
567 scrolled_win = gtk_scrolled_window_new (NULL, NULL);
568 gtk_widget_set_usize (scrolled_win, FONT_STYLE_LIST_WIDTH, -1);
569 gtk_container_add (GTK_CONTAINER (scrolled_win), fontsel->font_style_clist);
570 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
571 GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
572 gtk_widget_show(fontsel->font_style_clist);
573 gtk_widget_show(scrolled_win);
574 gtk_table_attach (GTK_TABLE (table), scrolled_win, 1, 2, 2, 3,
575 GTK_EXPAND | GTK_FILL,
576 GTK_EXPAND | GTK_FILL, 0, 0);
578 fontsel->size_clist = gtk_clist_new(1);
579 gtk_clist_column_titles_hide (GTK_CLIST(fontsel->size_clist));
580 gtk_clist_set_column_width (GTK_CLIST(fontsel->size_clist), 0, 20);
581 scrolled_win = gtk_scrolled_window_new (NULL, NULL);
582 gtk_widget_set_usize (scrolled_win, FONT_SIZE_LIST_WIDTH, -1);
583 gtk_container_add (GTK_CONTAINER (scrolled_win), fontsel->size_clist);
584 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
585 GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
586 gtk_widget_show(fontsel->size_clist);
587 gtk_widget_show(scrolled_win);
588 gtk_table_attach (GTK_TABLE (table), scrolled_win, 2, 3, 2, 3,
589 GTK_FILL, GTK_FILL, 0, 0);
592 /* Insert the fonts. If there exist fonts with the same family but
593 different foundries, then the foundry name is appended in brackets. */
594 gtk_font_selection_show_available_fonts(fontsel);
596 gtk_signal_connect (GTK_OBJECT (fontsel->font_clist), "select_row",
597 GTK_SIGNAL_FUNC(gtk_font_selection_select_font),
599 GTK_WIDGET_SET_FLAGS (fontsel->font_clist, GTK_CAN_FOCUS);
600 gtk_signal_connect (GTK_OBJECT (fontsel->font_clist), "key_press_event",
601 GTK_SIGNAL_FUNC(gtk_font_selection_on_clist_key_press),
603 gtk_signal_connect_after (GTK_OBJECT (fontsel->font_clist), "expose_event",
604 GTK_SIGNAL_FUNC(gtk_font_selection_expose_list),
607 gtk_signal_connect (GTK_OBJECT (fontsel->font_style_clist), "select_row",
608 GTK_SIGNAL_FUNC(gtk_font_selection_select_style),
610 GTK_WIDGET_SET_FLAGS (fontsel->font_style_clist, GTK_CAN_FOCUS);
611 gtk_signal_connect (GTK_OBJECT (fontsel->font_style_clist),
613 GTK_SIGNAL_FUNC(gtk_font_selection_on_clist_key_press),
615 gtk_signal_connect_after (GTK_OBJECT (fontsel->font_style_clist),
617 GTK_SIGNAL_FUNC(gtk_font_selection_realize_list),
620 /* Insert the standard font sizes */
621 gtk_clist_freeze (GTK_CLIST(fontsel->size_clist));
622 size_to_match = INITIAL_FONT_SIZE;
623 if (INITIAL_METRIC == GTK_FONT_METRIC_POINTS)
624 size_to_match = size_to_match / 10;
625 for (i = 0; i < sizeof(font_sizes) / sizeof(font_sizes[0]); i++)
627 sprintf(buffer, "%i", font_sizes[i]);
629 gtk_clist_append(GTK_CLIST(fontsel->size_clist), &size);
630 if (font_sizes[i] == size_to_match)
632 gtk_clist_select_row(GTK_CLIST(fontsel->size_clist), i, 0);
633 gtk_entry_set_text(GTK_ENTRY(fontsel->size_entry), buffer);
636 gtk_clist_thaw (GTK_CLIST(fontsel->size_clist));
638 gtk_signal_connect (GTK_OBJECT (fontsel->size_clist), "select_row",
639 GTK_SIGNAL_FUNC(gtk_font_selection_select_size),
641 GTK_WIDGET_SET_FLAGS (fontsel->size_clist, GTK_CAN_FOCUS);
642 gtk_signal_connect (GTK_OBJECT (fontsel->size_clist), "key_press_event",
643 GTK_SIGNAL_FUNC(gtk_font_selection_on_clist_key_press),
647 /* create the Reset Filter & Metric buttons */
648 hbox = gtk_hbox_new(FALSE, 8);
649 gtk_widget_show (hbox);
650 gtk_box_pack_start (GTK_BOX (fontsel->main_vbox), hbox, FALSE, TRUE, 0);
652 fontsel->filter_button = gtk_button_new_with_label(_("Reset Filter"));
653 gtk_misc_set_padding (GTK_MISC (GTK_BIN (fontsel->filter_button)->child),
655 gtk_widget_show(fontsel->filter_button);
656 gtk_box_pack_start (GTK_BOX (hbox), fontsel->filter_button, FALSE, FALSE, 0);
657 gtk_widget_set_sensitive (fontsel->filter_button, FALSE);
658 gtk_signal_connect (GTK_OBJECT (fontsel->filter_button), "clicked",
659 GTK_SIGNAL_FUNC(gtk_font_selection_on_clear_filter),
662 hbox2 = gtk_hbox_new(FALSE, 0);
663 gtk_widget_show (hbox2);
664 gtk_box_pack_end (GTK_BOX (hbox), hbox2, FALSE, FALSE, 0);
666 label = gtk_label_new(_("Metric:"));
667 gtk_widget_show (label);
668 gtk_box_pack_start (GTK_BOX (hbox2), label, FALSE, TRUE, 8);
670 fontsel->points_button = gtk_radio_button_new_with_label(NULL, _("Points"));
671 gtk_widget_show (fontsel->points_button);
672 gtk_box_pack_start (GTK_BOX (hbox2), fontsel->points_button, FALSE, TRUE, 0);
673 if (INITIAL_METRIC == GTK_FONT_METRIC_POINTS)
674 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(fontsel->points_button),
677 fontsel->pixels_button = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(fontsel->points_button), _("Pixels"));
678 gtk_widget_show (fontsel->pixels_button);
679 gtk_box_pack_start (GTK_BOX (hbox2), fontsel->pixels_button, FALSE, TRUE, 0);
680 if (INITIAL_METRIC == GTK_FONT_METRIC_PIXELS)
681 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(fontsel->pixels_button),
684 gtk_signal_connect(GTK_OBJECT(fontsel->points_button), "toggled",
685 (GtkSignalFunc) gtk_font_selection_metric_callback,
687 gtk_signal_connect(GTK_OBJECT(fontsel->pixels_button), "toggled",
688 (GtkSignalFunc) gtk_font_selection_metric_callback,
692 /* create the text entry widget */
693 text_frame = gtk_frame_new (_("Preview:"));
694 gtk_widget_show (text_frame);
695 gtk_frame_set_shadow_type(GTK_FRAME(text_frame), GTK_SHADOW_ETCHED_IN);
696 gtk_box_pack_start (GTK_BOX (fontsel->main_vbox), text_frame,
699 /* This is just used to get a 4-pixel space around the preview entry. */
700 text_box = gtk_hbox_new (FALSE, 0);
701 gtk_widget_show (text_box);
702 gtk_container_add (GTK_CONTAINER (text_frame), text_box);
703 gtk_container_set_border_width (GTK_CONTAINER (text_box), 4);
705 fontsel->preview_entry = gtk_entry_new ();
706 gtk_widget_show (fontsel->preview_entry);
707 gtk_widget_set_usize (fontsel->preview_entry, -1, INITIAL_PREVIEW_HEIGHT);
708 gtk_box_pack_start (GTK_BOX (text_box), fontsel->preview_entry,
711 /* Create the message area */
712 fontsel->message_label = gtk_label_new("");
713 gtk_widget_show (fontsel->message_label);
714 gtk_box_pack_start (GTK_BOX (fontsel->main_vbox), fontsel->message_label,
718 /* Create the font info page */
719 fontsel->info_vbox = gtk_vbox_new (FALSE, 4);
720 gtk_widget_show (fontsel->info_vbox);
721 gtk_container_set_border_width (GTK_CONTAINER (fontsel->info_vbox), 2);
722 label = gtk_label_new(_("Font Information"));
723 gtk_notebook_append_page (GTK_NOTEBOOK (fontsel),
724 fontsel->info_vbox, label);
726 fontsel->info_clist = gtk_clist_new_with_titles (3, titles);
727 gtk_widget_set_usize (fontsel->info_clist, 390, 150);
728 gtk_clist_set_column_width(GTK_CLIST(fontsel->info_clist), 0, 130);
729 gtk_clist_set_column_width(GTK_CLIST(fontsel->info_clist), 1, 130);
730 gtk_clist_set_column_width(GTK_CLIST(fontsel->info_clist), 2, 130);
731 gtk_clist_column_titles_passive(GTK_CLIST(fontsel->info_clist));
732 scrolled_win = gtk_scrolled_window_new (NULL, NULL);
733 gtk_container_add (GTK_CONTAINER (scrolled_win), fontsel->info_clist);
734 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
735 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
736 gtk_widget_show(fontsel->info_clist);
737 gtk_widget_show(scrolled_win);
738 gtk_box_pack_start (GTK_BOX (fontsel->info_vbox), scrolled_win,
741 /* Insert the property names */
742 gtk_clist_freeze (GTK_CLIST(fontsel->info_clist));
745 for (i = 0; i < GTK_XLFD_NUM_FIELDS; i++)
747 row_text[0] = _(xlfd_field_names[i]);
748 gtk_clist_append(GTK_CLIST(fontsel->info_clist), row_text);
749 gtk_clist_set_shift(GTK_CLIST(fontsel->info_clist), i, 0, 0, 4);
750 gtk_clist_set_shift(GTK_CLIST(fontsel->info_clist), i, 1, 0, 4);
751 gtk_clist_set_shift(GTK_CLIST(fontsel->info_clist), i, 2, 0, 4);
753 gtk_clist_thaw (GTK_CLIST(fontsel->info_clist));
755 label = gtk_label_new(_("Requested Font Name:"));
756 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
757 gtk_widget_show (label);
758 gtk_box_pack_start (GTK_BOX (fontsel->info_vbox), label, FALSE, TRUE, 0);
760 fontsel->requested_font_name = gtk_entry_new();
761 gtk_entry_set_editable(GTK_ENTRY(fontsel->requested_font_name), FALSE);
762 gtk_widget_show (fontsel->requested_font_name);
763 gtk_box_pack_start (GTK_BOX (fontsel->info_vbox),
764 fontsel->requested_font_name, FALSE, TRUE, 0);
766 label = gtk_label_new(_("Actual Font Name:"));
767 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
768 gtk_widget_show (label);
769 gtk_box_pack_start (GTK_BOX (fontsel->info_vbox), label, FALSE, TRUE, 0);
771 fontsel->actual_font_name = gtk_entry_new();
772 gtk_entry_set_editable(GTK_ENTRY(fontsel->actual_font_name), FALSE);
773 gtk_widget_show (fontsel->actual_font_name);
774 gtk_box_pack_start (GTK_BOX (fontsel->info_vbox),
775 fontsel->actual_font_name, FALSE, TRUE, 0);
777 sprintf(buffer, _("%i fonts available with a total of %i styles."),
778 fontsel_info->nfonts, fontsel_info->nstyles);
779 label = gtk_label_new(buffer);
780 gtk_widget_show (label);
781 gtk_box_pack_start (GTK_BOX (fontsel->info_vbox), label, FALSE, FALSE, 0);
783 gtk_signal_connect (GTK_OBJECT (fontsel), "switch_page",
784 GTK_SIGNAL_FUNC(gtk_font_selection_switch_page),
788 /* Create the Filter page. */
789 fontsel->filter_vbox = gtk_vbox_new (FALSE, 4);
790 gtk_widget_show (fontsel->filter_vbox);
791 gtk_container_set_border_width (GTK_CONTAINER (fontsel->filter_vbox), 2);
792 label = gtk_label_new(_("Filter"));
793 gtk_notebook_append_page (GTK_NOTEBOOK (fontsel),
794 fontsel->filter_vbox, label);
796 /* Create the font type checkbuttons. */
797 frame = gtk_frame_new (NULL);
798 gtk_widget_show (frame);
799 gtk_box_pack_start (GTK_BOX (fontsel->filter_vbox), frame, FALSE, TRUE, 0);
801 hbox = gtk_hbox_new (FALSE, 20);
802 gtk_widget_show (hbox);
803 gtk_container_add (GTK_CONTAINER (frame), hbox);
805 label = gtk_label_new(_("Font Types:"));
806 gtk_widget_show (label);
807 gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 10);
809 hbox2 = gtk_hbox_new (TRUE, 0);
810 gtk_widget_show (hbox2);
811 gtk_box_pack_start (GTK_BOX (hbox), hbox2, FALSE, TRUE, 0);
813 fontsel->type_bitmaps_button = gtk_check_button_new_with_label (_("Bitmap"));
814 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fontsel->type_bitmaps_button), TRUE);
815 gtk_widget_show (fontsel->type_bitmaps_button);
816 gtk_box_pack_start (GTK_BOX (hbox2), fontsel->type_bitmaps_button,
819 fontsel->type_scalable_button = gtk_check_button_new_with_label (_("Scalable"));
820 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fontsel->type_scalable_button), TRUE);
821 gtk_widget_show (fontsel->type_scalable_button);
822 gtk_box_pack_start (GTK_BOX (hbox2), fontsel->type_scalable_button,
825 fontsel->type_scaled_bitmaps_button = gtk_check_button_new_with_label (_("Scaled Bitmap"));
826 gtk_widget_show (fontsel->type_scaled_bitmaps_button);
827 gtk_box_pack_start (GTK_BOX (hbox2), fontsel->type_scaled_bitmaps_button,
830 table = gtk_table_new (4, 3, FALSE);
831 gtk_table_set_col_spacings(GTK_TABLE(table), 2);
832 gtk_widget_show (table);
833 gtk_box_pack_start (GTK_BOX (fontsel->filter_vbox), table, TRUE, TRUE, 0);
835 for (prop = 0; prop < GTK_NUM_FONT_PROPERTIES; prop++)
837 gint left = filter_positions[prop][0];
838 gint top = filter_positions[prop][1];
840 label = gtk_label_new(_(xlfd_field_names[xlfd_index[prop]]));
841 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 1.0);
842 gtk_misc_set_padding (GTK_MISC (label), 0, 2);
843 gtk_widget_show(label);
844 gtk_table_attach (GTK_TABLE (table), label, left, left + 1,
845 top, top + 1, GTK_FILL, GTK_FILL, 0, 0);
847 clist = gtk_clist_new(1);
848 gtk_widget_set_usize (clist, 100, filter_heights[prop]);
849 gtk_clist_set_selection_mode(GTK_CLIST(clist), GTK_SELECTION_MULTIPLE);
850 gtk_clist_column_titles_hide(GTK_CLIST(clist));
851 gtk_clist_set_column_auto_resize (GTK_CLIST (clist), 0, TRUE);
852 scrolled_win = gtk_scrolled_window_new (NULL, NULL);
853 gtk_container_add (GTK_CONTAINER (scrolled_win), clist);
854 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
855 GTK_POLICY_AUTOMATIC,
856 GTK_POLICY_AUTOMATIC);
857 gtk_widget_show(clist);
858 gtk_widget_show(scrolled_win);
860 /* For the bottom-right cell we add the 'Reset Filter' button. */
861 if (top == 2 && left == 2)
863 vbox = gtk_vbox_new(FALSE, 0);
864 gtk_widget_show(vbox);
865 gtk_table_attach (GTK_TABLE (table), vbox, left, left + 1,
866 top + 1, top + 2, GTK_FILL, GTK_FILL, 0, 0);
868 gtk_box_pack_start (GTK_BOX (vbox), scrolled_win, TRUE, TRUE, 0);
870 alignment = gtk_alignment_new(0.5, 0.0, 0.8, 0.0);
871 gtk_widget_show(alignment);
872 gtk_box_pack_start (GTK_BOX (vbox), alignment, FALSE, TRUE, 4);
874 button = gtk_button_new_with_label(_("Reset Filter"));
875 gtk_widget_show(button);
876 gtk_container_add(GTK_CONTAINER(alignment), button);
877 gtk_signal_connect (GTK_OBJECT (button), "clicked",
878 GTK_SIGNAL_FUNC(gtk_font_selection_reset_filter),
882 gtk_table_attach (GTK_TABLE (table), scrolled_win,
883 left, left + 1, top + 1, top + 2,
884 GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
886 gtk_signal_connect (GTK_OBJECT (clist), "select_row",
887 GTK_SIGNAL_FUNC(gtk_font_selection_select_filter),
889 gtk_signal_connect (GTK_OBJECT (clist), "unselect_row",
890 GTK_SIGNAL_FUNC(gtk_font_selection_unselect_filter),
893 /* Insert the property names, expanded, and in sorted order.
894 But we make sure that the wildcard '*' is first. */
895 gtk_clist_freeze (GTK_CLIST(clist));
897 gtk_clist_append(GTK_CLIST(clist), &property);
899 for (i = 1; i < fontsel_info->nproperties[prop]; i++) {
900 property = _(fontsel_info->properties[prop][i]);
902 property = gtk_font_selection_expand_slant_code(property);
903 else if (prop == SPACING)
904 property = gtk_font_selection_expand_spacing_code(property);
907 for (row = 1; row < GTK_CLIST(clist)->rows; row++)
909 gtk_clist_get_text(GTK_CLIST(clist), row, 0, &text);
910 if (strcmp(property, text) < 0)
913 gtk_clist_insert(GTK_CLIST(clist), row, &property);
918 row = gtk_clist_append(GTK_CLIST(clist), &property);
919 gtk_clist_set_row_data(GTK_CLIST(clist), row, GINT_TO_POINTER (i));
921 gtk_clist_select_row(GTK_CLIST(clist), 0, 0);
922 gtk_clist_thaw (GTK_CLIST(clist));
923 fontsel->filter_clists[prop] = clist;
928 gtk_font_selection_new()
930 GtkFontSelection *fontsel;
932 fontsel = gtk_type_new (GTK_TYPE_FONT_SELECTION);
934 return GTK_WIDGET (fontsel);
938 gtk_font_selection_destroy (GtkObject *object)
940 GtkFontSelection *fontsel;
942 g_return_if_fail (object != NULL);
943 g_return_if_fail (GTK_IS_FONT_SELECTION (object));
945 fontsel = GTK_FONT_SELECTION (object);
947 /* All we have to do is unref the font, if we have one. */
949 gdk_font_unref (fontsel->font);
951 if (GTK_OBJECT_CLASS (font_selection_parent_class)->destroy)
952 (* GTK_OBJECT_CLASS (font_selection_parent_class)->destroy) (object);
956 /* This is called when the clist is exposed. Here we scroll to the current
957 font if necessary. */
959 gtk_font_selection_expose_list (GtkWidget *widget,
960 GdkEventExpose *event,
963 GtkFontSelection *fontsel;
969 g_message("In expose_list\n");
971 fontsel = GTK_FONT_SELECTION(data);
973 font_info = fontsel_info->font_info;
975 /* Try to scroll the font family clist to the selected item */
976 selection = GTK_CLIST(fontsel->font_clist)->selection;
979 index = GPOINTER_TO_INT (selection->data);
980 if (gtk_clist_row_is_visible(GTK_CLIST(fontsel->font_clist), index)
981 != GTK_VISIBILITY_FULL)
982 gtk_clist_moveto(GTK_CLIST(fontsel->font_clist), index, -1, 0.5, 0);
985 /* Try to scroll the font style clist to the selected item */
986 selection = GTK_CLIST(fontsel->font_style_clist)->selection;
989 index = GPOINTER_TO_INT (selection->data);
990 if (gtk_clist_row_is_visible(GTK_CLIST(fontsel->font_style_clist), index)
991 != GTK_VISIBILITY_FULL)
992 gtk_clist_moveto(GTK_CLIST(fontsel->font_style_clist), index, -1,
996 /* Try to scroll the font size clist to the selected item */
997 selection = GTK_CLIST(fontsel->size_clist)->selection;
1000 index = GPOINTER_TO_INT (selection->data);
1001 if (gtk_clist_row_is_visible(GTK_CLIST(fontsel->size_clist), index)
1002 != GTK_VISIBILITY_FULL)
1003 gtk_clist_moveto(GTK_CLIST(fontsel->size_clist), index, -1, 0.5, 0);
1008 /* This is called when the style clist is realized. We need to set any
1009 charset rows to insensitive colours. */
1011 gtk_font_selection_realize_list (GtkWidget *widget,
1014 GtkFontSelection *fontsel;
1016 GdkColor *inactive_fg, *inactive_bg;
1018 #ifdef FONTSEL_DEBUG
1019 g_message("In realize_list\n");
1021 fontsel = GTK_FONT_SELECTION (data);
1023 /* Set the colours for any charset rows to insensitive. */
1024 inactive_fg = &fontsel->font_style_clist->style->fg[GTK_STATE_INSENSITIVE];
1025 inactive_bg = &fontsel->font_style_clist->style->bg[GTK_STATE_INSENSITIVE];
1027 for (row = 0; row < GTK_CLIST (fontsel->font_style_clist)->rows; row++)
1029 if (GPOINTER_TO_INT (gtk_clist_get_row_data (GTK_CLIST (fontsel->font_style_clist), row)) == -1)
1031 gtk_clist_set_foreground (GTK_CLIST (fontsel->font_style_clist),
1033 gtk_clist_set_background (GTK_CLIST (fontsel->font_style_clist),
1040 /* This is called when a family is selected in the list. */
1042 gtk_font_selection_select_font (GtkWidget *w,
1045 GdkEventButton *bevent,
1048 GtkFontSelection *fontsel;
1049 FontInfo *font_info;
1052 #ifdef FONTSEL_DEBUG
1053 g_message("In select_font\n");
1055 fontsel = GTK_FONT_SELECTION(data);
1056 font_info = fontsel_info->font_info;
1058 if (bevent && !GTK_WIDGET_HAS_FOCUS (w))
1059 gtk_widget_grab_focus (w);
1061 row = GPOINTER_TO_INT (gtk_clist_get_row_data (GTK_CLIST (fontsel->font_clist), row));
1062 font = &font_info[row];
1063 gtk_entry_set_text(GTK_ENTRY(fontsel->font_entry), font->family);
1065 /* If it is already the current font, just return. */
1066 if (fontsel->font_index == row)
1069 fontsel->font_index = row;
1070 gtk_font_selection_show_available_styles (fontsel);
1071 gtk_font_selection_select_best_style (fontsel, TRUE);
1076 gtk_font_selection_on_clist_key_press (GtkWidget *clist,
1078 GtkFontSelection *fontsel)
1080 #ifdef FONTSEL_DEBUG
1081 g_message("In on_clist_key_press\n");
1083 if (event->keyval == GDK_Up)
1084 return gtk_font_selection_select_next (fontsel, clist, -1);
1085 else if (event->keyval == GDK_Down)
1086 return gtk_font_selection_select_next (fontsel, clist, 1);
1093 gtk_font_selection_select_next (GtkFontSelection *fontsel,
1098 gint current_row, row;
1100 selection = GTK_CLIST(clist)->selection;
1103 current_row = GPOINTER_TO_INT (selection->data);
1105 /* Stop the normal clist key handler from being run. */
1106 gtk_signal_emit_stop_by_name (GTK_OBJECT (clist), "key_press_event");
1108 for (row = current_row + step;
1109 row >= 0 && row < GTK_CLIST(clist)->rows;
1112 /* If this is the style clist, make sure that the item is not a charset
1114 if (clist == fontsel->font_style_clist)
1115 if (GPOINTER_TO_INT (gtk_clist_get_row_data(GTK_CLIST(clist), row)) == -1)
1118 /* Now we've found the row to select. */
1119 if (gtk_clist_row_is_visible(GTK_CLIST(clist), row)
1120 != GTK_VISIBILITY_FULL)
1121 gtk_clist_moveto(GTK_CLIST(clist), row, -1, (step < 0) ? 0 : 1, 0);
1122 gtk_clist_select_row(GTK_CLIST(clist), row, 0);
1129 /* This fills the font style clist with all the possible style combinations
1130 for the current font family. */
1132 gtk_font_selection_show_available_styles (GtkFontSelection *fontsel)
1136 gint style, tmpstyle, row;
1137 gint weight_index, slant_index, set_width_index, spacing_index;
1139 gchar *weight, *slant, *set_width, *spacing;
1140 gchar *charset = NULL;
1142 gchar buffer[XLFD_MAX_FIELD_LEN * 6 + 2];
1143 GdkColor *inactive_fg, *inactive_bg;
1144 gboolean show_charset;
1146 #ifdef FONTSEL_DEBUG
1147 g_message("In show_available_styles\n");
1149 font = &fontsel_info->font_info[fontsel->font_index];
1150 styles = &fontsel_info->font_styles[font->style_index];
1152 gtk_clist_freeze (GTK_CLIST(fontsel->font_style_clist));
1153 gtk_clist_clear (GTK_CLIST(fontsel->font_style_clist));
1155 /* First we mark all visible styles as not having been displayed yet,
1156 and check if every style has the same charset. If not then we will
1157 display the charset in the list before the styles. */
1158 show_charset = FALSE;
1160 for (style = 0; style < font->nstyles; style++)
1162 if (gtk_font_selection_style_visible(fontsel, font, style))
1164 styles[style].flags &= ~GTK_FONT_DISPLAYED;
1166 if (charset_index == -1)
1167 charset_index = styles[style].properties[CHARSET];
1168 else if (charset_index != styles[style].properties[CHARSET])
1169 show_charset = TRUE;
1172 styles[style].flags |= GTK_FONT_DISPLAYED;
1175 /* Step through the undisplayed styles, finding the next charset which
1176 hasn't been displayed yet. Then display the charset on one line, if
1177 necessary, and the visible styles indented beneath it. */
1178 inactive_fg = &fontsel->font_style_clist->style->fg[GTK_STATE_INSENSITIVE];
1179 inactive_bg = &fontsel->font_style_clist->style->bg[GTK_STATE_INSENSITIVE];
1181 for (style = 0; style < font->nstyles; style++)
1183 if (styles[style].flags & GTK_FONT_DISPLAYED)
1188 charset_index = styles[style].properties[CHARSET];
1189 charset = fontsel_info->properties[CHARSET] [charset_index];
1190 row = gtk_clist_append(GTK_CLIST(fontsel->font_style_clist),
1192 gtk_clist_set_row_data(GTK_CLIST(fontsel->font_style_clist), row,
1194 if (GTK_WIDGET_REALIZED (fontsel->font_style_clist))
1196 gtk_clist_set_foreground(GTK_CLIST(fontsel->font_style_clist),
1198 gtk_clist_set_background(GTK_CLIST(fontsel->font_style_clist),
1203 for (tmpstyle = style; tmpstyle < font->nstyles; tmpstyle++)
1205 if (styles[tmpstyle].flags & GTK_FONT_DISPLAYED
1206 || charset_index != styles[tmpstyle].properties[CHARSET])
1209 styles[tmpstyle].flags |= GTK_FONT_DISPLAYED;
1211 weight_index = styles[tmpstyle].properties[WEIGHT];
1212 slant_index = styles[tmpstyle].properties[SLANT];
1213 set_width_index = styles[tmpstyle].properties[SET_WIDTH];
1214 spacing_index = styles[tmpstyle].properties[SPACING];
1215 weight = fontsel_info->properties[WEIGHT] [weight_index];
1216 slant = fontsel_info->properties[SLANT] [slant_index];
1217 set_width = fontsel_info->properties[SET_WIDTH][set_width_index];
1218 spacing = fontsel_info->properties[SPACING] [spacing_index];
1220 /* Convert '(nil)' weights to 'regular', since it looks nicer. */
1221 if (!g_strcasecmp(weight, N_("(nil)"))) weight = N_("regular");
1223 /* We don't show default values or (nil) in the other properties. */
1224 if (!g_strcasecmp(slant, "r")) slant = NULL;
1225 else if (!g_strcasecmp(slant, "(nil)")) slant = NULL;
1226 else if (!g_strcasecmp(slant, "i")) slant = N_("italic");
1227 else if (!g_strcasecmp(slant, "o")) slant = N_("oblique");
1228 else if (!g_strcasecmp(slant, "ri")) slant = N_("reverse italic");
1229 else if (!g_strcasecmp(slant, "ro")) slant = N_("reverse oblique");
1230 else if (!g_strcasecmp(slant, "ot")) slant = N_("other");
1232 if (!g_strcasecmp(set_width, "normal")) set_width = NULL;
1233 else if (!g_strcasecmp(set_width, "(nil)")) set_width = NULL;
1235 if (!g_strcasecmp(spacing, "p")) spacing = NULL;
1236 else if (!g_strcasecmp(spacing, "(nil)")) spacing = NULL;
1237 else if (!g_strcasecmp(spacing, "m")) spacing = N_("[M]");
1238 else if (!g_strcasecmp(spacing, "c")) spacing = N_("[C]");
1240 /* Add the strings together, making sure there is 1 space between
1242 strcpy(buffer, _(weight));
1245 strcat(buffer, " ");
1246 strcat(buffer, _(slant));
1250 strcat(buffer, " ");
1251 strcat(buffer, _(set_width));
1255 strcat(buffer, " ");
1256 strcat(buffer, _(spacing));
1260 row = gtk_clist_append(GTK_CLIST(fontsel->font_style_clist),
1263 gtk_clist_set_shift(GTK_CLIST(fontsel->font_style_clist), row, 0,
1265 gtk_clist_set_row_data(GTK_CLIST(fontsel->font_style_clist), row,
1266 GINT_TO_POINTER (tmpstyle));
1270 gtk_clist_thaw (GTK_CLIST(fontsel->font_style_clist));
1274 /* This selects a style when the user selects a font. It just uses the first
1275 available style at present. I was thinking of trying to maintain the
1276 selected style, e.g. bold italic, when the user selects different fonts.
1277 However, the interface is so easy to use now I'm not sure it's worth it.
1278 Note: This will load a font. */
1280 gtk_font_selection_select_best_style(GtkFontSelection *fontsel,
1285 gint row, prop, style, matched;
1286 gint best_matched = -1, best_style = -1, best_row = -1;
1288 #ifdef FONTSEL_DEBUG
1289 g_message("In select_best_style\n");
1291 font = &fontsel_info->font_info[fontsel->font_index];
1292 styles = &fontsel_info->font_styles[font->style_index];
1294 for (row = 0; row < GTK_CLIST(fontsel->font_style_clist)->rows; row++)
1296 style = GPOINTER_TO_INT (gtk_clist_get_row_data (GTK_CLIST (fontsel->font_style_clist), row));
1297 /* Skip charset rows. */
1301 /* If we just want the first style, we've got it. */
1310 for (prop = 0; prop < GTK_NUM_STYLE_PROPERTIES; prop++)
1312 if (fontsel->property_values[prop] == styles[style].properties[prop])
1315 if (matched > best_matched)
1317 best_matched = matched;
1322 g_return_if_fail (best_style != -1);
1323 g_return_if_fail (best_row != -1);
1325 fontsel->style = best_style;
1327 for (prop = 0; prop < GTK_NUM_STYLE_PROPERTIES; prop++)
1328 fontsel->property_values[prop] = styles[fontsel->style].properties[prop];
1330 gtk_clist_select_row(GTK_CLIST(fontsel->font_style_clist), best_row, 0);
1331 if (gtk_clist_row_is_visible(GTK_CLIST(fontsel->font_style_clist), best_row)
1332 != GTK_VISIBILITY_FULL)
1333 gtk_clist_moveto(GTK_CLIST(fontsel->font_style_clist), best_row, -1,
1335 gtk_font_selection_show_available_sizes (fontsel);
1336 gtk_font_selection_select_best_size (fontsel);
1340 /* This is called when a style is selected in the list. */
1342 gtk_font_selection_select_style (GtkWidget *w,
1345 GdkEventButton *bevent,
1348 GtkFontSelection *fontsel;
1349 FontInfo *font_info;
1355 #ifdef FONTSEL_DEBUG
1356 g_message("In select_style\n");
1358 fontsel = GTK_FONT_SELECTION(data);
1359 font_info = fontsel_info->font_info;
1360 font = &font_info[fontsel->font_index];
1361 styles = &fontsel_info->font_styles[font->style_index];
1363 if (bevent && !GTK_WIDGET_HAS_FOCUS (w))
1364 gtk_widget_grab_focus (w);
1366 /* The style index is stored in the row data, so we just need to copy
1367 the style values into the fontsel and reload the font. */
1368 style = GPOINTER_TO_INT (gtk_clist_get_row_data(GTK_CLIST(fontsel->font_style_clist), row));
1370 /* Don't allow selection of charset rows. */
1373 gtk_clist_unselect_row(GTK_CLIST(fontsel->font_style_clist), row, 0);
1377 gtk_clist_get_text(GTK_CLIST(fontsel->font_style_clist), row, 0, &text);
1378 gtk_entry_set_text(GTK_ENTRY(fontsel->font_style_entry), text);
1380 for (prop = 0; prop < GTK_NUM_STYLE_PROPERTIES; prop++)
1381 fontsel->property_values[prop] = styles[style].properties[prop];
1383 if (fontsel->style == style)
1386 fontsel->style = style;
1387 gtk_font_selection_show_available_sizes (fontsel);
1388 gtk_font_selection_select_best_size (fontsel);
1392 /* This shows all the available sizes in the size clist, according to the
1393 current metric and the current font & style. */
1395 gtk_font_selection_show_available_sizes (GtkFontSelection *fontsel)
1398 FontStyle *styles, *style;
1399 const guint16 *standard_sizes;
1400 guint16 *bitmapped_sizes;
1401 gint nstandard_sizes, nbitmapped_sizes;
1402 gchar buffer[16], *size;
1403 gfloat bitmap_size_float = 0.;
1404 guint16 bitmap_size = 0;
1408 #ifdef FONTSEL_DEBUG
1409 g_message("In show_available_sizes\n");
1411 font = &fontsel_info->font_info[fontsel->font_index];
1412 styles = &fontsel_info->font_styles[font->style_index];
1413 style = &styles[fontsel->style];
1415 standard_sizes = font_sizes;
1416 nstandard_sizes = sizeof(font_sizes) / sizeof(font_sizes[0]);
1417 if (fontsel->metric == GTK_FONT_METRIC_POINTS)
1419 bitmapped_sizes = &fontsel_info->point_sizes[style->point_sizes_index];
1420 nbitmapped_sizes = style->npoint_sizes;
1424 bitmapped_sizes = &fontsel_info->pixel_sizes[style->pixel_sizes_index];
1425 nbitmapped_sizes = style->npixel_sizes;
1428 /* Only show the standard sizes if a scalable font is available. */
1429 type_filter = fontsel->filters[GTK_FONT_FILTER_BASE].font_type
1430 & fontsel->filters[GTK_FONT_FILTER_USER].font_type;
1432 if (!((style->flags & GTK_FONT_SCALABLE_BITMAP
1433 && type_filter & GTK_FONT_SCALABLE_BITMAP)
1434 || (style->flags & GTK_FONT_SCALABLE
1435 && type_filter & GTK_FONT_SCALABLE)))
1436 nstandard_sizes = 0;
1438 gtk_clist_freeze (GTK_CLIST(fontsel->size_clist));
1439 gtk_clist_clear (GTK_CLIST(fontsel->size_clist));
1441 /* Interleave the standard sizes with the bitmapped sizes so we get a list
1442 of ascending sizes. If the metric is points, we have to convert the
1443 decipoints to points. */
1444 while (nstandard_sizes || nbitmapped_sizes)
1448 if (nbitmapped_sizes)
1449 if (fontsel->metric == GTK_FONT_METRIC_POINTS)
1451 if (*bitmapped_sizes % 10 != 0)
1453 bitmap_size = *bitmapped_sizes / 10;
1454 bitmap_size_float = *bitmapped_sizes / 10;
1458 bitmap_size = *bitmapped_sizes;
1459 bitmap_size_float = *bitmapped_sizes;
1462 if (can_match && nstandard_sizes && nbitmapped_sizes
1463 && *standard_sizes == bitmap_size)
1465 sprintf(buffer, "%i *", *standard_sizes);
1471 else if (nstandard_sizes
1472 && (!nbitmapped_sizes
1473 || (gfloat)*standard_sizes < bitmap_size_float))
1475 sprintf(buffer, "%i", *standard_sizes);
1481 if (fontsel->metric == GTK_FONT_METRIC_POINTS)
1483 if (*bitmapped_sizes % 10 == 0)
1484 sprintf(buffer, "%i *", *bitmapped_sizes / 10);
1486 sprintf(buffer, "%i.%i *", *bitmapped_sizes / 10,
1487 *bitmapped_sizes % 10);
1491 sprintf(buffer, "%i *", *bitmapped_sizes);
1497 gtk_clist_append(GTK_CLIST(fontsel->size_clist), &size);
1499 gtk_clist_thaw (GTK_CLIST(fontsel->size_clist));
1503 /* If the user hits return in the font size entry, we change to the new font
1506 gtk_font_selection_size_key_press (GtkWidget *w,
1510 GtkFontSelection *fontsel;
1512 gfloat new_size_float;
1515 #ifdef FONTSEL_DEBUG
1516 g_message("In size_key_press\n");
1518 fontsel = GTK_FONT_SELECTION(data);
1520 if (event->keyval == GDK_Return)
1522 text = gtk_entry_get_text (GTK_ENTRY (fontsel->size_entry));
1523 if (fontsel->metric == GTK_FONT_METRIC_PIXELS)
1525 new_size = atoi (text);
1531 new_size_float = atof (text) * 10;
1532 new_size = (gint) new_size_float;
1537 /* Remember that this size was set explicitly. */
1538 fontsel->selected_size = new_size;
1540 /* Check if the font size has changed, and return if it hasn't. */
1541 if (fontsel->size == new_size)
1544 fontsel->size = new_size;
1545 gtk_font_selection_select_best_size (fontsel);
1553 /* This tries to select the closest size to the current size, though it
1554 may have to change the size if only unscaled bitmaps are available.
1555 Note: this will load a font. */
1557 gtk_font_selection_select_best_size(GtkFontSelection *fontsel)
1560 FontStyle *styles, *style;
1562 gint row, best_row = 0, size, size_fraction, best_size = 0, nmatched;
1563 gboolean found = FALSE;
1568 #ifdef FONTSEL_DEBUG
1569 g_message("In select_best_size\n");
1571 font = &fontsel_info->font_info[fontsel->font_index];
1572 styles = &fontsel_info->font_styles[font->style_index];
1573 style = &styles[fontsel->style];
1575 /* Find the closest size available in the size clist. If the exact size is
1576 in the list set found to TRUE. */
1577 for (row = 0; row < GTK_CLIST(fontsel->size_clist)->rows; row++)
1579 gtk_clist_get_text(GTK_CLIST(fontsel->size_clist), row, 0, &text);
1580 nmatched = sscanf(text, "%i.%i", &size, &size_fraction);
1581 if (fontsel->metric == GTK_FONT_METRIC_POINTS)
1585 size += size_fraction;
1588 if (size == fontsel->selected_size)
1595 else if (best_size == 0
1596 || abs(size - fontsel->selected_size)
1597 < (abs(best_size - fontsel->selected_size)))
1604 /* If we aren't scaling bitmapped fonts and this is a bitmapped font, we
1605 need to use the closest size found. */
1606 type_filter = fontsel->filters[GTK_FONT_FILTER_BASE].font_type
1607 & fontsel->filters[GTK_FONT_FILTER_USER].font_type;
1609 if (!((style->flags & GTK_FONT_SCALABLE_BITMAP
1610 && type_filter & GTK_FONT_SCALABLE_BITMAP)
1611 || (style->flags & GTK_FONT_SCALABLE
1612 && type_filter & GTK_FONT_SCALABLE)))
1617 fontsel->size = best_size;
1618 gtk_clist_moveto(GTK_CLIST(fontsel->size_clist), best_row, -1, 0.5, 0);
1619 gtk_clist_select_row(GTK_CLIST(fontsel->size_clist), best_row, 0);
1623 fontsel->size = fontsel->selected_size;
1624 selection = GTK_CLIST(fontsel->size_clist)->selection;
1626 gtk_clist_unselect_row(GTK_CLIST(fontsel->size_clist),
1627 GPOINTER_TO_INT (selection->data), 0);
1628 gtk_clist_moveto(GTK_CLIST(fontsel->size_clist), best_row, -1, 0.5, 0);
1630 /* Show the size in the size entry. */
1631 if (fontsel->metric == GTK_FONT_METRIC_PIXELS)
1632 sprintf(buffer, "%i", fontsel->size);
1635 if (fontsel->size % 10 == 0)
1636 sprintf(buffer, "%i", fontsel->size / 10);
1638 sprintf(buffer, "%i.%i", fontsel->size / 10, fontsel->size % 10);
1640 gtk_entry_set_text (GTK_ENTRY (fontsel->size_entry), buffer);
1642 gtk_font_selection_load_font (fontsel);
1646 /* This is called when a size is selected in the list. */
1648 gtk_font_selection_select_size (GtkWidget *w,
1651 GdkEventButton *bevent,
1654 GtkFontSelection *fontsel;
1660 #ifdef FONTSEL_DEBUG
1661 g_message("In select_size\n");
1663 fontsel = GTK_FONT_SELECTION(data);
1665 if (bevent && !GTK_WIDGET_HAS_FOCUS (w))
1666 gtk_widget_grab_focus (w);
1668 /* Copy the size from the clist to the size entry, but without the bitmapped
1670 gtk_clist_get_text(GTK_CLIST(fontsel->size_clist), row, 0, &text);
1672 while (i < 15 && (text[i] == '.' || (text[i] >= '0' && text[i] <= '9')))
1674 buffer[i] = text[i];
1678 gtk_entry_set_text(GTK_ENTRY(fontsel->size_entry), buffer);
1680 /* Check if the font size has changed, and return if it hasn't. */
1681 new_size = atoi(text);
1682 if (fontsel->metric == GTK_FONT_METRIC_POINTS)
1685 if (fontsel->size == new_size)
1688 /* If the size was selected by the user we set the selected_size. */
1689 fontsel->selected_size = new_size;
1691 fontsel->size = new_size;
1692 gtk_font_selection_load_font (fontsel);
1696 /* This is called when the pixels or points radio buttons are pressed. */
1698 gtk_font_selection_metric_callback (GtkWidget *w,
1701 GtkFontSelection *fontsel = GTK_FONT_SELECTION(data);
1703 #ifdef FONTSEL_DEBUG
1704 g_message("In metric_callback\n");
1706 if (GTK_TOGGLE_BUTTON(fontsel->pixels_button)->active)
1708 if (fontsel->metric == GTK_FONT_METRIC_PIXELS)
1710 fontsel->metric = GTK_FONT_METRIC_PIXELS;
1711 fontsel->size = (fontsel->size + 5) / 10;
1712 fontsel->selected_size = (fontsel->selected_size + 5) / 10;
1716 if (fontsel->metric == GTK_FONT_METRIC_POINTS)
1718 fontsel->metric = GTK_FONT_METRIC_POINTS;
1719 fontsel->size *= 10;
1720 fontsel->selected_size *= 10;
1722 if (fontsel->font_index != -1)
1724 gtk_font_selection_show_available_sizes (fontsel);
1725 gtk_font_selection_select_best_size (fontsel);
1730 /* This searches the given property table and returns the index of the given
1731 string, or 0, which is the wildcard '*' index, if it's not found. */
1733 gtk_font_selection_field_to_index (gchar **table,
1739 for (i = 0; i < ntable; i++)
1740 if (strcmp (field, table[i]) == 0)
1748 /* This attempts to load the current font, and returns TRUE if it succeeds. */
1750 gtk_font_selection_load_font (GtkFontSelection *fontsel)
1753 gchar *fontname, *label_text;
1756 gdk_font_unref (fontsel->font);
1757 fontsel->font = NULL;
1759 /* If no family has been selected yet, just return FALSE. */
1760 if (fontsel->font_index == -1)
1763 fontname = gtk_font_selection_get_font_name (fontsel);
1766 #ifdef FONTSEL_DEBUG
1767 g_message("Loading: %s\n", fontname);
1769 font = gdk_font_load (fontname);
1774 fontsel->font = font;
1775 /* Make sure the message label is empty, but don't change it unless
1776 it's necessary as it results in a resize of the whole window! */
1777 gtk_label_get(GTK_LABEL(fontsel->message_label), &label_text);
1778 if (strcmp(label_text, ""))
1779 gtk_label_set_text(GTK_LABEL(fontsel->message_label), "");
1780 gtk_font_selection_update_preview (fontsel);
1785 gtk_label_set_text(GTK_LABEL(fontsel->message_label),
1786 _("The selected font is not available."));
1791 gtk_label_set_text(GTK_LABEL(fontsel->message_label),
1792 _("The selected font is not a valid font."));
1799 /* This sets the font in the preview entry to the selected font, and tries to
1800 make sure that the preview entry is a reasonable size, i.e. so that the
1801 text can be seen with a bit of space to spare. But it tries to avoid
1802 resizing the entry every time the font changes.
1803 This also used to shrink the preview if the font size was decreased, but
1804 that made it awkward if the user wanted to resize the window themself. */
1806 gtk_font_selection_update_preview (GtkFontSelection *fontsel)
1808 GtkWidget *preview_entry;
1810 gint text_height, new_height;
1812 #if GDK_WINDOWING == GDK_WINDOWING_X11
1816 #ifdef FONTSEL_DEBUG
1817 g_message("In update_preview\n");
1819 style = gtk_style_new ();
1820 gdk_font_unref (style->font);
1821 style->font = fontsel->font;
1822 gdk_font_ref (style->font);
1824 preview_entry = fontsel->preview_entry;
1825 gtk_widget_set_style (preview_entry, style);
1826 gtk_style_unref(style);
1828 text_height = preview_entry->style->font->ascent
1829 + preview_entry->style->font->descent;
1830 /* We don't ever want to be over MAX_PREVIEW_HEIGHT pixels high. */
1831 new_height = text_height + 20;
1832 if (new_height < INITIAL_PREVIEW_HEIGHT)
1833 new_height = INITIAL_PREVIEW_HEIGHT;
1834 if (new_height > MAX_PREVIEW_HEIGHT)
1835 new_height = MAX_PREVIEW_HEIGHT;
1837 if ((preview_entry->requisition.height < text_height + 10)
1838 || (preview_entry->requisition.height > text_height + 40))
1839 gtk_widget_set_usize(preview_entry, -1, new_height);
1841 /* This sets the preview text, if it hasn't been set already. */
1842 text = gtk_entry_get_text(GTK_ENTRY(fontsel->preview_entry));
1843 if (strlen(text) == 0)
1844 gtk_entry_set_text(GTK_ENTRY(fontsel->preview_entry), PREVIEW_TEXT);
1845 gtk_entry_set_position(GTK_ENTRY(fontsel->preview_entry), 0);
1847 #if GDK_WINDOWING == GDK_WINDOWING_X11
1848 /* If this is a 2-byte font display a message to say it may not be
1849 displayed properly. */
1850 xfs = GDK_FONT_XFONT(fontsel->font);
1851 if (xfs->min_byte1 != 0 || xfs->max_byte1 != 0)
1852 gtk_label_set_text(GTK_LABEL(fontsel->message_label),
1853 _("This is a 2-byte font and may not be displayed correctly."));
1859 gtk_font_selection_switch_page (GtkWidget *w,
1860 GtkNotebookPage *page,
1864 GtkFontSelection *fontsel = GTK_FONT_SELECTION(data);
1866 /* This function strangely gets called when the window is destroyed,
1867 so we check here to see if the notebook is visible. */
1868 if (!GTK_WIDGET_VISIBLE(w))
1872 gtk_font_selection_update_filter(fontsel);
1873 else if (page_num == 1)
1874 gtk_font_selection_show_font_info(fontsel);
1879 gtk_font_selection_show_font_info (GtkFontSelection *fontsel)
1881 #if GDK_WINDOWING == GDK_WINDOWING_X11
1882 Atom font_atom, atom;
1887 gchar field_buffer[XLFD_MAX_FIELD_LEN];
1890 gboolean shown_actual_fields = FALSE;
1892 fontname = gtk_font_selection_get_font_name(fontsel);
1893 gtk_entry_set_text(GTK_ENTRY(fontsel->requested_font_name),
1894 fontname ? fontname : "");
1896 gtk_clist_freeze (GTK_CLIST(fontsel->info_clist));
1897 for (i = 0; i < GTK_XLFD_NUM_FIELDS; i++)
1900 field = gtk_font_selection_get_xlfd_field (fontname, i, field_buffer);
1905 if (i == XLFD_SLANT)
1906 field = gtk_font_selection_expand_slant_code(field);
1907 else if (i == XLFD_SPACING)
1908 field = gtk_font_selection_expand_spacing_code(field);
1910 gtk_clist_set_text(GTK_CLIST(fontsel->info_clist), i, 1,
1911 field ? field : "");
1913 #if GDK_WINDOWING == GDK_WINDOWING_X11
1916 font_atom = XInternAtom(GDK_DISPLAY(), "FONT", True);
1917 if (font_atom != None)
1919 status = XGetFontProperty(GDK_FONT_XFONT(fontsel->font), font_atom,
1923 name = XGetAtomName(GDK_DISPLAY(), atom);
1924 gtk_entry_set_text(GTK_ENTRY(fontsel->actual_font_name), name);
1926 for (i = 0; i < GTK_XLFD_NUM_FIELDS; i++)
1928 field = gtk_font_selection_get_xlfd_field (name, i,
1930 if (i == XLFD_SLANT)
1931 field = gtk_font_selection_expand_slant_code(field);
1932 else if (i == XLFD_SPACING)
1933 field = gtk_font_selection_expand_spacing_code(field);
1934 gtk_clist_set_text(GTK_CLIST(fontsel->info_clist), i, 2,
1935 field ? field : "");
1937 shown_actual_fields = TRUE;
1942 #elif GDK_WINDOWING == GDK_WINDOWING_WIN32
1947 if (GetObject (GDK_FONT_XFONT (fontsel->font),
1948 sizeof (LOGFONT), &logfont) > 0)
1950 name = logfont_to_xlfd (&logfont, logfont.lfHeight, -1, 0);
1951 gtk_entry_set_text (GTK_ENTRY(fontsel->actual_font_name),name);
1952 for (i = 0; i < GTK_XLFD_NUM_FIELDS; i++)
1954 field = gtk_font_selection_get_xlfd_field (name, i,
1956 if (i == XLFD_SLANT)
1957 field = gtk_font_selection_expand_slant_code(field);
1958 else if (i == XLFD_SPACING)
1959 field = gtk_font_selection_expand_spacing_code(field);
1960 gtk_clist_set_text(GTK_CLIST(fontsel->info_clist), i, 2,
1961 field ? field : "");
1963 shown_actual_fields = TRUE;
1969 if (!shown_actual_fields)
1971 gtk_entry_set_text(GTK_ENTRY(fontsel->actual_font_name), "");
1972 for (i = 0; i < GTK_XLFD_NUM_FIELDS; i++)
1974 gtk_clist_set_text(GTK_CLIST(fontsel->info_clist), i, 2,
1975 fontname ? _("(unknown)") : "");
1978 gtk_clist_thaw (GTK_CLIST(fontsel->info_clist));
1984 gtk_font_selection_expand_slant_code(gchar *slant)
1986 if (!g_strcasecmp(slant, "r")) return(_("roman"));
1987 else if (!g_strcasecmp(slant, "i")) return(_("italic"));
1988 else if (!g_strcasecmp(slant, "o")) return(_("oblique"));
1989 else if (!g_strcasecmp(slant, "ri")) return(_("reverse italic"));
1990 else if (!g_strcasecmp(slant, "ro")) return(_("reverse oblique"));
1991 else if (!g_strcasecmp(slant, "ot")) return(_("other"));
1996 gtk_font_selection_expand_spacing_code(gchar *spacing)
1998 if (!g_strcasecmp(spacing, "p")) return(_("proportional"));
1999 else if (!g_strcasecmp(spacing, "m")) return(_("monospaced"));
2000 else if (!g_strcasecmp(spacing, "c")) return(_("char cell"));
2005 /*****************************************************************************
2006 * These functions all deal with the Filter page and filtering the fonts.
2007 *****************************************************************************/
2009 /* This is called when an item is selected in one of the filter clists.
2010 We make sure that the first row of the clist, i.e. the wildcard '*', is
2011 selected if and only if none of the other items are selected.
2012 Also doesn't allow selections of values filtered out by base filter.
2013 We may need to be careful about triggering other signals. */
2015 gtk_font_selection_select_filter (GtkWidget *w,
2018 GdkEventButton *bevent,
2019 GtkFontSelection *fontsel)
2021 gint i, prop, index;
2025 for (i = 1; i < GTK_CLIST(w)->rows; i++)
2026 gtk_clist_unselect_row(GTK_CLIST(w), i, 0);
2030 /* Find out which property this is. */
2031 for (prop = 0; prop < GTK_NUM_FONT_PROPERTIES; prop++)
2032 if (fontsel->filter_clists[prop] == w)
2034 index = GPOINTER_TO_INT (gtk_clist_get_row_data(GTK_CLIST(w), row));
2035 if (gtk_font_selection_filter_state (fontsel, GTK_FONT_FILTER_BASE,
2036 prop, index) == NOT_FILTERED)
2037 gtk_clist_unselect_row(GTK_CLIST(w), row, 0);
2039 gtk_clist_unselect_row(GTK_CLIST(w), 0, 0);
2044 /* Here a filter item is being deselected. If there are now no items selected
2045 we select the first '*' item, unless that it is the item being deselected,
2046 in which case we select all of the other items. This makes it easy to
2047 select all items in the list except one or two. */
2049 gtk_font_selection_unselect_filter (GtkWidget *w,
2052 GdkEventButton *bevent,
2053 GtkFontSelection *fontsel)
2055 gint i, prop, index;
2057 if (!GTK_CLIST(w)->selection)
2061 /* Find out which property this is. */
2062 for (prop = 0; prop < GTK_NUM_FONT_PROPERTIES; prop++)
2063 if (fontsel->filter_clists[prop] == w)
2066 for (i = 1; i < GTK_CLIST(w)->rows; i++)
2068 index = GPOINTER_TO_INT (gtk_clist_get_row_data(GTK_CLIST(w),
2070 if (gtk_font_selection_filter_state (fontsel,
2071 GTK_FONT_FILTER_BASE,
2074 gtk_clist_select_row(GTK_CLIST(w), i, 0);
2079 gtk_clist_select_row(GTK_CLIST(w), 0, 0);
2085 /* This is called when the main notebook page is selected. It checks if the
2086 filter has changed, an if so it creates the filter settings, and filters the
2087 fonts shown. If an empty filter (all '*'s) is applied, then filtering is
2090 gtk_font_selection_update_filter (GtkFontSelection *fontsel)
2094 gboolean default_filter = TRUE, filter_changed = FALSE;
2095 gint prop, nselected, i, row, index;
2096 GtkFontFilter *filter = &fontsel->filters[GTK_FONT_FILTER_USER];
2097 gint base_font_type, user_font_type, new_font_type;
2099 #ifdef FONTSEL_DEBUG
2100 g_message("In update_filter\n");
2103 /* Check if the user filter has changed, and also if it is the default
2104 filter, i.e. bitmap & scalable fonts and all '*'s selected.
2105 We only look at the bits which are not already filtered out by the base
2106 filter, since that overrides the user filter. */
2107 base_font_type = fontsel->filters[GTK_FONT_FILTER_BASE].font_type
2109 user_font_type = fontsel->filters[GTK_FONT_FILTER_USER].font_type
2111 new_font_type = GTK_TOGGLE_BUTTON(fontsel->type_bitmaps_button)->active
2112 ? GTK_FONT_BITMAP : 0;
2113 new_font_type |= (GTK_TOGGLE_BUTTON(fontsel->type_scalable_button)->active
2114 ? GTK_FONT_SCALABLE : 0);
2115 new_font_type |= (GTK_TOGGLE_BUTTON(fontsel->type_scaled_bitmaps_button)->active ? GTK_FONT_SCALABLE_BITMAP : 0);
2116 new_font_type &= base_font_type;
2117 new_font_type |= (~base_font_type & user_font_type);
2118 if (new_font_type != (GTK_FONT_BITMAP | GTK_FONT_SCALABLE))
2119 default_filter = FALSE;
2121 if (new_font_type != user_font_type)
2122 filter_changed = TRUE;
2123 fontsel->filters[GTK_FONT_FILTER_USER].font_type = new_font_type;
2125 for (prop = 0; prop < GTK_NUM_FONT_PROPERTIES; prop++)
2127 clist = fontsel->filter_clists[prop];
2128 selection = GTK_CLIST(clist)->selection;
2129 nselected = g_list_length(selection);
2130 if (nselected != 1 || GPOINTER_TO_INT (selection->data) != 0)
2132 default_filter = FALSE;
2134 if (filter->property_nfilters[prop] != nselected)
2135 filter_changed = TRUE;
2138 for (i = 0; i < nselected; i++)
2140 row = GPOINTER_TO_INT (selection->data);
2141 index = GPOINTER_TO_INT (gtk_clist_get_row_data (GTK_CLIST (clist), row));
2142 if (filter->property_filters[prop][i] != index)
2143 filter_changed = TRUE;
2144 selection = selection->next;
2150 if (filter->property_nfilters[prop] != 0)
2151 filter_changed = TRUE;
2155 /* If the filter hasn't changed we just return. */
2156 if (!filter_changed)
2159 #ifdef FONTSEL_DEBUG
2160 g_message(" update_fonts: filter has changed\n");
2163 /* Free the old filter data and create the new arrays. */
2164 for (prop = 0; prop < GTK_NUM_FONT_PROPERTIES; prop++)
2166 g_free(filter->property_filters[prop]);
2168 clist = fontsel->filter_clists[prop];
2169 selection = GTK_CLIST(clist)->selection;
2170 nselected = g_list_length(selection);
2171 if (nselected == 1 && GPOINTER_TO_INT (selection->data) == 0)
2173 filter->property_filters[prop] = NULL;
2174 filter->property_nfilters[prop] = 0;
2178 filter->property_filters[prop] = g_new(guint16, nselected);
2179 filter->property_nfilters[prop] = nselected;
2180 for (i = 0; i < nselected; i++)
2182 row = GPOINTER_TO_INT (selection->data);
2183 index = GPOINTER_TO_INT (gtk_clist_get_row_data (GTK_CLIST (clist), row));
2184 filter->property_filters[prop][i] = index;
2185 selection = selection->next;
2190 /* Set the 'Reset Filter' button sensitive if a filter is in effect, and
2191 also set the label above the font list to show this as well. */
2194 gtk_widget_set_sensitive(fontsel->filter_button, FALSE);
2195 gtk_label_set_text(GTK_LABEL(fontsel->font_label), _("Font:"));
2199 gtk_widget_set_sensitive(fontsel->filter_button, TRUE);
2200 gtk_label_set_text(GTK_LABEL(fontsel->font_label), _("Font: (Filter Applied)"));
2202 gtk_font_selection_show_available_fonts(fontsel);
2206 /* This shows all the available fonts in the font clist. */
2208 gtk_font_selection_show_available_fonts (GtkFontSelection *fontsel)
2210 FontInfo *font_info, *font;
2211 GtkFontFilter *filter;
2212 gint nfonts, i, j, k, row, style, font_row = -1;
2213 gchar font_buffer[XLFD_MAX_FIELD_LEN * 2 + 4];
2215 gboolean matched, matched_style;
2217 #ifdef FONTSEL_DEBUG
2218 g_message("In show_available_fonts\n");
2220 font_info = fontsel_info->font_info;
2221 nfonts = fontsel_info->nfonts;
2223 /* Filter the list of fonts. */
2224 gtk_clist_freeze (GTK_CLIST(fontsel->font_clist));
2225 gtk_clist_clear (GTK_CLIST(fontsel->font_clist));
2226 for (i = 0; i < nfonts; i++)
2228 font = &font_info[i];
2230 /* Check if the foundry passes through all filters. */
2232 for (k = 0; k < GTK_NUM_FONT_FILTERS; k++)
2234 filter = &fontsel->filters[k];
2236 if (filter->property_nfilters[FOUNDRY] != 0)
2239 for (j = 0; j < filter->property_nfilters[FOUNDRY]; j++)
2241 if (font->foundry == filter->property_filters[FOUNDRY][j])
2256 /* Now check if the other properties are matched in at least one style.*/
2257 matched_style = FALSE;
2258 for (style = 0; style < font->nstyles; style++)
2260 if (gtk_font_selection_style_visible(fontsel, font, style))
2262 matched_style = TRUE;
2269 /* Insert the font in the clist. */
2270 if ((i > 0 && font->family == font_info[i-1].family)
2271 || (i < nfonts - 1 && font->family == font_info[i+1].family))
2273 sprintf(font_buffer, "%s (%s)", font->family,
2274 fontsel_info->properties[FOUNDRY][font->foundry]);
2275 font_item = font_buffer;
2276 row = gtk_clist_append(GTK_CLIST(fontsel->font_clist), &font_item);
2280 row = gtk_clist_append(GTK_CLIST(fontsel->font_clist),
2283 gtk_clist_set_row_data(GTK_CLIST(fontsel->font_clist), row,
2284 GINT_TO_POINTER (i));
2285 if (fontsel->font_index == i)
2288 gtk_clist_thaw (GTK_CLIST(fontsel->font_clist));
2290 /* If the currently-selected font isn't in the new list, reset the
2294 fontsel->font_index = -1;
2296 gdk_font_unref(fontsel->font);
2297 fontsel->font = NULL;
2298 gtk_entry_set_text(GTK_ENTRY(fontsel->font_entry), "");
2299 gtk_clist_clear (GTK_CLIST(fontsel->font_style_clist));
2300 gtk_entry_set_text(GTK_ENTRY(fontsel->font_style_entry), "");
2304 gtk_clist_select_row(GTK_CLIST(fontsel->font_clist), font_row, 0);
2305 if (gtk_clist_row_is_visible(GTK_CLIST(fontsel->font_clist), font_row)
2306 != GTK_VISIBILITY_FULL)
2307 gtk_clist_moveto(GTK_CLIST(fontsel->font_clist), font_row, -1, 0.5, 0);
2309 gtk_font_selection_show_available_styles (fontsel);
2310 gtk_font_selection_select_best_style (fontsel, FALSE);
2314 /* Returns TRUE if the style is not currently filtered out. */
2316 gtk_font_selection_style_visible(GtkFontSelection *fontsel,
2320 FontStyle *styles, *style;
2321 GtkFontFilter *filter;
2327 styles = &fontsel_info->font_styles[font->style_index];
2328 style = &styles[style_index];
2330 /* Check if font_type of style is filtered. */
2331 type_filter = fontsel->filters[GTK_FONT_FILTER_BASE].font_type
2332 & fontsel->filters[GTK_FONT_FILTER_USER].font_type;
2333 if (!(style->flags & type_filter))
2336 for (prop = 0; prop < GTK_NUM_STYLE_PROPERTIES; prop++)
2338 value = style->properties[prop];
2340 /* Check each filter. */
2341 for (i = 0; i < GTK_NUM_FONT_FILTERS; i++)
2343 filter = &fontsel->filters[i];
2345 if (filter->property_nfilters[prop] != 0)
2348 for (j = 0; j < filter->property_nfilters[prop]; j++)
2350 if (value == filter->property_filters[prop][j])
2365 /* This resets the font type to bitmap or scalable, and sets all the filter
2366 clists to the wildcard '*' options. */
2368 gtk_font_selection_reset_filter (GtkWidget *w,
2369 GtkFontSelection *fontsel)
2371 gint prop, base_font_type;
2373 fontsel->filters[GTK_FONT_FILTER_USER].font_type = GTK_FONT_BITMAP
2374 | GTK_FONT_SCALABLE;
2376 base_font_type = fontsel->filters[GTK_FONT_FILTER_BASE].font_type;
2377 if (base_font_type & GTK_FONT_BITMAP)
2378 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fontsel->type_bitmaps_button), TRUE);
2379 if (base_font_type & GTK_FONT_SCALABLE)
2380 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fontsel->type_scalable_button), TRUE);
2381 if (base_font_type & GTK_FONT_SCALABLE_BITMAP)
2382 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fontsel->type_scaled_bitmaps_button), FALSE);
2384 for (prop = 0; prop < GTK_NUM_FONT_PROPERTIES; prop++)
2385 gtk_clist_select_row(GTK_CLIST(fontsel->filter_clists[prop]), 0, 0);
2389 /* This clears the filter, showing all fonts and styles again. */
2391 gtk_font_selection_on_clear_filter (GtkWidget *w,
2392 GtkFontSelection *fontsel)
2394 gtk_font_selection_clear_filter(fontsel);
2398 /* This resets the user filter, showing all fonts and styles which pass the
2399 base filter again. Note that the font type is set to bitmaps and scalable
2400 fonts - scaled bitmaps are not shown. */
2402 gtk_font_selection_clear_filter (GtkFontSelection *fontsel)
2404 GtkFontFilter *filter;
2407 #ifdef FONTSEL_DEBUG
2408 g_message("In clear_filter\n");
2410 /* Clear the filter data. */
2411 filter = &fontsel->filters[GTK_FONT_FILTER_USER];
2412 filter->font_type = GTK_FONT_BITMAP | GTK_FONT_SCALABLE;
2413 for (prop = 0; prop < GTK_NUM_FONT_PROPERTIES; prop++)
2415 g_free(filter->property_filters[prop]);
2416 filter->property_filters[prop] = NULL;
2417 filter->property_nfilters[prop] = 0;
2420 /* Select all the '*'s on the filter page. */
2421 gtk_font_selection_reset_filter(NULL, fontsel);
2423 /* Update the main notebook page. */
2424 gtk_widget_set_sensitive(fontsel->filter_button, FALSE);
2425 gtk_label_set_text(GTK_LABEL(fontsel->font_label), _("Font:"));
2427 gtk_font_selection_show_available_fonts(fontsel);
2432 gtk_font_selection_set_filter (GtkFontSelection *fontsel,
2433 GtkFontFilterType filter_type,
2434 GtkFontType font_type,
2442 GtkFontFilter *filter;
2443 gchar **filter_strings [GTK_NUM_FONT_PROPERTIES];
2444 gchar *filter_string;
2445 gchar *property, *property_alt;
2446 gint prop, nfilters, i, j, num_found;
2447 gint base_font_type, user_font_type;
2448 gboolean filter_set;
2450 /* Put them into an array so we can use a simple loop. */
2451 filter_strings[FOUNDRY] = foundries;
2452 filter_strings[WEIGHT] = weights;
2453 filter_strings[SLANT] = slants;
2454 filter_strings[SET_WIDTH] = setwidths;
2455 filter_strings[SPACING] = spacings;
2456 filter_strings[CHARSET] = charsets;
2458 filter = &fontsel->filters[filter_type];
2459 filter->font_type = font_type;
2461 /* Free the old filter data, and insert the new. */
2462 for (prop = 0; prop < GTK_NUM_FONT_PROPERTIES; prop++)
2464 g_free(filter->property_filters[prop]);
2465 filter->property_filters[prop] = NULL;
2466 filter->property_nfilters[prop] = 0;
2468 if (filter_strings[prop])
2470 /* Count how many items in the new array. */
2472 while (filter_strings[prop][nfilters])
2475 filter->property_filters[prop] = g_new(guint16, nfilters);
2476 filter->property_nfilters[prop] = 0;
2478 /* Now convert the strings to property indices. */
2480 for (i = 0; i < nfilters; i++)
2482 filter_string = filter_strings[prop][i];
2483 for (j = 0; j < fontsel_info->nproperties[prop]; j++)
2485 property = _(fontsel_info->properties[prop][j]);
2486 property_alt = NULL;
2488 property_alt = gtk_font_selection_expand_slant_code(property);
2489 else if (prop == SPACING)
2490 property_alt = gtk_font_selection_expand_spacing_code(property);
2491 if (!strcmp (filter_string, property)
2492 || (property_alt && !strcmp (filter_string, property_alt)))
2494 filter->property_filters[prop][num_found] = j;
2500 filter->property_nfilters[prop] = num_found;
2504 /* Now set the clists on the filter page according to the new filter. */
2505 gtk_font_selection_update_filter_lists (fontsel);
2507 if (filter_type == GTK_FONT_FILTER_BASE)
2509 user_font_type = fontsel->filters[GTK_FONT_FILTER_USER].font_type;
2510 if (font_type & GTK_FONT_BITMAP)
2512 gtk_widget_set_sensitive (fontsel->type_bitmaps_button, TRUE);
2513 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fontsel->type_bitmaps_button), user_font_type & GTK_FONT_BITMAP);
2517 gtk_widget_set_sensitive (fontsel->type_bitmaps_button, FALSE);
2518 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fontsel->type_bitmaps_button), FALSE);
2521 if (font_type & GTK_FONT_SCALABLE)
2523 gtk_widget_set_sensitive (fontsel->type_scalable_button, TRUE);
2524 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fontsel->type_scalable_button), user_font_type & GTK_FONT_SCALABLE);
2528 gtk_widget_set_sensitive (fontsel->type_scalable_button, FALSE);
2529 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fontsel->type_scalable_button), FALSE);
2532 if (font_type & GTK_FONT_SCALABLE_BITMAP)
2534 gtk_widget_set_sensitive (fontsel->type_scaled_bitmaps_button, TRUE);
2535 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fontsel->type_scaled_bitmaps_button), user_font_type & GTK_FONT_SCALABLE_BITMAP);
2539 gtk_widget_set_sensitive (fontsel->type_scaled_bitmaps_button, FALSE);
2540 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fontsel->type_scaled_bitmaps_button), FALSE);
2545 base_font_type = fontsel->filters[GTK_FONT_FILTER_BASE].font_type;
2546 if (base_font_type & GTK_FONT_BITMAP)
2547 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fontsel->type_bitmaps_button), font_type & GTK_FONT_BITMAP);
2549 if (base_font_type & GTK_FONT_SCALABLE)
2550 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fontsel->type_scalable_button), font_type & GTK_FONT_SCALABLE);
2552 if (base_font_type & GTK_FONT_SCALABLE_BITMAP)
2553 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fontsel->type_scaled_bitmaps_button), font_type & GTK_FONT_SCALABLE_BITMAP);
2555 /* If the user filter is not the default, make the 'Reset Filter' button
2558 if (font_type != (GTK_FONT_BITMAP | GTK_FONT_SCALABLE))
2560 for (prop = 0; prop < GTK_NUM_FONT_PROPERTIES; prop++)
2562 if (filter->property_nfilters[prop] != 0)
2566 gtk_widget_set_sensitive (fontsel->filter_button, TRUE);
2569 gtk_font_selection_show_available_fonts (fontsel);
2573 /* This sets the colour of each property in the filter clists according to
2574 the base filter. i.e. Filtered properties are shown as insensitive. */
2576 gtk_font_selection_update_filter_lists (GtkFontSelection *fontsel)
2579 GdkColor *inactive_fg, *inactive_bg, *fg, *bg;
2580 gint prop, row, index;
2582 /* We have to make sure the clist is realized to use the colours. */
2583 for (prop = 0; prop < GTK_NUM_FONT_PROPERTIES; prop++)
2585 clist = fontsel->filter_clists[prop];
2586 gtk_widget_realize (clist);
2587 inactive_fg = &clist->style->fg[GTK_STATE_INSENSITIVE];
2588 inactive_bg = &clist->style->bg[GTK_STATE_INSENSITIVE];
2589 for (row = 1; row < GTK_CLIST(clist)->rows; row++)
2591 index = GPOINTER_TO_INT (gtk_clist_get_row_data(GTK_CLIST(clist),
2593 /* Set the colour according to the base filter. */
2594 if (gtk_font_selection_filter_state (fontsel, GTK_FONT_FILTER_BASE,
2595 prop, index) == NOT_FILTERED)
2605 gtk_clist_set_foreground(GTK_CLIST(clist), row, fg);
2606 gtk_clist_set_background(GTK_CLIST(clist), row, bg);
2608 /* Set the selection state according to the user filter. */
2609 if (gtk_font_selection_filter_state (fontsel, GTK_FONT_FILTER_USER,
2610 prop, index) == FILTERED
2612 gtk_clist_select_row (GTK_CLIST (clist), row, 0);
2614 gtk_clist_unselect_row (GTK_CLIST (clist), row, 0);
2620 /* Returns whether a property value is in the filter or not, or if the
2621 property has no filter set. */
2622 static GtkFontPropertyFilterState
2623 gtk_font_selection_filter_state (GtkFontSelection *fontsel,
2624 GtkFontFilterType filter_type,
2628 GtkFontFilter *filter;
2631 filter = &fontsel->filters[filter_type];
2632 if (filter->property_nfilters[property] == 0)
2635 for (i = 0; i < filter->property_nfilters[property]; i++)
2637 if (filter->property_filters[property][i] == index)
2640 return NOT_FILTERED;
2644 #if GDK_WINDOWING == GDK_WINDOWING_WIN32
2646 static gint num_fonts;
2647 static gint font_names_size;
2648 static gchar **xfontnames;
2652 logfont_to_xlfd (const LOGFONT *lfp,
2657 const gchar *weight;
2658 const gchar *registry, *encoding;
2660 static int logpixelsy = 0;
2661 gchar facename[LF_FACESIZE*3];
2664 if (logpixelsy == 0)
2666 HDC hdc = GetDC (NULL);
2667 logpixelsy = GetDeviceCaps (hdc, LOGPIXELSY);
2668 ReleaseDC (NULL, hdc);
2671 /* Don't use _() here, only N_(), the actual translation is done elsewhere */
2672 if (lfp->lfWeight >= FW_HEAVY)
2673 weight = N_("heavy");
2674 else if (lfp->lfWeight >= FW_EXTRABOLD)
2675 weight = N_("extrabold");
2676 else if (lfp->lfWeight >= FW_BOLD)
2677 weight = N_("bold");
2678 else if (lfp->lfWeight >= FW_DEMIBOLD)
2679 weight = N_("demibold");
2680 else if (lfp->lfWeight >= FW_MEDIUM)
2681 weight = N_("medium");
2682 else if (lfp->lfWeight >= FW_NORMAL)
2683 weight = N_("normal");
2684 else if (lfp->lfWeight >= FW_LIGHT)
2685 weight = N_("light");
2686 else if (lfp->lfWeight >= FW_EXTRALIGHT)
2687 weight = N_("extralight");
2688 else if (lfp->lfWeight >= FW_THIN)
2689 weight = N_("thin");
2691 weight = N_("regular");
2693 if (lfp->lfCharSet == ANSI_CHARSET)
2695 registry = "iso8859";
2700 registry = "windows";
2701 if (lfp->lfCharSet == DEFAULT_CHARSET)
2702 encoding = "default";
2703 else if (lfp->lfCharSet == SYMBOL_CHARSET)
2704 encoding = "symbol";
2705 else if (lfp->lfCharSet == SHIFTJIS_CHARSET)
2706 encoding = "shiftjis";
2707 else if (lfp->lfCharSet == GB2312_CHARSET)
2708 encoding = "gb2312";
2709 else if (lfp->lfCharSet == HANGEUL_CHARSET)
2710 encoding = "hangeul";
2711 else if (lfp->lfCharSet == CHINESEBIG5_CHARSET)
2712 encoding = "chinesebig5";
2713 else if (lfp->lfCharSet == OEM_CHARSET)
2715 else if (lfp->lfCharSet == JOHAB_CHARSET)
2717 else if (lfp->lfCharSet == HEBREW_CHARSET)
2718 encoding = "hebrew";
2719 else if (lfp->lfCharSet == ARABIC_CHARSET)
2720 encoding = "arabic";
2721 else if (lfp->lfCharSet == GREEK_CHARSET)
2723 else if (lfp->lfCharSet == TURKISH_CHARSET)
2724 encoding = "turkish";
2725 else if (lfp->lfCharSet == THAI_CHARSET)
2727 else if (lfp->lfCharSet == EASTEUROPE_CHARSET)
2728 encoding = "easteurope";
2729 else if (lfp->lfCharSet == RUSSIAN_CHARSET)
2730 encoding = "russian";
2731 else if (lfp->lfCharSet == MAC_CHARSET)
2733 else if (lfp->lfCharSet == BALTIC_CHARSET)
2734 encoding = "baltic";
2736 encoding = "unknown";
2739 point_size = (int) (((double) size/logpixelsy) * 720.);
2744 /* Replace illegal characters with hex escapes. */
2746 q = lfp->lfFaceName;
2749 if (*q == '-' || *q == '*' || *q == '?' || *q == '%')
2750 p += sprintf (p, "%%%.02x", *q);
2757 return g_strdup_printf
2758 ("-%s-%s-%s-%s-%s-%s-%d-%d-%d-%d-%s-%d-%s-%s",
2763 ((lfp->lfPitchAndFamily & 0xF0) == FF_ROMAN
2764 || (lfp->lfPitchAndFamily & 0xF0) == FF_SCRIPT ?
2772 ((lfp->lfPitchAndFamily & 0x03) == FIXED_PITCH ? "m" : "p"),
2774 registry, encoding);
2778 InnerEnumFontFamExProc (const LOGFONT *lfp,
2779 const TEXTMETRIC *metrics,
2785 if (fontType == TRUETYPE_FONTTYPE)
2791 size = lfp->lfHeight;
2795 if (num_fonts == font_names_size)
2797 font_names_size *= 2;
2798 xfontnames = g_realloc (xfontnames, font_names_size * sizeof (gchar *));
2800 xfontnames[num_fonts-1] =
2801 logfont_to_xlfd (lfp, size, 0, 0);
2806 EnumFontFamExProc (const LOGFONT *lfp,
2807 const TEXTMETRIC *metrics,
2811 if (fontType == TRUETYPE_FONTTYPE)
2814 lf.lfPitchAndFamily = 0;
2815 EnumFontFamiliesEx (hdc, &lf, InnerEnumFontFamExProc, 0, 0);
2818 InnerEnumFontFamExProc (lfp, metrics, fontType, lParam);
2824 /*****************************************************************************
2825 * These functions all deal with creating the main class arrays containing
2826 * the data about all available fonts.
2827 *****************************************************************************/
2829 gtk_font_selection_get_fonts (void)
2831 #if GDK_WINDOWING == GDK_WINDOWING_X11
2834 #elif GDK_WINDOWING == GDK_WINDOWING_WIN32
2838 gchar **xfontnames = NULL;
2843 gint i, prop, style, size;
2844 gint npixel_sizes = 0, npoint_sizes = 0;
2846 FontStyle *current_style, *prev_style, *tmp_style;
2847 gboolean matched_style, found_size;
2848 gint pixels, points, res_x, res_y;
2849 gchar field_buffer[XLFD_MAX_FIELD_LEN];
2852 guint16 *pixel_sizes, *point_sizes, *tmp_sizes;
2854 fontsel_info = g_new (GtkFontSelInfo, 1);
2856 #if GDK_WINDOWING == GDK_WINDOWING_X11
2857 /* Get a maximum of MAX_FONTS fontnames from the X server.
2858 Use "-*" as the pattern rather than "-*-*-*-*-*-*-*-*-*-*-*-*-*-*" since
2859 the latter may result in fonts being returned which don't actually exist.
2860 xlsfonts also uses "*" so I think it's OK. "-*" gets rid of aliases. */
2861 xfontnames = XListFonts (GDK_DISPLAY(), "-*", MAX_FONTS, &num_fonts);
2862 /* Output a warning if we actually get MAX_FONTS fonts. */
2863 if (num_fonts == MAX_FONTS)
2864 g_warning(_("MAX_FONTS exceeded. Some fonts may be missing."));
2866 #elif GDK_WINDOWING == GDK_WINDOWING_WIN32
2869 font_names_size = 100;
2870 xfontnames = g_new (gchar *, font_names_size);
2871 logfont.lfCharSet = DEFAULT_CHARSET;
2872 logfont.lfFaceName[0] = '\0';
2873 logfont.lfPitchAndFamily = 0;
2874 EnumFontFamiliesEx (hdc, &logfont, EnumFontFamExProc, 0, 0);
2875 ReleaseDC (NULL, hdc);
2878 /* The maximum size of all these tables is the number of font names
2879 returned. We realloc them later when we know exactly how many
2880 unique entries there are. */
2881 fontsel_info->font_info = g_new (FontInfo, num_fonts);
2882 fontsel_info->font_styles = g_new (FontStyle, num_fonts);
2883 fontsel_info->pixel_sizes = g_new (guint16, num_fonts);
2884 fontsel_info->point_sizes = g_new (guint16, num_fonts);
2886 fontnames = g_new (GSList*, num_fonts);
2888 /* Create the initial arrays for the property value strings, though they
2889 may be realloc'ed later. Put the wildcard '*' in the first elements. */
2890 for (prop = 0; prop < GTK_NUM_FONT_PROPERTIES; prop++)
2892 fontsel_info->properties[prop] = g_new(gchar*, PROPERTY_ARRAY_INCREMENT);
2893 fontsel_info->space_allocated[prop] = PROPERTY_ARRAY_INCREMENT;
2894 fontsel_info->nproperties[prop] = 1;
2895 fontsel_info->properties[prop][0] = "*";
2899 /* Insert the font families into the main table, sorted by family and
2900 foundry (fonts with different foundries are placed in seaparate FontInfos.
2901 All fontnames in each family + foundry are placed into the fontnames
2903 fontsel_info->nfonts = 0;
2904 for (i = 0; i < num_fonts; i++)
2906 #ifdef FONTSEL_DEBUG
2907 g_message("%s\n", xfontnames[i]);
2909 if (gtk_font_selection_is_xlfd_font_name (xfontnames[i]))
2910 gtk_font_selection_insert_font (fontnames, &fontsel_info->nfonts, xfontnames[i]);
2913 #ifdef FONTSEL_DEBUG
2914 g_warning("Skipping invalid font: %s", xfontnames[i]);
2920 /* Since many font names will be in the same FontInfo not all of the
2921 allocated FontInfo table will be used, so we will now reallocate it
2922 with the real size. */
2923 fontsel_info->font_info = g_realloc(fontsel_info->font_info,
2924 sizeof(FontInfo) * fontsel_info->nfonts);
2927 /* Now we work out which choices of weight/slant etc. are valid for each
2929 fontsel_info->nstyles = 0;
2930 current_style = fontsel_info->font_styles;
2931 for (i = 0; i < fontsel_info->nfonts; i++)
2933 font = &fontsel_info->font_info[i];
2935 /* Use the next free position in the styles array. */
2936 font->style_index = fontsel_info->nstyles;
2938 /* Now step through each of the fontnames with this family, and create
2939 a style for each fontname. Each style contains the index into the
2940 weights/slants etc. arrays, and a number of pixel/point sizes. */
2942 temp_list = fontnames[i];
2945 fontname = temp_list->data;
2946 temp_list = temp_list->next;
2948 for (prop = 0; prop < GTK_NUM_STYLE_PROPERTIES; prop++)
2950 current_style->properties[prop]
2951 = gtk_font_selection_insert_field (fontname, prop);
2953 current_style->pixel_sizes_index = npixel_sizes;
2954 current_style->npixel_sizes = 0;
2955 current_style->point_sizes_index = npoint_sizes;
2956 current_style->npoint_sizes = 0;
2957 current_style->flags = 0;
2960 field = gtk_font_selection_get_xlfd_field (fontname, XLFD_PIXELS,
2962 pixels = atoi(field);
2964 field = gtk_font_selection_get_xlfd_field (fontname, XLFD_POINTS,
2966 points = atoi(field);
2968 field = gtk_font_selection_get_xlfd_field (fontname,
2971 res_x = atoi(field);
2973 field = gtk_font_selection_get_xlfd_field (fontname,
2976 res_y = atoi(field);
2978 if (pixels == 0 && points == 0)
2980 if (res_x == 0 && res_y == 0)
2981 flags = GTK_FONT_SCALABLE;
2983 flags = GTK_FONT_SCALABLE_BITMAP;
2986 flags = GTK_FONT_BITMAP;
2988 /* Now we check to make sure that the style is unique. If it isn't
2990 prev_style = fontsel_info->font_styles + font->style_index;
2991 matched_style = FALSE;
2992 while (prev_style < current_style)
2994 matched_style = TRUE;
2995 for (prop = 0; prop < GTK_NUM_STYLE_PROPERTIES; prop++)
2997 if (prev_style->properties[prop]
2998 != current_style->properties[prop])
3000 matched_style = FALSE;
3009 /* If we matched an existing style, we need to add the pixels &
3010 point sizes to the style. If not, we insert the pixel & point
3011 sizes into our new style. Note that we don't add sizes for
3015 prev_style->flags |= flags;
3016 if (flags == GTK_FONT_BITMAP)
3018 pixel_sizes = fontsel_info->pixel_sizes
3019 + prev_style->pixel_sizes_index;
3021 for (size = 0; size < prev_style->npixel_sizes; size++)
3023 if (pixels == *pixel_sizes)
3028 else if (pixels < *pixel_sizes)
3032 /* We need to move all the following pixel sizes up, and also
3033 update the indexes of any following styles. */
3036 for (tmp_sizes = fontsel_info->pixel_sizes + npixel_sizes;
3037 tmp_sizes > pixel_sizes; tmp_sizes--)
3038 *tmp_sizes = *(tmp_sizes - 1);
3040 *pixel_sizes = pixels;
3042 prev_style->npixel_sizes++;
3044 tmp_style = prev_style + 1;
3045 while (tmp_style < current_style)
3047 tmp_style->pixel_sizes_index++;
3052 point_sizes = fontsel_info->point_sizes
3053 + prev_style->point_sizes_index;
3055 for (size = 0; size < prev_style->npoint_sizes; size++)
3057 if (points == *point_sizes)
3062 else if (points < *point_sizes)
3066 /* We need to move all the following point sizes up, and also
3067 update the indexes of any following styles. */
3070 for (tmp_sizes = fontsel_info->point_sizes + npoint_sizes;
3071 tmp_sizes > point_sizes; tmp_sizes--)
3072 *tmp_sizes = *(tmp_sizes - 1);
3074 *point_sizes = points;
3076 prev_style->npoint_sizes++;
3078 tmp_style = prev_style + 1;
3079 while (tmp_style < current_style)
3081 tmp_style->point_sizes_index++;
3089 current_style->flags = flags;
3090 if (flags == GTK_FONT_BITMAP)
3092 fontsel_info->pixel_sizes[npixel_sizes++] = pixels;
3093 current_style->npixel_sizes = 1;
3094 fontsel_info->point_sizes[npoint_sizes++] = points;
3095 current_style->npoint_sizes = 1;
3098 fontsel_info->nstyles++;
3102 g_slist_free(fontnames[i]);
3104 /* Set nstyles to the real value, minus duplicated fontnames.
3105 Note that we aren't using all the allocated memory if fontnames are
3107 font->nstyles = style;
3110 /* Since some repeated styles may be skipped we won't have used all the
3111 allocated space, so we will now reallocate it with the real size. */
3112 fontsel_info->font_styles = g_realloc(fontsel_info->font_styles,
3113 sizeof(FontStyle) * fontsel_info->nstyles);
3114 fontsel_info->pixel_sizes = g_realloc(fontsel_info->pixel_sizes,
3115 sizeof(guint16) * npixel_sizes);
3116 fontsel_info->point_sizes = g_realloc(fontsel_info->point_sizes,
3117 sizeof(guint16) * npoint_sizes);
3120 #if GDK_WINDOWING == GDK_WINDOWING_X11
3121 XFreeFontNames (xfontnames);
3122 #elif GDK_WINDOWING == GDK_WINDOWING_WIN32
3123 for (i = 0; i < num_fonts; i++)
3124 g_free (xfontnames[i]);
3125 g_free (xfontnames);
3128 /* Debugging Output */
3129 /* This outputs all FontInfos. */
3130 #ifdef FONTSEL_DEBUG
3131 g_message("\n\n Font Family Weight Slant Set Width Spacing Charset\n\n");
3132 for (i = 0; i < fontsel_info->nfonts; i++)
3134 FontInfo *font = &fontsel_info->font_info[i];
3135 FontStyle *styles = fontsel_info->font_styles + font->style_index;
3136 for (style = 0; style < font->nstyles; style++)
3138 g_message("%5i %-16.16s ", i, font->family);
3139 for (prop = 0; prop < GTK_NUM_STYLE_PROPERTIES; prop++)
3140 g_message("%-9.9s ",
3141 fontsel_info->properties[prop][styles->properties[prop]]);
3144 if (styles->flags & GTK_FONT_BITMAP)
3145 g_message("Bitmapped font ");
3146 if (styles->flags & GTK_FONT_SCALABLE)
3147 g_message("Scalable font ");
3148 if (styles->flags & GTK_FONT_SCALABLE_BITMAP)
3149 g_message("Scalable-Bitmapped font ");
3152 if (styles->npixel_sizes)
3154 g_message(" Pixel sizes: ");
3155 tmp_sizes = fontsel_info->pixel_sizes + styles->pixel_sizes_index;
3156 for (size = 0; size < styles->npixel_sizes; size++)
3157 g_message("%i ", *tmp_sizes++);
3161 if (styles->npoint_sizes)
3163 g_message(" Point sizes: ");
3164 tmp_sizes = fontsel_info->point_sizes + styles->point_sizes_index;
3165 for (size = 0; size < styles->npoint_sizes; size++)
3166 g_message("%i ", *tmp_sizes++);
3174 /* This outputs all available properties. */
3175 for (prop = 0; prop < GTK_NUM_FONT_PROPERTIES; prop++)
3177 g_message("Property: %s\n", xlfd_field_names[xlfd_index[prop]]);
3178 for (i = 0; i < fontsel_info->nproperties[prop]; i++)
3179 g_message(" %s\n", fontsel_info->properties[prop][i]);
3184 /* This inserts the given fontname into the FontInfo table.
3185 If a FontInfo already exists with the same family and foundry, then the
3186 fontname is added to the FontInfos list of fontnames, else a new FontInfo
3187 is created and inserted in alphabetical order in the table. */
3189 gtk_font_selection_insert_font (GSList *fontnames[],
3195 GSList *temp_fontname;
3197 gboolean family_exists = FALSE;
3201 gchar family_buffer[XLFD_MAX_FIELD_LEN];
3203 table = fontsel_info->font_info;
3205 /* insert a fontname into a table */
3206 family = gtk_font_selection_get_xlfd_field (fontname, XLFD_FAMILY,
3211 foundry = gtk_font_selection_insert_field (fontname, FOUNDRY);
3216 /* Do a binary search to determine if we have already encountered
3217 * a font with this family & foundry. */
3219 while (lower < upper)
3221 middle = (lower + upper) >> 1;
3223 cmp = strcmp (family, table[middle].family);
3224 /* If the family matches we sort by the foundry. */
3227 family_exists = TRUE;
3228 family = table[middle].family;
3229 cmp = strcmp(fontsel_info->properties[FOUNDRY][foundry],
3230 fontsel_info->properties[FOUNDRY][table[middle].foundry]);
3235 fontnames[middle] = g_slist_prepend (fontnames[middle],
3246 /* Add another entry to the table for this new font family */
3247 temp_info.family = family_exists ? family : g_strdup(family);
3248 temp_info.foundry = foundry;
3249 temp_fontname = g_slist_prepend (NULL, fontname);
3253 /* Quickly insert the entry into the table in sorted order
3254 * using a modification of insertion sort and the knowledge
3255 * that the entries proper position in the table was determined
3256 * above in the binary search and is contained in the "lower"
3260 upper = *ntable - 1;
3261 while (lower != upper)
3263 table[upper] = table[upper-1];
3264 fontnames[upper] = fontnames[upper-1];
3268 table[lower] = temp_info;
3269 fontnames[lower] = temp_fontname;
3273 /* This checks that the specified field of the given fontname is in the
3274 appropriate properties array. If not it is added. Thus eventually we get
3275 arrays of all possible weights/slants etc. It returns the array index. */
3277 gtk_font_selection_insert_field (gchar *fontname,
3280 gchar field_buffer[XLFD_MAX_FIELD_LEN];
3284 field = gtk_font_selection_get_xlfd_field (fontname, xlfd_index[prop],
3289 /* If the field is already in the array just return its index. */
3290 for (index = 0; index < fontsel_info->nproperties[prop]; index++)
3291 if (!strcmp(field, fontsel_info->properties[prop][index]))
3294 /* Make sure we have enough space to add the field. */
3295 if (fontsel_info->nproperties[prop] == fontsel_info->space_allocated[prop])
3297 fontsel_info->space_allocated[prop] += PROPERTY_ARRAY_INCREMENT;
3298 fontsel_info->properties[prop] = g_realloc(fontsel_info->properties[prop],
3300 * fontsel_info->space_allocated[prop]);
3303 /* Add the new field. */
3304 index = fontsel_info->nproperties[prop];
3305 fontsel_info->properties[prop][index] = g_strdup(field);
3306 fontsel_info->nproperties[prop]++;
3311 /*****************************************************************************
3312 * These functions are the main public interface for getting/setting the font.
3313 *****************************************************************************/
3316 gtk_font_selection_get_font (GtkFontSelection *fontsel)
3318 g_return_val_if_fail (fontsel != NULL, NULL);
3319 return fontsel->font;
3324 gtk_font_selection_get_font_name (GtkFontSelection *fontsel)
3327 gchar *family_str, *foundry_str;
3328 gchar *property_str[GTK_NUM_STYLE_PROPERTIES];
3331 g_return_val_if_fail (fontsel != NULL, NULL);
3332 g_return_val_if_fail (GTK_IS_FONT_SELECTION (fontsel), NULL);
3334 /* If no family has been selected return NULL. */
3335 if (fontsel->font_index == -1)
3338 font = &fontsel_info->font_info[fontsel->font_index];
3339 family_str = font->family;
3340 foundry_str = fontsel_info->properties[FOUNDRY][font->foundry];
3342 for (prop = 0; prop < GTK_NUM_STYLE_PROPERTIES; prop++)
3345 = fontsel_info->properties[prop][fontsel->property_values[prop]];
3346 if (strcmp (property_str[prop], "(nil)") == 0)
3347 property_str[prop] = "";
3350 return gtk_font_selection_create_xlfd (fontsel->size,
3354 property_str[WEIGHT],
3355 property_str[SLANT],
3356 property_str[SET_WIDTH],
3357 property_str[SPACING],
3358 property_str[CHARSET]);
3362 /* This sets the current font, selecting the appropriate clist rows.
3363 First we check the fontname is valid and try to find the font family
3364 - i.e. the name in the main list. If we can't find that, then just return.
3365 Next we try to set each of the properties according to the fontname.
3366 Finally we select the font family & style in the clists. */
3368 gtk_font_selection_set_font_name (GtkFontSelection *fontsel,
3369 const gchar *fontname)
3371 gchar *family, *field;
3372 gint index, prop, size;
3373 guint16 foundry, value;
3374 gchar family_buffer[XLFD_MAX_FIELD_LEN];
3375 gchar field_buffer[XLFD_MAX_FIELD_LEN];
3378 g_return_val_if_fail (fontsel != NULL, FALSE);
3379 g_return_val_if_fail (GTK_IS_FONT_SELECTION (fontsel), FALSE);
3380 g_return_val_if_fail (fontname != NULL, FALSE);
3382 /* Check it is a valid fontname. */
3383 if (!gtk_font_selection_is_xlfd_font_name(fontname))
3386 family = gtk_font_selection_get_xlfd_field (fontname, XLFD_FAMILY,
3391 field = gtk_font_selection_get_xlfd_field (fontname, XLFD_FOUNDRY,
3393 foundry = gtk_font_selection_field_to_index (fontsel_info->properties[FOUNDRY],
3394 fontsel_info->nproperties[FOUNDRY],
3397 index = gtk_font_selection_find_font(fontsel, family, foundry);
3401 /* Convert the property fields into indices and set them. */
3402 for (prop = 0; prop < GTK_NUM_STYLE_PROPERTIES; prop++)
3404 field = gtk_font_selection_get_xlfd_field (fontname, xlfd_index[prop],
3406 value = gtk_font_selection_field_to_index (fontsel_info->properties[prop],
3407 fontsel_info->nproperties[prop],
3409 fontsel->property_values[prop] = value;
3412 field = gtk_font_selection_get_xlfd_field (fontname, XLFD_POINTS,
3419 fontsel->size = fontsel->selected_size = size;
3420 fontsel->metric = GTK_FONT_METRIC_POINTS;
3421 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(fontsel->points_button),
3424 sprintf (buffer, "%i", size / 10);
3426 sprintf (buffer, "%i.%i", size / 10, size % 10);
3430 field = gtk_font_selection_get_xlfd_field (fontname, XLFD_PIXELS,
3435 fontsel->size = fontsel->selected_size = size;
3436 fontsel->metric = GTK_FONT_METRIC_PIXELS;
3437 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(fontsel->pixels_button),
3439 sprintf (buffer, "%i", size);
3441 gtk_entry_set_text (GTK_ENTRY (fontsel->size_entry), buffer);
3443 /* Clear any current filter. */
3444 gtk_font_selection_clear_filter(fontsel);
3446 /* Now find the best style match. */
3447 fontsel->font_index = index;
3448 gtk_clist_select_row(GTK_CLIST(fontsel->font_clist), index, 0);
3449 if (GTK_WIDGET_MAPPED (fontsel->font_clist))
3450 gtk_clist_moveto(GTK_CLIST(fontsel->font_clist), index, -1, 0.5, 0);
3452 gtk_font_selection_show_available_styles (fontsel);
3453 /* This will load the font. */
3454 gtk_font_selection_select_best_style (fontsel, FALSE);
3460 /* Returns the index of the given family, or -1 if not found */
3462 gtk_font_selection_find_font (GtkFontSelection *fontsel,
3466 FontInfo *font_info;
3467 gint lower, upper, middle = -1, cmp, nfonts;
3468 gint found_family = -1;
3470 font_info = fontsel_info->font_info;
3471 nfonts = fontsel_info->nfonts;
3475 /* Do a binary search to find the font family. */
3478 while (lower < upper)
3480 middle = (lower + upper) >> 1;
3482 cmp = strcmp (family, font_info[middle].family);
3485 found_family = middle;
3486 cmp = strcmp(fontsel_info->properties[FOUNDRY][foundry],
3487 fontsel_info->properties[FOUNDRY][font_info[middle].foundry]);
3498 /* We couldn't find the family and foundry, but we may have just found the
3499 family, so we return that. */
3500 return found_family;
3504 /* This returns the text in the preview entry. You should copy the returned
3505 text if you need it. */
3507 gtk_font_selection_get_preview_text (GtkFontSelection *fontsel)
3509 return gtk_entry_get_text(GTK_ENTRY(fontsel->preview_entry));
3513 /* This sets the text in the preview entry. */
3515 gtk_font_selection_set_preview_text (GtkFontSelection *fontsel,
3518 gtk_entry_set_text(GTK_ENTRY(fontsel->preview_entry), text);
3522 /*****************************************************************************
3523 * These functions all deal with X Logical Font Description (XLFD) fontnames.
3524 * See the freely available documentation about this.
3525 *****************************************************************************/
3528 * Returns TRUE if the fontname is a valid XLFD.
3529 * (It just checks if the number of dashes is 14, and that each
3530 * field < XLFD_MAX_FIELD_LEN characters long - that's not in the XLFD but it
3531 * makes it easier for me).
3534 gtk_font_selection_is_xlfd_font_name (const gchar *fontname)
3541 if (*fontname++ == '-')
3543 if (field_len > XLFD_MAX_FIELD_LEN) return FALSE;
3551 return (i == 14) ? TRUE : FALSE;
3555 * This fills the buffer with the specified field from the X Logical Font
3556 * Description name, and returns it. If fontname is NULL or the field is
3557 * longer than XFLD_MAX_FIELD_LEN it returns NULL.
3558 * Note: For the charset field, we also return the encoding, e.g. 'iso8859-1'.
3561 gtk_font_selection_get_xlfd_field (const gchar *fontname,
3562 FontField field_num,
3565 const gchar *t1, *t2;
3566 gint countdown, len, num_dashes;
3571 /* we assume this is a valid fontname...that is, it has 14 fields */
3573 countdown = field_num;
3575 while (*t1 && (countdown >= 0))
3579 num_dashes = (field_num == XLFD_CHARSET) ? 2 : 1;
3580 for (t2 = t1; *t2; t2++)
3582 if (*t2 == '-' && --num_dashes == 0)
3588 /* Check we don't overflow the buffer */
3589 len = (long) t2 - (long) t1;
3590 if (len > XLFD_MAX_FIELD_LEN - 1)
3592 strncpy (buffer, t1, len);
3595 /* Convert to lower case. */
3599 strcpy(buffer, "(nil)");
3605 * This returns a X Logical Font Description font name, given all the pieces.
3606 * Note: this retval must be freed by the caller.
3609 gtk_font_selection_create_xlfd (gint size,
3610 GtkFontMetricType metric,
3620 gchar *pixel_size = "*", *point_size = "*", *fontname;
3625 sprintf (buffer, "%d", (int) size);
3626 if (metric == GTK_FONT_METRIC_PIXELS)
3627 pixel_size = buffer;
3629 point_size = buffer;
3631 fontname = g_strdup_printf ("-%s-%s-%s-%s-%s-*-%s-%s-*-*-%s-*-%s",
3632 foundry, family, weight, slant,
3633 set_width, pixel_size, point_size,
3640 /*****************************************************************************
3641 * GtkFontSelectionDialog
3642 *****************************************************************************/
3645 gtk_font_selection_dialog_get_type (void)
3647 static guint font_selection_dialog_type = 0;
3649 if (!font_selection_dialog_type)
3651 GtkTypeInfo fontsel_diag_info =
3653 "GtkFontSelectionDialog",
3654 sizeof (GtkFontSelectionDialog),
3655 sizeof (GtkFontSelectionDialogClass),
3656 (GtkClassInitFunc) gtk_font_selection_dialog_class_init,
3657 (GtkObjectInitFunc) gtk_font_selection_dialog_init,
3658 /* reserved_1 */ NULL,
3659 /* reserved_2 */ NULL,
3660 (GtkClassInitFunc) NULL,
3663 font_selection_dialog_type = gtk_type_unique (GTK_TYPE_WINDOW, &fontsel_diag_info);
3666 return font_selection_dialog_type;
3670 gtk_font_selection_dialog_class_init (GtkFontSelectionDialogClass *klass)
3672 GtkObjectClass *object_class;
3674 object_class = (GtkObjectClass*) klass;
3676 font_selection_dialog_parent_class = gtk_type_class (GTK_TYPE_WINDOW);
3680 gtk_font_selection_dialog_init (GtkFontSelectionDialog *fontseldiag)
3682 fontseldiag->dialog_width = -1;
3683 fontseldiag->auto_resize = TRUE;
3685 gtk_widget_set_events(GTK_WIDGET(fontseldiag), GDK_STRUCTURE_MASK);
3686 gtk_signal_connect (GTK_OBJECT (fontseldiag), "configure_event",
3687 (GtkSignalFunc) gtk_font_selection_dialog_on_configure,
3690 gtk_container_set_border_width (GTK_CONTAINER (fontseldiag), 4);
3691 gtk_window_set_policy(GTK_WINDOW(fontseldiag), FALSE, TRUE, TRUE);
3693 fontseldiag->main_vbox = gtk_vbox_new (FALSE, 4);
3694 gtk_widget_show (fontseldiag->main_vbox);
3695 gtk_container_add (GTK_CONTAINER (fontseldiag), fontseldiag->main_vbox);
3697 fontseldiag->fontsel = gtk_font_selection_new();
3698 gtk_widget_show (fontseldiag->fontsel);
3699 gtk_box_pack_start (GTK_BOX (fontseldiag->main_vbox),
3700 fontseldiag->fontsel, TRUE, TRUE, 0);
3702 /* Create the action area */
3703 fontseldiag->action_area = gtk_hbutton_box_new ();
3704 gtk_button_box_set_layout(GTK_BUTTON_BOX(fontseldiag->action_area),
3706 gtk_button_box_set_spacing(GTK_BUTTON_BOX(fontseldiag->action_area), 5);
3707 gtk_box_pack_start (GTK_BOX (fontseldiag->main_vbox),
3708 fontseldiag->action_area, FALSE, FALSE, 0);
3709 gtk_widget_show (fontseldiag->action_area);
3711 fontseldiag->ok_button = gtk_button_new_with_label(_("OK"));
3712 GTK_WIDGET_SET_FLAGS (fontseldiag->ok_button, GTK_CAN_DEFAULT);
3713 gtk_widget_show(fontseldiag->ok_button);
3714 gtk_box_pack_start (GTK_BOX (fontseldiag->action_area),
3715 fontseldiag->ok_button, TRUE, TRUE, 0);
3716 gtk_widget_grab_default (fontseldiag->ok_button);
3718 fontseldiag->apply_button = gtk_button_new_with_label(_("Apply"));
3719 GTK_WIDGET_SET_FLAGS (fontseldiag->apply_button, GTK_CAN_DEFAULT);
3720 /*gtk_widget_show(fontseldiag->apply_button);*/
3721 gtk_box_pack_start (GTK_BOX(fontseldiag->action_area),
3722 fontseldiag->apply_button, TRUE, TRUE, 0);
3724 fontseldiag->cancel_button = gtk_button_new_with_label(_("Cancel"));
3725 GTK_WIDGET_SET_FLAGS (fontseldiag->cancel_button, GTK_CAN_DEFAULT);
3726 gtk_widget_show(fontseldiag->cancel_button);
3727 gtk_box_pack_start (GTK_BOX(fontseldiag->action_area),
3728 fontseldiag->cancel_button, TRUE, TRUE, 0);
3734 gtk_font_selection_dialog_new (const gchar *title)
3736 GtkFontSelectionDialog *fontseldiag;
3738 fontseldiag = gtk_type_new (GTK_TYPE_FONT_SELECTION_DIALOG);
3739 gtk_window_set_title (GTK_WINDOW (fontseldiag),
3740 title ? title : _("Font Selection"));
3742 return GTK_WIDGET (fontseldiag);
3746 gtk_font_selection_dialog_get_font_name (GtkFontSelectionDialog *fsd)
3748 return gtk_font_selection_get_font_name(GTK_FONT_SELECTION(fsd->fontsel));
3752 gtk_font_selection_dialog_get_font (GtkFontSelectionDialog *fsd)
3754 return gtk_font_selection_get_font(GTK_FONT_SELECTION(fsd->fontsel));
3758 gtk_font_selection_dialog_set_font_name (GtkFontSelectionDialog *fsd,
3759 const gchar *fontname)
3761 return gtk_font_selection_set_font_name(GTK_FONT_SELECTION(fsd->fontsel),
3766 gtk_font_selection_dialog_set_filter (GtkFontSelectionDialog *fsd,
3767 GtkFontFilterType filter_type,
3768 GtkFontType font_type,
3776 gtk_font_selection_set_filter (GTK_FONT_SELECTION (fsd->fontsel),
3777 filter_type, font_type,
3778 foundries, weights, slants, setwidths,
3779 spacings, charsets);
3783 gtk_font_selection_dialog_get_preview_text (GtkFontSelectionDialog *fsd)
3785 return gtk_font_selection_get_preview_text(GTK_FONT_SELECTION(fsd->fontsel));
3789 gtk_font_selection_dialog_set_preview_text (GtkFontSelectionDialog *fsd,
3792 gtk_font_selection_set_preview_text(GTK_FONT_SELECTION(fsd->fontsel), text);
3796 /* This turns auto-shrink off if the user resizes the width of the dialog.
3797 It also turns it back on again if the user resizes it back to its normal
3800 gtk_font_selection_dialog_on_configure (GtkWidget *widget,
3801 GdkEventConfigure *event,
3802 GtkFontSelectionDialog *fsd)
3804 /* This sets the initial width. */
3805 if (fsd->dialog_width == -1)
3806 fsd->dialog_width = event->width;
3807 else if (fsd->auto_resize && fsd->dialog_width != event->width)
3809 fsd->auto_resize = FALSE;
3810 gtk_window_set_policy(GTK_WINDOW(fsd), FALSE, TRUE, FALSE);
3812 else if (!fsd->auto_resize && fsd->dialog_width == event->width)
3814 fsd->auto_resize = TRUE;
3815 gtk_window_set_policy(GTK_WINDOW(fsd), FALSE, TRUE, TRUE);