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.
73 /* Protect against the CHARSET struct in Win32 */
74 #ifdef GDK_WINDOWING_WIN32
75 # define CHARSET CHARSETstruct
78 #ifdef GDK_WINDOWING_WIN32
81 #include "gdk/gdkkeysyms.h"
83 #include "gtkbutton.h"
84 #include "gtkcheckbutton.h"
87 #include "gtkfontsel.h"
92 #include "gtknotebook.h"
93 #include "gtkradiobutton.h"
94 #include "gtksignal.h"
97 #include "gtkscrolledwindow.h"
100 /* The maximum number of fontnames requested with XListFonts(). */
101 #define MAX_FONTS 32767
103 /* This is the largest field length we will accept. If a fontname has a field
104 larger than this we will skip it. */
105 #define XLFD_MAX_FIELD_LEN 64
107 /* These are what we use as the standard font sizes, for the size clist.
108 Note that when using points we still show these integer point values but
109 we work internally in decipoints (and decipoint values can be typed in). */
110 static const guint16 font_sizes[] = {
111 8, 9, 10, 11, 12, 13, 14, 16, 18, 20, 22, 24, 26, 28,
112 32, 36, 40, 48, 56, 64, 72
115 /* Initial font metric & size (Remember point sizes are in decipoints).
116 The font size should match one of those in the font_sizes array. */
117 #define INITIAL_METRIC GTK_FONT_METRIC_POINTS
118 #define INITIAL_FONT_SIZE 140
120 /* This is the default text shown in the preview entry, though the user
121 can set it. Remember that some fonts only have capital letters. */
122 #define PREVIEW_TEXT "abcdefghijk ABCDEFGHIJK"
124 /* This is the initial and maximum height of the preview entry (it expands
125 when large font sizes are selected). Initial height is also the minimum. */
126 #define INITIAL_PREVIEW_HEIGHT 44
127 #define MAX_PREVIEW_HEIGHT 300
129 /* These are the sizes of the font, style & size clists. */
130 #define FONT_LIST_HEIGHT 136
131 #define FONT_LIST_WIDTH 190
132 #define FONT_STYLE_LIST_WIDTH 170
133 #define FONT_SIZE_LIST_WIDTH 60
135 /* This is the number of fields in an X Logical Font Description font name.
136 Note that we count the registry & encoding as 1. */
137 #define GTK_XLFD_NUM_FIELDS 13
139 typedef struct _GtkFontSelInfo GtkFontSelInfo;
140 typedef struct _FontInfo FontInfo;
141 typedef struct _FontStyle FontStyle;
143 /* This struct represents one family of fonts (with one foundry), e.g. adobe
144 courier or sony fixed. It stores the family name, the index of the foundry
145 name, and the index of and number of available styles. */
154 /* This represents one style, as displayed in the Font Style clist. It can
155 have a number of available pixel sizes and point sizes. The indexes point
156 into the two big fontsel_info->pixel_sizes & fontsel_info->point_sizes
157 arrays. The displayed flag is used when displaying styles to remember which
158 styles have already been displayed. Note that it is combined with the
159 GtkFontType in the flags field. */
160 #define GTK_FONT_DISPLAYED (1 << 7)
163 guint16 properties[GTK_NUM_STYLE_PROPERTIES];
164 gint pixel_sizes_index;
165 guint16 npixel_sizes;
166 gint point_sizes_index;
167 guint16 npoint_sizes;
171 struct _GtkFontSelInfo {
173 /* This is a table with each FontInfo representing one font family+foundry */
177 /* This stores all the valid combinations of properties for every family.
178 Each FontInfo holds an index into its own space in this one big array. */
179 FontStyle *font_styles;
182 /* This stores all the font sizes available for every style.
183 Each style holds an index into these arrays. */
184 guint16 *pixel_sizes;
185 guint16 *point_sizes;
187 /* These are the arrays of strings of all possible weights, slants,
188 set widths, spacings, charsets & foundries, and the amount of space
189 allocated for each array. */
190 gchar **properties[GTK_NUM_FONT_PROPERTIES];
191 guint16 nproperties[GTK_NUM_FONT_PROPERTIES];
192 guint16 space_allocated[GTK_NUM_FONT_PROPERTIES];
195 /* These are the field numbers in the X Logical Font Description fontnames,
196 e.g. -adobe-courier-bold-o-normal--25-180-100-100-m-150-iso8859-1 */
207 XLFD_RESOLUTION_X = 8,
208 XLFD_RESOLUTION_Y = 9,
210 XLFD_AVERAGE_WIDTH = 11,
214 /* These are the names of the fields, used on the info & filter page. */
215 static const gchar* xlfd_field_names[GTK_XLFD_NUM_FIELDS] = {
227 N_("Average Width:"),
231 /* These are the array indices of the font properties used in several arrays,
232 and should match the xlfd_index array below. */
243 /* This is used to look up a field in a fontname given one of the above
245 static const FontField xlfd_index[GTK_NUM_FONT_PROPERTIES] = {
254 /* These are the positions of the properties in the filter table - x, y. */
255 static const gint filter_positions[GTK_NUM_FONT_PROPERTIES][2] = {
256 { 1, 0 }, { 0, 2 }, { 1, 2 }, { 2, 2 }, { 2, 0 }, { 0, 0 }
258 static const gint filter_heights[GTK_NUM_FONT_PROPERTIES] = {
259 100, 70, 70, 40, 100, 100
262 /* This is returned by gtk_font_selection_filter_state to describe if a
263 property value is filtered. e.g. if 'bold' has been selected on the filter
264 page, then that will return 'FILTERED' and 'black' will be 'NOT_FILTERED'.
265 If none of the weight values are selected, they all return 'NOT_SET'. */
271 } GtkFontPropertyFilterState;
273 static GtkFontSelInfo *fontsel_info = NULL;
275 /* The initial size and increment of each of the arrays of property values. */
276 #define PROPERTY_ARRAY_INCREMENT 16
278 static void gtk_font_selection_class_init (GtkFontSelectionClass *klass);
279 static void gtk_font_selection_init (GtkFontSelection *fontsel);
280 static void gtk_font_selection_destroy (GtkObject *object);
282 /* These are all used for class initialization - loading in the fonts etc. */
283 static void gtk_font_selection_get_fonts (void);
284 static void gtk_font_selection_insert_font (GSList *fontnames[],
287 static gint gtk_font_selection_insert_field (gchar *fontname,
290 /* These are the callbacks & related functions. */
291 static void gtk_font_selection_select_font (GtkWidget *w,
294 GdkEventButton *bevent,
296 static gint gtk_font_selection_on_clist_key_press (GtkWidget *clist,
298 GtkFontSelection *fs);
299 static gboolean gtk_font_selection_select_next (GtkFontSelection *fs,
302 static void gtk_font_selection_show_available_styles
303 (GtkFontSelection *fs);
304 static void gtk_font_selection_select_best_style (GtkFontSelection *fs,
307 static void gtk_font_selection_select_style (GtkWidget *w,
310 GdkEventButton *bevent,
312 static void gtk_font_selection_show_available_sizes
313 (GtkFontSelection *fs);
314 static gint gtk_font_selection_size_key_press (GtkWidget *w,
317 static void gtk_font_selection_select_best_size (GtkFontSelection *fs);
318 static void gtk_font_selection_select_size (GtkWidget *w,
321 GdkEventButton *bevent,
324 static void gtk_font_selection_metric_callback (GtkWidget *w,
326 static void gtk_font_selection_expose_list (GtkWidget *w,
327 GdkEventExpose *event,
329 static void gtk_font_selection_realize_list (GtkWidget *widget,
332 static void gtk_font_selection_switch_page (GtkWidget *w,
333 GtkNotebookPage *page,
336 static void gtk_font_selection_show_font_info (GtkFontSelection *fs);
338 static void gtk_font_selection_select_filter (GtkWidget *w,
341 GdkEventButton *bevent,
342 GtkFontSelection *fs);
343 static void gtk_font_selection_unselect_filter (GtkWidget *w,
346 GdkEventButton *bevent,
347 GtkFontSelection *fs);
348 static void gtk_font_selection_update_filter (GtkFontSelection *fs);
349 static gboolean gtk_font_selection_style_visible (GtkFontSelection *fs,
352 static void gtk_font_selection_reset_filter (GtkWidget *w,
353 GtkFontSelection *fs);
354 static void gtk_font_selection_on_clear_filter (GtkWidget *w,
355 GtkFontSelection *fs);
356 static void gtk_font_selection_show_available_fonts
357 (GtkFontSelection *fs);
358 static void gtk_font_selection_clear_filter (GtkFontSelection *fs);
359 static void gtk_font_selection_update_filter_lists(GtkFontSelection *fs);
360 static GtkFontPropertyFilterState gtk_font_selection_filter_state
361 (GtkFontSelection *fs,
362 GtkFontFilterType filter_type,
366 /* Misc. utility functions. */
367 static gboolean gtk_font_selection_load_font (GtkFontSelection *fs);
368 static void gtk_font_selection_update_preview (GtkFontSelection *fs);
370 static gint gtk_font_selection_find_font (GtkFontSelection *fs,
373 static guint16 gtk_font_selection_field_to_index (gchar **table,
377 static gchar* gtk_font_selection_expand_slant_code (gchar *slant);
378 static gchar* gtk_font_selection_expand_spacing_code(gchar *spacing);
380 /* Functions for handling X Logical Font Description fontnames. */
381 static gboolean gtk_font_selection_is_xlfd_font_name (const gchar *fontname);
382 static char* gtk_font_selection_get_xlfd_field (const gchar *fontname,
385 static gchar * gtk_font_selection_create_xlfd (gint size,
386 GtkFontMetricType metric,
396 /* FontSelectionDialog */
397 static void gtk_font_selection_dialog_class_init (GtkFontSelectionDialogClass *klass);
398 static void gtk_font_selection_dialog_init (GtkFontSelectionDialog *fontseldiag);
400 static gint gtk_font_selection_dialog_on_configure(GtkWidget *widget,
401 GdkEventConfigure *event,
402 GtkFontSelectionDialog *fsd);
404 #ifdef GDK_WINDOWING_WIN32
405 static char *logfont_to_xlfd (const LOGFONT *lfp,
411 static GtkWindowClass *font_selection_parent_class = NULL;
412 static GtkNotebookClass *font_selection_dialog_parent_class = NULL;
415 gtk_font_selection_get_type()
417 static GtkType font_selection_type = 0;
419 if(!font_selection_type)
421 static const GtkTypeInfo fontsel_type_info =
424 sizeof (GtkFontSelection),
425 sizeof (GtkFontSelectionClass),
426 (GtkClassInitFunc) gtk_font_selection_class_init,
427 (GtkObjectInitFunc) gtk_font_selection_init,
428 /* reserved_1 */ NULL,
429 /* reserved_2 */ NULL,
430 (GtkClassInitFunc) NULL,
433 font_selection_type = gtk_type_unique (GTK_TYPE_NOTEBOOK,
437 return font_selection_type;
441 gtk_font_selection_class_init(GtkFontSelectionClass *klass)
443 GtkObjectClass *object_class;
445 object_class = (GtkObjectClass *) klass;
447 font_selection_parent_class = gtk_type_class (GTK_TYPE_NOTEBOOK);
449 object_class->destroy = gtk_font_selection_destroy;
451 gtk_font_selection_get_fonts ();
455 gtk_font_selection_init(GtkFontSelection *fontsel)
457 GtkWidget *scrolled_win;
458 GtkWidget *text_frame;
459 GtkWidget *text_box, *frame;
460 GtkWidget *table, *label, *hbox, *hbox2, *clist, *button, *vbox, *alignment;
462 gchar *titles[] = { NULL, NULL, NULL };
467 gchar *property, *text;
470 /* Number of internationalized titles here must match number
471 of NULL initializers above */
472 titles[0] = _("Font Property");
473 titles[1] = _("Requested Value");
474 titles[2] = _("Actual Value");
476 /* Initialize the GtkFontSelection struct. We do this here in case any
477 callbacks are triggered while creating the interface. */
478 fontsel->font = NULL;
479 fontsel->font_index = -1;
481 fontsel->metric = INITIAL_METRIC;
482 fontsel->size = INITIAL_FONT_SIZE;
483 fontsel->selected_size = INITIAL_FONT_SIZE;
485 fontsel->filters[GTK_FONT_FILTER_BASE].font_type = GTK_FONT_ALL;
486 fontsel->filters[GTK_FONT_FILTER_USER].font_type = GTK_FONT_BITMAP
490 for (prop = 0; prop < GTK_NUM_FONT_PROPERTIES; prop++)
492 fontsel->filters[GTK_FONT_FILTER_BASE].property_filters[prop] = NULL;
493 fontsel->filters[GTK_FONT_FILTER_BASE].property_nfilters[prop] = 0;
494 fontsel->filters[GTK_FONT_FILTER_USER].property_filters[prop] = NULL;
495 fontsel->filters[GTK_FONT_FILTER_USER].property_nfilters[prop] = 0;
498 for (prop = 0; prop < GTK_NUM_STYLE_PROPERTIES; prop++)
499 fontsel->property_values[prop] = 0;
501 /* Create the main notebook page. */
502 gtk_notebook_set_homogeneous_tabs (GTK_NOTEBOOK (fontsel), TRUE);
503 gtk_notebook_set_tab_hborder (GTK_NOTEBOOK (fontsel), 8);
504 fontsel->main_vbox = gtk_vbox_new (FALSE, 4);
505 gtk_widget_show (fontsel->main_vbox);
506 gtk_container_set_border_width (GTK_CONTAINER (fontsel->main_vbox), 6);
507 label = gtk_label_new(_("Font"));
508 gtk_notebook_append_page (GTK_NOTEBOOK (fontsel),
509 fontsel->main_vbox, label);
511 /* Create the table of font, style & size. */
512 table = gtk_table_new (3, 3, FALSE);
513 gtk_widget_show (table);
514 gtk_table_set_col_spacings(GTK_TABLE(table), 8);
515 gtk_box_pack_start (GTK_BOX (fontsel->main_vbox), table, TRUE, TRUE, 0);
517 fontsel->font_label = gtk_label_new(_("Font:"));
518 gtk_misc_set_alignment (GTK_MISC (fontsel->font_label), 0.0, 0.5);
519 gtk_widget_show (fontsel->font_label);
520 gtk_table_attach (GTK_TABLE (table), fontsel->font_label, 0, 1, 0, 1,
522 label = gtk_label_new(_("Font Style:"));
523 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
524 gtk_widget_show (label);
525 gtk_table_attach (GTK_TABLE (table), label, 1, 2, 0, 1,
527 label = gtk_label_new(_("Size:"));
528 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
529 gtk_widget_show (label);
530 gtk_table_attach (GTK_TABLE (table), label, 2, 3, 0, 1,
533 fontsel->font_entry = gtk_entry_new();
534 gtk_entry_set_editable(GTK_ENTRY(fontsel->font_entry), FALSE);
535 gtk_widget_set_usize (fontsel->font_entry, 20, -1);
536 gtk_widget_show (fontsel->font_entry);
537 gtk_table_attach (GTK_TABLE (table), fontsel->font_entry, 0, 1, 1, 2,
539 fontsel->font_style_entry = gtk_entry_new();
540 gtk_entry_set_editable(GTK_ENTRY(fontsel->font_style_entry), FALSE);
541 gtk_widget_set_usize (fontsel->font_style_entry, 20, -1);
542 gtk_widget_show (fontsel->font_style_entry);
543 gtk_table_attach (GTK_TABLE (table), fontsel->font_style_entry, 1, 2, 1, 2,
545 fontsel->size_entry = gtk_entry_new();
546 gtk_widget_set_usize (fontsel->size_entry, 20, -1);
547 gtk_widget_show (fontsel->size_entry);
548 gtk_table_attach (GTK_TABLE (table), fontsel->size_entry, 2, 3, 1, 2,
550 gtk_signal_connect (GTK_OBJECT (fontsel->size_entry), "key_press_event",
551 (GtkSignalFunc) gtk_font_selection_size_key_press,
554 /* Create the clists */
555 fontsel->font_clist = gtk_clist_new(1);
556 gtk_clist_column_titles_hide (GTK_CLIST(fontsel->font_clist));
557 gtk_clist_set_column_auto_resize (GTK_CLIST (fontsel->font_clist), 0, TRUE);
558 scrolled_win = gtk_scrolled_window_new (NULL, NULL);
559 gtk_widget_set_usize (scrolled_win, FONT_LIST_WIDTH, FONT_LIST_HEIGHT);
560 gtk_container_add (GTK_CONTAINER (scrolled_win), fontsel->font_clist);
561 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
562 GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
563 gtk_widget_show(fontsel->font_clist);
564 gtk_widget_show(scrolled_win);
566 gtk_table_attach (GTK_TABLE (table), scrolled_win, 0, 1, 2, 3,
567 GTK_EXPAND | GTK_FILL,
568 GTK_EXPAND | GTK_FILL, 0, 0);
570 fontsel->font_style_clist = gtk_clist_new(1);
571 gtk_clist_column_titles_hide (GTK_CLIST(fontsel->font_style_clist));
572 gtk_clist_set_column_auto_resize (GTK_CLIST (fontsel->font_style_clist),
574 scrolled_win = gtk_scrolled_window_new (NULL, NULL);
575 gtk_widget_set_usize (scrolled_win, FONT_STYLE_LIST_WIDTH, -1);
576 gtk_container_add (GTK_CONTAINER (scrolled_win), fontsel->font_style_clist);
577 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
578 GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
579 gtk_widget_show(fontsel->font_style_clist);
580 gtk_widget_show(scrolled_win);
581 gtk_table_attach (GTK_TABLE (table), scrolled_win, 1, 2, 2, 3,
582 GTK_EXPAND | GTK_FILL,
583 GTK_EXPAND | GTK_FILL, 0, 0);
585 fontsel->size_clist = gtk_clist_new(1);
586 gtk_clist_column_titles_hide (GTK_CLIST(fontsel->size_clist));
587 gtk_clist_set_column_width (GTK_CLIST(fontsel->size_clist), 0, 20);
588 scrolled_win = gtk_scrolled_window_new (NULL, NULL);
589 gtk_widget_set_usize (scrolled_win, FONT_SIZE_LIST_WIDTH, -1);
590 gtk_container_add (GTK_CONTAINER (scrolled_win), fontsel->size_clist);
591 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
592 GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
593 gtk_widget_show(fontsel->size_clist);
594 gtk_widget_show(scrolled_win);
595 gtk_table_attach (GTK_TABLE (table), scrolled_win, 2, 3, 2, 3,
596 GTK_FILL, GTK_FILL, 0, 0);
599 /* Insert the fonts. If there exist fonts with the same family but
600 different foundries, then the foundry name is appended in brackets. */
601 gtk_font_selection_show_available_fonts(fontsel);
603 gtk_signal_connect (GTK_OBJECT (fontsel->font_clist), "select_row",
604 GTK_SIGNAL_FUNC(gtk_font_selection_select_font),
606 GTK_WIDGET_SET_FLAGS (fontsel->font_clist, GTK_CAN_FOCUS);
607 gtk_signal_connect (GTK_OBJECT (fontsel->font_clist), "key_press_event",
608 GTK_SIGNAL_FUNC(gtk_font_selection_on_clist_key_press),
610 gtk_signal_connect_after (GTK_OBJECT (fontsel->font_clist), "expose_event",
611 GTK_SIGNAL_FUNC(gtk_font_selection_expose_list),
614 gtk_signal_connect (GTK_OBJECT (fontsel->font_style_clist), "select_row",
615 GTK_SIGNAL_FUNC(gtk_font_selection_select_style),
617 GTK_WIDGET_SET_FLAGS (fontsel->font_style_clist, GTK_CAN_FOCUS);
618 gtk_signal_connect (GTK_OBJECT (fontsel->font_style_clist),
620 GTK_SIGNAL_FUNC(gtk_font_selection_on_clist_key_press),
622 gtk_signal_connect_after (GTK_OBJECT (fontsel->font_style_clist),
624 GTK_SIGNAL_FUNC(gtk_font_selection_realize_list),
627 /* Insert the standard font sizes */
628 gtk_clist_freeze (GTK_CLIST(fontsel->size_clist));
629 size_to_match = INITIAL_FONT_SIZE;
630 if (INITIAL_METRIC == GTK_FONT_METRIC_POINTS)
631 size_to_match = size_to_match / 10;
632 for (i = 0; i < sizeof(font_sizes) / sizeof(font_sizes[0]); i++)
634 sprintf(buffer, "%i", font_sizes[i]);
636 gtk_clist_append(GTK_CLIST(fontsel->size_clist), &size);
637 if (font_sizes[i] == size_to_match)
639 gtk_clist_select_row(GTK_CLIST(fontsel->size_clist), i, 0);
640 gtk_entry_set_text(GTK_ENTRY(fontsel->size_entry), buffer);
643 gtk_clist_thaw (GTK_CLIST(fontsel->size_clist));
645 gtk_signal_connect (GTK_OBJECT (fontsel->size_clist), "select_row",
646 GTK_SIGNAL_FUNC(gtk_font_selection_select_size),
648 GTK_WIDGET_SET_FLAGS (fontsel->size_clist, GTK_CAN_FOCUS);
649 gtk_signal_connect (GTK_OBJECT (fontsel->size_clist), "key_press_event",
650 GTK_SIGNAL_FUNC(gtk_font_selection_on_clist_key_press),
654 /* create the Reset Filter & Metric buttons */
655 hbox = gtk_hbox_new(FALSE, 8);
656 gtk_widget_show (hbox);
657 gtk_box_pack_start (GTK_BOX (fontsel->main_vbox), hbox, FALSE, TRUE, 0);
659 fontsel->filter_button = gtk_button_new_with_label(_("Reset Filter"));
660 gtk_misc_set_padding (GTK_MISC (GTK_BIN (fontsel->filter_button)->child),
662 gtk_widget_show(fontsel->filter_button);
663 gtk_box_pack_start (GTK_BOX (hbox), fontsel->filter_button, FALSE, FALSE, 0);
664 gtk_widget_set_sensitive (fontsel->filter_button, FALSE);
665 gtk_signal_connect (GTK_OBJECT (fontsel->filter_button), "clicked",
666 GTK_SIGNAL_FUNC(gtk_font_selection_on_clear_filter),
669 hbox2 = gtk_hbox_new(FALSE, 0);
670 gtk_widget_show (hbox2);
671 gtk_box_pack_end (GTK_BOX (hbox), hbox2, FALSE, FALSE, 0);
673 label = gtk_label_new(_("Metric:"));
674 gtk_widget_show (label);
675 gtk_box_pack_start (GTK_BOX (hbox2), label, FALSE, TRUE, 8);
677 fontsel->points_button = gtk_radio_button_new_with_label(NULL, _("Points"));
678 gtk_widget_show (fontsel->points_button);
679 gtk_box_pack_start (GTK_BOX (hbox2), fontsel->points_button, FALSE, TRUE, 0);
680 if (INITIAL_METRIC == GTK_FONT_METRIC_POINTS)
681 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(fontsel->points_button),
684 fontsel->pixels_button = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(fontsel->points_button), _("Pixels"));
685 gtk_widget_show (fontsel->pixels_button);
686 gtk_box_pack_start (GTK_BOX (hbox2), fontsel->pixels_button, FALSE, TRUE, 0);
687 if (INITIAL_METRIC == GTK_FONT_METRIC_PIXELS)
688 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(fontsel->pixels_button),
691 gtk_signal_connect(GTK_OBJECT(fontsel->points_button), "toggled",
692 (GtkSignalFunc) gtk_font_selection_metric_callback,
694 gtk_signal_connect(GTK_OBJECT(fontsel->pixels_button), "toggled",
695 (GtkSignalFunc) gtk_font_selection_metric_callback,
699 /* create the text entry widget */
700 text_frame = gtk_frame_new (_("Preview:"));
701 gtk_widget_show (text_frame);
702 gtk_frame_set_shadow_type(GTK_FRAME(text_frame), GTK_SHADOW_ETCHED_IN);
703 gtk_box_pack_start (GTK_BOX (fontsel->main_vbox), text_frame,
706 /* This is just used to get a 4-pixel space around the preview entry. */
707 text_box = gtk_hbox_new (FALSE, 0);
708 gtk_widget_show (text_box);
709 gtk_container_add (GTK_CONTAINER (text_frame), text_box);
710 gtk_container_set_border_width (GTK_CONTAINER (text_box), 4);
712 fontsel->preview_entry = gtk_entry_new ();
713 gtk_widget_show (fontsel->preview_entry);
714 gtk_widget_set_usize (fontsel->preview_entry, -1, INITIAL_PREVIEW_HEIGHT);
715 gtk_box_pack_start (GTK_BOX (text_box), fontsel->preview_entry,
718 /* Create the message area */
719 fontsel->message_label = gtk_label_new("");
720 gtk_widget_show (fontsel->message_label);
721 gtk_box_pack_start (GTK_BOX (fontsel->main_vbox), fontsel->message_label,
725 /* Create the font info page */
726 fontsel->info_vbox = gtk_vbox_new (FALSE, 4);
727 gtk_widget_show (fontsel->info_vbox);
728 gtk_container_set_border_width (GTK_CONTAINER (fontsel->info_vbox), 2);
729 label = gtk_label_new(_("Font Information"));
730 gtk_notebook_append_page (GTK_NOTEBOOK (fontsel),
731 fontsel->info_vbox, label);
733 fontsel->info_clist = gtk_clist_new_with_titles (3, titles);
734 gtk_widget_set_usize (fontsel->info_clist, 390, 150);
735 gtk_clist_set_column_width(GTK_CLIST(fontsel->info_clist), 0, 130);
736 gtk_clist_set_column_width(GTK_CLIST(fontsel->info_clist), 1, 130);
737 gtk_clist_set_column_width(GTK_CLIST(fontsel->info_clist), 2, 130);
738 gtk_clist_column_titles_passive(GTK_CLIST(fontsel->info_clist));
739 scrolled_win = gtk_scrolled_window_new (NULL, NULL);
740 gtk_container_add (GTK_CONTAINER (scrolled_win), fontsel->info_clist);
741 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
742 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
743 gtk_widget_show(fontsel->info_clist);
744 gtk_widget_show(scrolled_win);
745 gtk_box_pack_start (GTK_BOX (fontsel->info_vbox), scrolled_win,
748 /* Insert the property names */
749 gtk_clist_freeze (GTK_CLIST(fontsel->info_clist));
752 for (i = 0; i < GTK_XLFD_NUM_FIELDS; i++)
754 row_text[0] = _(xlfd_field_names[i]);
755 gtk_clist_append(GTK_CLIST(fontsel->info_clist), row_text);
756 gtk_clist_set_shift(GTK_CLIST(fontsel->info_clist), i, 0, 0, 4);
757 gtk_clist_set_shift(GTK_CLIST(fontsel->info_clist), i, 1, 0, 4);
758 gtk_clist_set_shift(GTK_CLIST(fontsel->info_clist), i, 2, 0, 4);
760 gtk_clist_thaw (GTK_CLIST(fontsel->info_clist));
762 label = gtk_label_new(_("Requested Font Name:"));
763 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
764 gtk_widget_show (label);
765 gtk_box_pack_start (GTK_BOX (fontsel->info_vbox), label, FALSE, TRUE, 0);
767 fontsel->requested_font_name = gtk_entry_new();
768 gtk_entry_set_editable(GTK_ENTRY(fontsel->requested_font_name), FALSE);
769 gtk_widget_show (fontsel->requested_font_name);
770 gtk_box_pack_start (GTK_BOX (fontsel->info_vbox),
771 fontsel->requested_font_name, FALSE, TRUE, 0);
773 label = gtk_label_new(_("Actual Font Name:"));
774 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
775 gtk_widget_show (label);
776 gtk_box_pack_start (GTK_BOX (fontsel->info_vbox), label, FALSE, TRUE, 0);
778 fontsel->actual_font_name = gtk_entry_new();
779 gtk_entry_set_editable(GTK_ENTRY(fontsel->actual_font_name), FALSE);
780 gtk_widget_show (fontsel->actual_font_name);
781 gtk_box_pack_start (GTK_BOX (fontsel->info_vbox),
782 fontsel->actual_font_name, FALSE, TRUE, 0);
784 sprintf(buffer, _("%i fonts available with a total of %i styles."),
785 fontsel_info->nfonts, fontsel_info->nstyles);
786 label = gtk_label_new(buffer);
787 gtk_widget_show (label);
788 gtk_box_pack_start (GTK_BOX (fontsel->info_vbox), label, FALSE, FALSE, 0);
790 gtk_signal_connect (GTK_OBJECT (fontsel), "switch_page",
791 GTK_SIGNAL_FUNC(gtk_font_selection_switch_page),
795 /* Create the Filter page. */
796 fontsel->filter_vbox = gtk_vbox_new (FALSE, 4);
797 gtk_widget_show (fontsel->filter_vbox);
798 gtk_container_set_border_width (GTK_CONTAINER (fontsel->filter_vbox), 2);
799 label = gtk_label_new(_("Filter"));
800 gtk_notebook_append_page (GTK_NOTEBOOK (fontsel),
801 fontsel->filter_vbox, label);
803 /* Create the font type checkbuttons. */
804 frame = gtk_frame_new (NULL);
805 gtk_widget_show (frame);
806 gtk_box_pack_start (GTK_BOX (fontsel->filter_vbox), frame, FALSE, TRUE, 0);
808 hbox = gtk_hbox_new (FALSE, 20);
809 gtk_widget_show (hbox);
810 gtk_container_add (GTK_CONTAINER (frame), hbox);
812 label = gtk_label_new(_("Font Types:"));
813 gtk_widget_show (label);
814 gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 10);
816 hbox2 = gtk_hbox_new (TRUE, 0);
817 gtk_widget_show (hbox2);
818 gtk_box_pack_start (GTK_BOX (hbox), hbox2, FALSE, TRUE, 0);
820 fontsel->type_bitmaps_button = gtk_check_button_new_with_label (_("Bitmap"));
821 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fontsel->type_bitmaps_button), TRUE);
822 gtk_widget_show (fontsel->type_bitmaps_button);
823 gtk_box_pack_start (GTK_BOX (hbox2), fontsel->type_bitmaps_button,
826 fontsel->type_scalable_button = gtk_check_button_new_with_label (_("Scalable"));
827 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fontsel->type_scalable_button), TRUE);
828 gtk_widget_show (fontsel->type_scalable_button);
829 gtk_box_pack_start (GTK_BOX (hbox2), fontsel->type_scalable_button,
832 fontsel->type_scaled_bitmaps_button = gtk_check_button_new_with_label (_("Scaled Bitmap"));
833 gtk_widget_show (fontsel->type_scaled_bitmaps_button);
834 gtk_box_pack_start (GTK_BOX (hbox2), fontsel->type_scaled_bitmaps_button,
837 table = gtk_table_new (4, 3, FALSE);
838 gtk_table_set_col_spacings(GTK_TABLE(table), 2);
839 gtk_widget_show (table);
840 gtk_box_pack_start (GTK_BOX (fontsel->filter_vbox), table, TRUE, TRUE, 0);
842 for (prop = 0; prop < GTK_NUM_FONT_PROPERTIES; prop++)
844 gint left = filter_positions[prop][0];
845 gint top = filter_positions[prop][1];
847 label = gtk_label_new(_(xlfd_field_names[xlfd_index[prop]]));
848 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 1.0);
849 gtk_misc_set_padding (GTK_MISC (label), 0, 2);
850 gtk_widget_show(label);
851 gtk_table_attach (GTK_TABLE (table), label, left, left + 1,
852 top, top + 1, GTK_FILL, GTK_FILL, 0, 0);
854 clist = gtk_clist_new(1);
855 gtk_widget_set_usize (clist, 100, filter_heights[prop]);
856 gtk_clist_set_selection_mode(GTK_CLIST(clist), GTK_SELECTION_MULTIPLE);
857 gtk_clist_column_titles_hide(GTK_CLIST(clist));
858 gtk_clist_set_column_auto_resize (GTK_CLIST (clist), 0, TRUE);
859 scrolled_win = gtk_scrolled_window_new (NULL, NULL);
860 gtk_container_add (GTK_CONTAINER (scrolled_win), clist);
861 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
862 GTK_POLICY_AUTOMATIC,
863 GTK_POLICY_AUTOMATIC);
864 gtk_widget_show(clist);
865 gtk_widget_show(scrolled_win);
867 /* For the bottom-right cell we add the 'Reset Filter' button. */
868 if (top == 2 && left == 2)
870 vbox = gtk_vbox_new(FALSE, 0);
871 gtk_widget_show(vbox);
872 gtk_table_attach (GTK_TABLE (table), vbox, left, left + 1,
873 top + 1, top + 2, GTK_FILL, GTK_FILL, 0, 0);
875 gtk_box_pack_start (GTK_BOX (vbox), scrolled_win, TRUE, TRUE, 0);
877 alignment = gtk_alignment_new(0.5, 0.0, 0.8, 0.0);
878 gtk_widget_show(alignment);
879 gtk_box_pack_start (GTK_BOX (vbox), alignment, FALSE, TRUE, 4);
881 button = gtk_button_new_with_label(_("Reset Filter"));
882 gtk_widget_show(button);
883 gtk_container_add(GTK_CONTAINER(alignment), button);
884 gtk_signal_connect (GTK_OBJECT (button), "clicked",
885 GTK_SIGNAL_FUNC(gtk_font_selection_reset_filter),
889 gtk_table_attach (GTK_TABLE (table), scrolled_win,
890 left, left + 1, top + 1, top + 2,
891 GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
893 gtk_signal_connect (GTK_OBJECT (clist), "select_row",
894 GTK_SIGNAL_FUNC(gtk_font_selection_select_filter),
896 gtk_signal_connect (GTK_OBJECT (clist), "unselect_row",
897 GTK_SIGNAL_FUNC(gtk_font_selection_unselect_filter),
900 /* Insert the property names, expanded, and in sorted order.
901 But we make sure that the wildcard '*' is first. */
902 gtk_clist_freeze (GTK_CLIST(clist));
904 gtk_clist_append(GTK_CLIST(clist), &property);
906 for (i = 1; i < fontsel_info->nproperties[prop]; i++) {
907 property = _(fontsel_info->properties[prop][i]);
909 property = gtk_font_selection_expand_slant_code(property);
910 else if (prop == SPACING)
911 property = gtk_font_selection_expand_spacing_code(property);
914 for (row = 1; row < GTK_CLIST(clist)->rows; row++)
916 gtk_clist_get_text(GTK_CLIST(clist), row, 0, &text);
917 if (strcmp(property, text) < 0)
920 gtk_clist_insert(GTK_CLIST(clist), row, &property);
925 row = gtk_clist_append(GTK_CLIST(clist), &property);
926 gtk_clist_set_row_data(GTK_CLIST(clist), row, GINT_TO_POINTER (i));
928 gtk_clist_select_row(GTK_CLIST(clist), 0, 0);
929 gtk_clist_thaw (GTK_CLIST(clist));
930 fontsel->filter_clists[prop] = clist;
935 gtk_font_selection_new()
937 GtkFontSelection *fontsel;
939 fontsel = gtk_type_new (GTK_TYPE_FONT_SELECTION);
941 return GTK_WIDGET (fontsel);
945 gtk_font_selection_destroy (GtkObject *object)
947 GtkFontSelection *fontsel;
949 g_return_if_fail (object != NULL);
950 g_return_if_fail (GTK_IS_FONT_SELECTION (object));
952 fontsel = GTK_FONT_SELECTION (object);
954 /* All we have to do is unref the font, if we have one. */
956 gdk_font_unref (fontsel->font);
958 if (GTK_OBJECT_CLASS (font_selection_parent_class)->destroy)
959 (* GTK_OBJECT_CLASS (font_selection_parent_class)->destroy) (object);
963 /* This is called when the clist is exposed. Here we scroll to the current
964 font if necessary. */
966 gtk_font_selection_expose_list (GtkWidget *widget,
967 GdkEventExpose *event,
970 GtkFontSelection *fontsel;
976 g_message("In expose_list\n");
978 fontsel = GTK_FONT_SELECTION(data);
980 font_info = fontsel_info->font_info;
982 /* Try to scroll the font family clist to the selected item */
983 selection = GTK_CLIST(fontsel->font_clist)->selection;
986 index = GPOINTER_TO_INT (selection->data);
987 if (gtk_clist_row_is_visible(GTK_CLIST(fontsel->font_clist), index)
988 != GTK_VISIBILITY_FULL)
989 gtk_clist_moveto(GTK_CLIST(fontsel->font_clist), index, -1, 0.5, 0);
992 /* Try to scroll the font style clist to the selected item */
993 selection = GTK_CLIST(fontsel->font_style_clist)->selection;
996 index = GPOINTER_TO_INT (selection->data);
997 if (gtk_clist_row_is_visible(GTK_CLIST(fontsel->font_style_clist), index)
998 != GTK_VISIBILITY_FULL)
999 gtk_clist_moveto(GTK_CLIST(fontsel->font_style_clist), index, -1,
1003 /* Try to scroll the font size clist to the selected item */
1004 selection = GTK_CLIST(fontsel->size_clist)->selection;
1007 index = GPOINTER_TO_INT (selection->data);
1008 if (gtk_clist_row_is_visible(GTK_CLIST(fontsel->size_clist), index)
1009 != GTK_VISIBILITY_FULL)
1010 gtk_clist_moveto(GTK_CLIST(fontsel->size_clist), index, -1, 0.5, 0);
1015 /* This is called when the style clist is realized. We need to set any
1016 charset rows to insensitive colours. */
1018 gtk_font_selection_realize_list (GtkWidget *widget,
1021 GtkFontSelection *fontsel;
1023 GdkColor *inactive_fg, *inactive_bg;
1025 #ifdef FONTSEL_DEBUG
1026 g_message("In realize_list\n");
1028 fontsel = GTK_FONT_SELECTION (data);
1030 /* Set the colours for any charset rows to insensitive. */
1031 inactive_fg = &fontsel->font_style_clist->style->fg[GTK_STATE_INSENSITIVE];
1032 inactive_bg = &fontsel->font_style_clist->style->bg[GTK_STATE_INSENSITIVE];
1034 for (row = 0; row < GTK_CLIST (fontsel->font_style_clist)->rows; row++)
1036 if (GPOINTER_TO_INT (gtk_clist_get_row_data (GTK_CLIST (fontsel->font_style_clist), row)) == -1)
1038 gtk_clist_set_foreground (GTK_CLIST (fontsel->font_style_clist),
1040 gtk_clist_set_background (GTK_CLIST (fontsel->font_style_clist),
1047 /* This is called when a family is selected in the list. */
1049 gtk_font_selection_select_font (GtkWidget *w,
1052 GdkEventButton *bevent,
1055 GtkFontSelection *fontsel;
1056 FontInfo *font_info;
1059 #ifdef FONTSEL_DEBUG
1060 g_message("In select_font\n");
1062 fontsel = GTK_FONT_SELECTION(data);
1063 font_info = fontsel_info->font_info;
1065 if (bevent && !GTK_WIDGET_HAS_FOCUS (w))
1066 gtk_widget_grab_focus (w);
1068 row = GPOINTER_TO_INT (gtk_clist_get_row_data (GTK_CLIST (fontsel->font_clist), row));
1069 font = &font_info[row];
1070 gtk_entry_set_text(GTK_ENTRY(fontsel->font_entry), font->family);
1072 /* If it is already the current font, just return. */
1073 if (fontsel->font_index == row)
1076 fontsel->font_index = row;
1077 gtk_font_selection_show_available_styles (fontsel);
1078 gtk_font_selection_select_best_style (fontsel, TRUE);
1083 gtk_font_selection_on_clist_key_press (GtkWidget *clist,
1085 GtkFontSelection *fontsel)
1087 #ifdef FONTSEL_DEBUG
1088 g_message("In on_clist_key_press\n");
1090 if (event->keyval == GDK_Up)
1091 return gtk_font_selection_select_next (fontsel, clist, -1);
1092 else if (event->keyval == GDK_Down)
1093 return gtk_font_selection_select_next (fontsel, clist, 1);
1100 gtk_font_selection_select_next (GtkFontSelection *fontsel,
1105 gint current_row, row;
1107 selection = GTK_CLIST(clist)->selection;
1110 current_row = GPOINTER_TO_INT (selection->data);
1112 /* Stop the normal clist key handler from being run. */
1113 gtk_signal_emit_stop_by_name (GTK_OBJECT (clist), "key_press_event");
1115 for (row = current_row + step;
1116 row >= 0 && row < GTK_CLIST(clist)->rows;
1119 /* If this is the style clist, make sure that the item is not a charset
1121 if (clist == fontsel->font_style_clist)
1122 if (GPOINTER_TO_INT (gtk_clist_get_row_data(GTK_CLIST(clist), row)) == -1)
1125 /* Now we've found the row to select. */
1126 if (gtk_clist_row_is_visible(GTK_CLIST(clist), row)
1127 != GTK_VISIBILITY_FULL)
1128 gtk_clist_moveto(GTK_CLIST(clist), row, -1, (step < 0) ? 0 : 1, 0);
1129 gtk_clist_select_row(GTK_CLIST(clist), row, 0);
1136 /* This fills the font style clist with all the possible style combinations
1137 for the current font family. */
1139 gtk_font_selection_show_available_styles (GtkFontSelection *fontsel)
1143 gint style, tmpstyle, row;
1144 gint weight_index, slant_index, set_width_index, spacing_index;
1146 gchar *weight, *slant, *set_width, *spacing;
1147 gchar *charset = NULL;
1149 gchar buffer[XLFD_MAX_FIELD_LEN * 6 + 2];
1150 GdkColor *inactive_fg, *inactive_bg;
1151 gboolean show_charset;
1153 #ifdef FONTSEL_DEBUG
1154 g_message("In show_available_styles\n");
1156 font = &fontsel_info->font_info[fontsel->font_index];
1157 styles = &fontsel_info->font_styles[font->style_index];
1159 gtk_clist_freeze (GTK_CLIST(fontsel->font_style_clist));
1160 gtk_clist_clear (GTK_CLIST(fontsel->font_style_clist));
1162 /* First we mark all visible styles as not having been displayed yet,
1163 and check if every style has the same charset. If not then we will
1164 display the charset in the list before the styles. */
1165 show_charset = FALSE;
1167 for (style = 0; style < font->nstyles; style++)
1169 if (gtk_font_selection_style_visible(fontsel, font, style))
1171 styles[style].flags &= ~GTK_FONT_DISPLAYED;
1173 if (charset_index == -1)
1174 charset_index = styles[style].properties[CHARSET];
1175 else if (charset_index != styles[style].properties[CHARSET])
1176 show_charset = TRUE;
1179 styles[style].flags |= GTK_FONT_DISPLAYED;
1182 /* Step through the undisplayed styles, finding the next charset which
1183 hasn't been displayed yet. Then display the charset on one line, if
1184 necessary, and the visible styles indented beneath it. */
1185 inactive_fg = &fontsel->font_style_clist->style->fg[GTK_STATE_INSENSITIVE];
1186 inactive_bg = &fontsel->font_style_clist->style->bg[GTK_STATE_INSENSITIVE];
1188 for (style = 0; style < font->nstyles; style++)
1190 if (styles[style].flags & GTK_FONT_DISPLAYED)
1195 charset_index = styles[style].properties[CHARSET];
1196 charset = fontsel_info->properties[CHARSET] [charset_index];
1197 row = gtk_clist_append(GTK_CLIST(fontsel->font_style_clist),
1199 gtk_clist_set_row_data(GTK_CLIST(fontsel->font_style_clist), row,
1201 if (GTK_WIDGET_REALIZED (fontsel->font_style_clist))
1203 gtk_clist_set_foreground(GTK_CLIST(fontsel->font_style_clist),
1205 gtk_clist_set_background(GTK_CLIST(fontsel->font_style_clist),
1210 for (tmpstyle = style; tmpstyle < font->nstyles; tmpstyle++)
1212 if (styles[tmpstyle].flags & GTK_FONT_DISPLAYED
1213 || charset_index != styles[tmpstyle].properties[CHARSET])
1216 styles[tmpstyle].flags |= GTK_FONT_DISPLAYED;
1218 weight_index = styles[tmpstyle].properties[WEIGHT];
1219 slant_index = styles[tmpstyle].properties[SLANT];
1220 set_width_index = styles[tmpstyle].properties[SET_WIDTH];
1221 spacing_index = styles[tmpstyle].properties[SPACING];
1222 weight = fontsel_info->properties[WEIGHT] [weight_index];
1223 slant = fontsel_info->properties[SLANT] [slant_index];
1224 set_width = fontsel_info->properties[SET_WIDTH][set_width_index];
1225 spacing = fontsel_info->properties[SPACING] [spacing_index];
1227 /* Convert '(nil)' weights to 'regular', since it looks nicer. */
1228 if (!g_strcasecmp(weight, N_("(nil)"))) weight = N_("regular");
1230 /* We don't show default values or (nil) in the other properties. */
1231 if (!g_strcasecmp(slant, "r")) slant = NULL;
1232 else if (!g_strcasecmp(slant, "(nil)")) slant = NULL;
1233 else if (!g_strcasecmp(slant, "i")) slant = N_("italic");
1234 else if (!g_strcasecmp(slant, "o")) slant = N_("oblique");
1235 else if (!g_strcasecmp(slant, "ri")) slant = N_("reverse italic");
1236 else if (!g_strcasecmp(slant, "ro")) slant = N_("reverse oblique");
1237 else if (!g_strcasecmp(slant, "ot")) slant = N_("other");
1239 if (!g_strcasecmp(set_width, "normal")) set_width = NULL;
1240 else if (!g_strcasecmp(set_width, "(nil)")) set_width = NULL;
1242 if (!g_strcasecmp(spacing, "p")) spacing = NULL;
1243 else if (!g_strcasecmp(spacing, "(nil)")) spacing = NULL;
1244 else if (!g_strcasecmp(spacing, "m")) spacing = N_("[M]");
1245 else if (!g_strcasecmp(spacing, "c")) spacing = N_("[C]");
1247 /* Add the strings together, making sure there is 1 space between
1249 strcpy(buffer, _(weight));
1252 strcat(buffer, " ");
1253 strcat(buffer, _(slant));
1257 strcat(buffer, " ");
1258 strcat(buffer, _(set_width));
1262 strcat(buffer, " ");
1263 strcat(buffer, _(spacing));
1267 row = gtk_clist_append(GTK_CLIST(fontsel->font_style_clist),
1270 gtk_clist_set_shift(GTK_CLIST(fontsel->font_style_clist), row, 0,
1272 gtk_clist_set_row_data(GTK_CLIST(fontsel->font_style_clist), row,
1273 GINT_TO_POINTER (tmpstyle));
1277 gtk_clist_thaw (GTK_CLIST(fontsel->font_style_clist));
1281 /* This selects a style when the user selects a font. It just uses the first
1282 available style at present. I was thinking of trying to maintain the
1283 selected style, e.g. bold italic, when the user selects different fonts.
1284 However, the interface is so easy to use now I'm not sure it's worth it.
1285 Note: This will load a font. */
1287 gtk_font_selection_select_best_style(GtkFontSelection *fontsel,
1292 gint row, prop, style, matched;
1293 gint best_matched = -1, best_style = -1, best_row = -1;
1295 #ifdef FONTSEL_DEBUG
1296 g_message("In select_best_style\n");
1298 font = &fontsel_info->font_info[fontsel->font_index];
1299 styles = &fontsel_info->font_styles[font->style_index];
1301 for (row = 0; row < GTK_CLIST(fontsel->font_style_clist)->rows; row++)
1303 style = GPOINTER_TO_INT (gtk_clist_get_row_data (GTK_CLIST (fontsel->font_style_clist), row));
1304 /* Skip charset rows. */
1308 /* If we just want the first style, we've got it. */
1317 for (prop = 0; prop < GTK_NUM_STYLE_PROPERTIES; prop++)
1319 if (fontsel->property_values[prop] == styles[style].properties[prop])
1322 if (matched > best_matched)
1324 best_matched = matched;
1329 g_return_if_fail (best_style != -1);
1330 g_return_if_fail (best_row != -1);
1332 fontsel->style = best_style;
1334 for (prop = 0; prop < GTK_NUM_STYLE_PROPERTIES; prop++)
1335 fontsel->property_values[prop] = styles[fontsel->style].properties[prop];
1337 gtk_clist_select_row(GTK_CLIST(fontsel->font_style_clist), best_row, 0);
1338 if (gtk_clist_row_is_visible(GTK_CLIST(fontsel->font_style_clist), best_row)
1339 != GTK_VISIBILITY_FULL)
1340 gtk_clist_moveto(GTK_CLIST(fontsel->font_style_clist), best_row, -1,
1342 gtk_font_selection_show_available_sizes (fontsel);
1343 gtk_font_selection_select_best_size (fontsel);
1347 /* This is called when a style is selected in the list. */
1349 gtk_font_selection_select_style (GtkWidget *w,
1352 GdkEventButton *bevent,
1355 GtkFontSelection *fontsel;
1356 FontInfo *font_info;
1362 #ifdef FONTSEL_DEBUG
1363 g_message("In select_style\n");
1365 fontsel = GTK_FONT_SELECTION(data);
1366 font_info = fontsel_info->font_info;
1367 font = &font_info[fontsel->font_index];
1368 styles = &fontsel_info->font_styles[font->style_index];
1370 if (bevent && !GTK_WIDGET_HAS_FOCUS (w))
1371 gtk_widget_grab_focus (w);
1373 /* The style index is stored in the row data, so we just need to copy
1374 the style values into the fontsel and reload the font. */
1375 style = GPOINTER_TO_INT (gtk_clist_get_row_data(GTK_CLIST(fontsel->font_style_clist), row));
1377 /* Don't allow selection of charset rows. */
1380 gtk_clist_unselect_row(GTK_CLIST(fontsel->font_style_clist), row, 0);
1384 gtk_clist_get_text(GTK_CLIST(fontsel->font_style_clist), row, 0, &text);
1385 gtk_entry_set_text(GTK_ENTRY(fontsel->font_style_entry), text);
1387 for (prop = 0; prop < GTK_NUM_STYLE_PROPERTIES; prop++)
1388 fontsel->property_values[prop] = styles[style].properties[prop];
1390 if (fontsel->style == style)
1393 fontsel->style = style;
1394 gtk_font_selection_show_available_sizes (fontsel);
1395 gtk_font_selection_select_best_size (fontsel);
1399 /* This shows all the available sizes in the size clist, according to the
1400 current metric and the current font & style. */
1402 gtk_font_selection_show_available_sizes (GtkFontSelection *fontsel)
1405 FontStyle *styles, *style;
1406 const guint16 *standard_sizes;
1407 guint16 *bitmapped_sizes;
1408 gint nstandard_sizes, nbitmapped_sizes;
1409 gchar buffer[16], *size;
1410 gfloat bitmap_size_float = 0.;
1411 guint16 bitmap_size = 0;
1415 #ifdef FONTSEL_DEBUG
1416 g_message("In show_available_sizes\n");
1418 font = &fontsel_info->font_info[fontsel->font_index];
1419 styles = &fontsel_info->font_styles[font->style_index];
1420 style = &styles[fontsel->style];
1422 standard_sizes = font_sizes;
1423 nstandard_sizes = sizeof(font_sizes) / sizeof(font_sizes[0]);
1424 if (fontsel->metric == GTK_FONT_METRIC_POINTS)
1426 bitmapped_sizes = &fontsel_info->point_sizes[style->point_sizes_index];
1427 nbitmapped_sizes = style->npoint_sizes;
1431 bitmapped_sizes = &fontsel_info->pixel_sizes[style->pixel_sizes_index];
1432 nbitmapped_sizes = style->npixel_sizes;
1435 /* Only show the standard sizes if a scalable font is available. */
1436 type_filter = fontsel->filters[GTK_FONT_FILTER_BASE].font_type
1437 & fontsel->filters[GTK_FONT_FILTER_USER].font_type;
1439 if (!((style->flags & GTK_FONT_SCALABLE_BITMAP
1440 && type_filter & GTK_FONT_SCALABLE_BITMAP)
1441 || (style->flags & GTK_FONT_SCALABLE
1442 && type_filter & GTK_FONT_SCALABLE)))
1443 nstandard_sizes = 0;
1445 gtk_clist_freeze (GTK_CLIST(fontsel->size_clist));
1446 gtk_clist_clear (GTK_CLIST(fontsel->size_clist));
1448 /* Interleave the standard sizes with the bitmapped sizes so we get a list
1449 of ascending sizes. If the metric is points, we have to convert the
1450 decipoints to points. */
1451 while (nstandard_sizes || nbitmapped_sizes)
1455 if (nbitmapped_sizes)
1456 if (fontsel->metric == GTK_FONT_METRIC_POINTS)
1458 if (*bitmapped_sizes % 10 != 0)
1460 bitmap_size = *bitmapped_sizes / 10;
1461 bitmap_size_float = *bitmapped_sizes / 10;
1465 bitmap_size = *bitmapped_sizes;
1466 bitmap_size_float = *bitmapped_sizes;
1469 if (can_match && nstandard_sizes && nbitmapped_sizes
1470 && *standard_sizes == bitmap_size)
1472 sprintf(buffer, "%i *", *standard_sizes);
1478 else if (nstandard_sizes
1479 && (!nbitmapped_sizes
1480 || (gfloat)*standard_sizes < bitmap_size_float))
1482 sprintf(buffer, "%i", *standard_sizes);
1488 if (fontsel->metric == GTK_FONT_METRIC_POINTS)
1490 if (*bitmapped_sizes % 10 == 0)
1491 sprintf(buffer, "%i *", *bitmapped_sizes / 10);
1493 sprintf(buffer, "%i.%i *", *bitmapped_sizes / 10,
1494 *bitmapped_sizes % 10);
1498 sprintf(buffer, "%i *", *bitmapped_sizes);
1504 gtk_clist_append(GTK_CLIST(fontsel->size_clist), &size);
1506 gtk_clist_thaw (GTK_CLIST(fontsel->size_clist));
1510 /* If the user hits return in the font size entry, we change to the new font
1513 gtk_font_selection_size_key_press (GtkWidget *w,
1517 GtkFontSelection *fontsel;
1519 gfloat new_size_float;
1522 #ifdef FONTSEL_DEBUG
1523 g_message("In size_key_press\n");
1525 fontsel = GTK_FONT_SELECTION(data);
1527 if (event->keyval == GDK_Return)
1529 text = gtk_entry_get_text (GTK_ENTRY (fontsel->size_entry));
1530 if (fontsel->metric == GTK_FONT_METRIC_PIXELS)
1532 new_size = atoi (text);
1538 new_size_float = atof (text) * 10;
1539 new_size = (gint) new_size_float;
1544 /* Remember that this size was set explicitly. */
1545 fontsel->selected_size = new_size;
1547 /* Check if the font size has changed, and return if it hasn't. */
1548 if (fontsel->size == new_size)
1551 fontsel->size = new_size;
1552 gtk_font_selection_select_best_size (fontsel);
1560 /* This tries to select the closest size to the current size, though it
1561 may have to change the size if only unscaled bitmaps are available.
1562 Note: this will load a font. */
1564 gtk_font_selection_select_best_size(GtkFontSelection *fontsel)
1567 FontStyle *styles, *style;
1569 gint row, best_row = 0, size, size_fraction, best_size = 0, nmatched;
1570 gboolean found = FALSE;
1575 #ifdef FONTSEL_DEBUG
1576 g_message("In select_best_size\n");
1578 font = &fontsel_info->font_info[fontsel->font_index];
1579 styles = &fontsel_info->font_styles[font->style_index];
1580 style = &styles[fontsel->style];
1582 /* Find the closest size available in the size clist. If the exact size is
1583 in the list set found to TRUE. */
1584 for (row = 0; row < GTK_CLIST(fontsel->size_clist)->rows; row++)
1586 gtk_clist_get_text(GTK_CLIST(fontsel->size_clist), row, 0, &text);
1587 nmatched = sscanf(text, "%i.%i", &size, &size_fraction);
1588 if (fontsel->metric == GTK_FONT_METRIC_POINTS)
1592 size += size_fraction;
1595 if (size == fontsel->selected_size)
1602 else if (best_size == 0
1603 || abs(size - fontsel->selected_size)
1604 < (abs(best_size - fontsel->selected_size)))
1611 /* If we aren't scaling bitmapped fonts and this is a bitmapped font, we
1612 need to use the closest size found. */
1613 type_filter = fontsel->filters[GTK_FONT_FILTER_BASE].font_type
1614 & fontsel->filters[GTK_FONT_FILTER_USER].font_type;
1616 if (!((style->flags & GTK_FONT_SCALABLE_BITMAP
1617 && type_filter & GTK_FONT_SCALABLE_BITMAP)
1618 || (style->flags & GTK_FONT_SCALABLE
1619 && type_filter & GTK_FONT_SCALABLE)))
1624 fontsel->size = best_size;
1625 gtk_clist_moveto(GTK_CLIST(fontsel->size_clist), best_row, -1, 0.5, 0);
1626 gtk_clist_select_row(GTK_CLIST(fontsel->size_clist), best_row, 0);
1630 fontsel->size = fontsel->selected_size;
1631 selection = GTK_CLIST(fontsel->size_clist)->selection;
1633 gtk_clist_unselect_row(GTK_CLIST(fontsel->size_clist),
1634 GPOINTER_TO_INT (selection->data), 0);
1635 gtk_clist_moveto(GTK_CLIST(fontsel->size_clist), best_row, -1, 0.5, 0);
1637 /* Show the size in the size entry. */
1638 if (fontsel->metric == GTK_FONT_METRIC_PIXELS)
1639 sprintf(buffer, "%i", fontsel->size);
1642 if (fontsel->size % 10 == 0)
1643 sprintf(buffer, "%i", fontsel->size / 10);
1645 sprintf(buffer, "%i.%i", fontsel->size / 10, fontsel->size % 10);
1647 gtk_entry_set_text (GTK_ENTRY (fontsel->size_entry), buffer);
1649 gtk_font_selection_load_font (fontsel);
1653 /* This is called when a size is selected in the list. */
1655 gtk_font_selection_select_size (GtkWidget *w,
1658 GdkEventButton *bevent,
1661 GtkFontSelection *fontsel;
1667 #ifdef FONTSEL_DEBUG
1668 g_message("In select_size\n");
1670 fontsel = GTK_FONT_SELECTION(data);
1672 if (bevent && !GTK_WIDGET_HAS_FOCUS (w))
1673 gtk_widget_grab_focus (w);
1675 /* Copy the size from the clist to the size entry, but without the bitmapped
1677 gtk_clist_get_text(GTK_CLIST(fontsel->size_clist), row, 0, &text);
1679 while (i < 15 && (text[i] == '.' || (text[i] >= '0' && text[i] <= '9')))
1681 buffer[i] = text[i];
1685 gtk_entry_set_text(GTK_ENTRY(fontsel->size_entry), buffer);
1687 /* Check if the font size has changed, and return if it hasn't. */
1688 new_size = atoi(text);
1689 if (fontsel->metric == GTK_FONT_METRIC_POINTS)
1692 if (fontsel->size == new_size)
1695 /* If the size was selected by the user we set the selected_size. */
1696 fontsel->selected_size = new_size;
1698 fontsel->size = new_size;
1699 gtk_font_selection_load_font (fontsel);
1703 /* This is called when the pixels or points radio buttons are pressed. */
1705 gtk_font_selection_metric_callback (GtkWidget *w,
1708 GtkFontSelection *fontsel = GTK_FONT_SELECTION(data);
1710 #ifdef FONTSEL_DEBUG
1711 g_message("In metric_callback\n");
1713 if (GTK_TOGGLE_BUTTON(fontsel->pixels_button)->active)
1715 if (fontsel->metric == GTK_FONT_METRIC_PIXELS)
1717 fontsel->metric = GTK_FONT_METRIC_PIXELS;
1718 fontsel->size = (fontsel->size + 5) / 10;
1719 fontsel->selected_size = (fontsel->selected_size + 5) / 10;
1723 if (fontsel->metric == GTK_FONT_METRIC_POINTS)
1725 fontsel->metric = GTK_FONT_METRIC_POINTS;
1726 fontsel->size *= 10;
1727 fontsel->selected_size *= 10;
1729 if (fontsel->font_index != -1)
1731 gtk_font_selection_show_available_sizes (fontsel);
1732 gtk_font_selection_select_best_size (fontsel);
1737 /* This searches the given property table and returns the index of the given
1738 string, or 0, which is the wildcard '*' index, if it's not found. */
1740 gtk_font_selection_field_to_index (gchar **table,
1746 for (i = 0; i < ntable; i++)
1747 if (strcmp (field, table[i]) == 0)
1755 /* This attempts to load the current font, and returns TRUE if it succeeds. */
1757 gtk_font_selection_load_font (GtkFontSelection *fontsel)
1760 gchar *fontname, *label_text;
1763 gdk_font_unref (fontsel->font);
1764 fontsel->font = NULL;
1766 /* If no family has been selected yet, just return FALSE. */
1767 if (fontsel->font_index == -1)
1770 fontname = gtk_font_selection_get_font_name (fontsel);
1773 #ifdef FONTSEL_DEBUG
1774 g_message("Loading: %s\n", fontname);
1776 font = gdk_font_load (fontname);
1781 fontsel->font = font;
1782 /* Make sure the message label is empty, but don't change it unless
1783 it's necessary as it results in a resize of the whole window! */
1784 gtk_label_get(GTK_LABEL(fontsel->message_label), &label_text);
1785 if (strcmp(label_text, ""))
1786 gtk_label_set_text(GTK_LABEL(fontsel->message_label), "");
1787 gtk_font_selection_update_preview (fontsel);
1792 gtk_label_set_text(GTK_LABEL(fontsel->message_label),
1793 _("The selected font is not available."));
1798 gtk_label_set_text(GTK_LABEL(fontsel->message_label),
1799 _("The selected font is not a valid font."));
1806 /* This sets the font in the preview entry to the selected font, and tries to
1807 make sure that the preview entry is a reasonable size, i.e. so that the
1808 text can be seen with a bit of space to spare. But it tries to avoid
1809 resizing the entry every time the font changes.
1810 This also used to shrink the preview if the font size was decreased, but
1811 that made it awkward if the user wanted to resize the window themself. */
1813 gtk_font_selection_update_preview (GtkFontSelection *fontsel)
1815 GtkWidget *preview_entry;
1817 gint text_height, new_height;
1819 #ifdef GDK_WINDOWING_X11
1823 #ifdef FONTSEL_DEBUG
1824 g_message("In update_preview\n");
1826 style = gtk_style_new ();
1827 gdk_font_unref (style->font);
1828 style->font = fontsel->font;
1829 gdk_font_ref (style->font);
1831 preview_entry = fontsel->preview_entry;
1832 gtk_widget_set_style (preview_entry, style);
1833 gtk_style_unref(style);
1835 text_height = preview_entry->style->font->ascent
1836 + preview_entry->style->font->descent;
1837 /* We don't ever want to be over MAX_PREVIEW_HEIGHT pixels high. */
1838 new_height = text_height + 20;
1839 if (new_height < INITIAL_PREVIEW_HEIGHT)
1840 new_height = INITIAL_PREVIEW_HEIGHT;
1841 if (new_height > MAX_PREVIEW_HEIGHT)
1842 new_height = MAX_PREVIEW_HEIGHT;
1844 if ((preview_entry->requisition.height < text_height + 10)
1845 || (preview_entry->requisition.height > text_height + 40))
1846 gtk_widget_set_usize(preview_entry, -1, new_height);
1848 /* This sets the preview text, if it hasn't been set already. */
1849 text = gtk_entry_get_text(GTK_ENTRY(fontsel->preview_entry));
1850 if (strlen(text) == 0)
1851 gtk_entry_set_text(GTK_ENTRY(fontsel->preview_entry), PREVIEW_TEXT);
1852 gtk_entry_set_position(GTK_ENTRY(fontsel->preview_entry), 0);
1854 #ifdef GDK_WINDOWING_X11
1855 /* If this is a 2-byte font display a message to say it may not be
1856 displayed properly. */
1857 xfs = GDK_FONT_XFONT(fontsel->font);
1858 if (xfs->min_byte1 != 0 || xfs->max_byte1 != 0)
1859 gtk_label_set_text(GTK_LABEL(fontsel->message_label),
1860 _("This is a 2-byte font and may not be displayed correctly."));
1866 gtk_font_selection_switch_page (GtkWidget *w,
1867 GtkNotebookPage *page,
1871 GtkFontSelection *fontsel = GTK_FONT_SELECTION(data);
1873 /* This function strangely gets called when the window is destroyed,
1874 so we check here to see if the notebook is visible. */
1875 if (!GTK_WIDGET_VISIBLE(w))
1879 gtk_font_selection_update_filter(fontsel);
1880 else if (page_num == 1)
1881 gtk_font_selection_show_font_info(fontsel);
1886 gtk_font_selection_show_font_info (GtkFontSelection *fontsel)
1888 #ifdef GDK_WINDOWING_X11
1889 Atom font_atom, atom;
1894 gchar field_buffer[XLFD_MAX_FIELD_LEN];
1897 gboolean shown_actual_fields = FALSE;
1899 fontname = gtk_font_selection_get_font_name(fontsel);
1900 gtk_entry_set_text(GTK_ENTRY(fontsel->requested_font_name),
1901 fontname ? fontname : "");
1903 gtk_clist_freeze (GTK_CLIST(fontsel->info_clist));
1904 for (i = 0; i < GTK_XLFD_NUM_FIELDS; i++)
1907 field = gtk_font_selection_get_xlfd_field (fontname, i, field_buffer);
1912 if (i == XLFD_SLANT)
1913 field = gtk_font_selection_expand_slant_code(field);
1914 else if (i == XLFD_SPACING)
1915 field = gtk_font_selection_expand_spacing_code(field);
1917 gtk_clist_set_text(GTK_CLIST(fontsel->info_clist), i, 1,
1918 field ? field : "");
1920 #ifdef GDK_WINDOWING_X11
1923 font_atom = XInternAtom(GDK_DISPLAY(), "FONT", True);
1924 if (font_atom != None)
1926 status = XGetFontProperty(GDK_FONT_XFONT(fontsel->font), font_atom,
1930 name = XGetAtomName(GDK_DISPLAY(), atom);
1931 gtk_entry_set_text(GTK_ENTRY(fontsel->actual_font_name), name);
1933 for (i = 0; i < GTK_XLFD_NUM_FIELDS; i++)
1935 field = gtk_font_selection_get_xlfd_field (name, i,
1937 if (i == XLFD_SLANT)
1938 field = gtk_font_selection_expand_slant_code(field);
1939 else if (i == XLFD_SPACING)
1940 field = gtk_font_selection_expand_spacing_code(field);
1941 gtk_clist_set_text(GTK_CLIST(fontsel->info_clist), i, 2,
1942 field ? field : "");
1944 shown_actual_fields = TRUE;
1949 #elif defined (GDK_WINDOWING_WIN32)
1954 if (GetObject (GDK_FONT_XFONT (fontsel->font),
1955 sizeof (LOGFONT), &logfont) > 0)
1957 name = logfont_to_xlfd (&logfont, logfont.lfHeight, -1, 0);
1958 gtk_entry_set_text (GTK_ENTRY(fontsel->actual_font_name),name);
1959 for (i = 0; i < GTK_XLFD_NUM_FIELDS; i++)
1961 field = gtk_font_selection_get_xlfd_field (name, i,
1963 if (i == XLFD_SLANT)
1964 field = gtk_font_selection_expand_slant_code(field);
1965 else if (i == XLFD_SPACING)
1966 field = gtk_font_selection_expand_spacing_code(field);
1967 gtk_clist_set_text(GTK_CLIST(fontsel->info_clist), i, 2,
1968 field ? field : "");
1970 shown_actual_fields = TRUE;
1976 if (!shown_actual_fields)
1978 gtk_entry_set_text(GTK_ENTRY(fontsel->actual_font_name), "");
1979 for (i = 0; i < GTK_XLFD_NUM_FIELDS; i++)
1981 gtk_clist_set_text(GTK_CLIST(fontsel->info_clist), i, 2,
1982 fontname ? _("(unknown)") : "");
1985 gtk_clist_thaw (GTK_CLIST(fontsel->info_clist));
1991 gtk_font_selection_expand_slant_code(gchar *slant)
1993 if (!g_strcasecmp(slant, "r")) return(_("roman"));
1994 else if (!g_strcasecmp(slant, "i")) return(_("italic"));
1995 else if (!g_strcasecmp(slant, "o")) return(_("oblique"));
1996 else if (!g_strcasecmp(slant, "ri")) return(_("reverse italic"));
1997 else if (!g_strcasecmp(slant, "ro")) return(_("reverse oblique"));
1998 else if (!g_strcasecmp(slant, "ot")) return(_("other"));
2003 gtk_font_selection_expand_spacing_code(gchar *spacing)
2005 if (!g_strcasecmp(spacing, "p")) return(_("proportional"));
2006 else if (!g_strcasecmp(spacing, "m")) return(_("monospaced"));
2007 else if (!g_strcasecmp(spacing, "c")) return(_("char cell"));
2012 /*****************************************************************************
2013 * These functions all deal with the Filter page and filtering the fonts.
2014 *****************************************************************************/
2016 /* This is called when an item is selected in one of the filter clists.
2017 We make sure that the first row of the clist, i.e. the wildcard '*', is
2018 selected if and only if none of the other items are selected.
2019 Also doesn't allow selections of values filtered out by base filter.
2020 We may need to be careful about triggering other signals. */
2022 gtk_font_selection_select_filter (GtkWidget *w,
2025 GdkEventButton *bevent,
2026 GtkFontSelection *fontsel)
2028 gint i, prop, index;
2032 for (i = 1; i < GTK_CLIST(w)->rows; i++)
2033 gtk_clist_unselect_row(GTK_CLIST(w), i, 0);
2037 /* Find out which property this is. */
2038 for (prop = 0; prop < GTK_NUM_FONT_PROPERTIES; prop++)
2039 if (fontsel->filter_clists[prop] == w)
2041 index = GPOINTER_TO_INT (gtk_clist_get_row_data(GTK_CLIST(w), row));
2042 if (gtk_font_selection_filter_state (fontsel, GTK_FONT_FILTER_BASE,
2043 prop, index) == NOT_FILTERED)
2044 gtk_clist_unselect_row(GTK_CLIST(w), row, 0);
2046 gtk_clist_unselect_row(GTK_CLIST(w), 0, 0);
2051 /* Here a filter item is being deselected. If there are now no items selected
2052 we select the first '*' item, unless that it is the item being deselected,
2053 in which case we select all of the other items. This makes it easy to
2054 select all items in the list except one or two. */
2056 gtk_font_selection_unselect_filter (GtkWidget *w,
2059 GdkEventButton *bevent,
2060 GtkFontSelection *fontsel)
2062 gint i, prop, index;
2064 if (!GTK_CLIST(w)->selection)
2068 /* Find out which property this is. */
2069 for (prop = 0; prop < GTK_NUM_FONT_PROPERTIES; prop++)
2070 if (fontsel->filter_clists[prop] == w)
2073 for (i = 1; i < GTK_CLIST(w)->rows; i++)
2075 index = GPOINTER_TO_INT (gtk_clist_get_row_data(GTK_CLIST(w),
2077 if (gtk_font_selection_filter_state (fontsel,
2078 GTK_FONT_FILTER_BASE,
2081 gtk_clist_select_row(GTK_CLIST(w), i, 0);
2086 gtk_clist_select_row(GTK_CLIST(w), 0, 0);
2092 /* This is called when the main notebook page is selected. It checks if the
2093 filter has changed, an if so it creates the filter settings, and filters the
2094 fonts shown. If an empty filter (all '*'s) is applied, then filtering is
2097 gtk_font_selection_update_filter (GtkFontSelection *fontsel)
2101 gboolean default_filter = TRUE, filter_changed = FALSE;
2102 gint prop, nselected, i, row, index;
2103 GtkFontFilter *filter = &fontsel->filters[GTK_FONT_FILTER_USER];
2104 gint base_font_type, user_font_type, new_font_type;
2106 #ifdef FONTSEL_DEBUG
2107 g_message("In update_filter\n");
2110 /* Check if the user filter has changed, and also if it is the default
2111 filter, i.e. bitmap & scalable fonts and all '*'s selected.
2112 We only look at the bits which are not already filtered out by the base
2113 filter, since that overrides the user filter. */
2114 base_font_type = fontsel->filters[GTK_FONT_FILTER_BASE].font_type
2116 user_font_type = fontsel->filters[GTK_FONT_FILTER_USER].font_type
2118 new_font_type = GTK_TOGGLE_BUTTON(fontsel->type_bitmaps_button)->active
2119 ? GTK_FONT_BITMAP : 0;
2120 new_font_type |= (GTK_TOGGLE_BUTTON(fontsel->type_scalable_button)->active
2121 ? GTK_FONT_SCALABLE : 0);
2122 new_font_type |= (GTK_TOGGLE_BUTTON(fontsel->type_scaled_bitmaps_button)->active ? GTK_FONT_SCALABLE_BITMAP : 0);
2123 new_font_type &= base_font_type;
2124 new_font_type |= (~base_font_type & user_font_type);
2125 if (new_font_type != (GTK_FONT_BITMAP | GTK_FONT_SCALABLE))
2126 default_filter = FALSE;
2128 if (new_font_type != user_font_type)
2129 filter_changed = TRUE;
2130 fontsel->filters[GTK_FONT_FILTER_USER].font_type = new_font_type;
2132 for (prop = 0; prop < GTK_NUM_FONT_PROPERTIES; prop++)
2134 clist = fontsel->filter_clists[prop];
2135 selection = GTK_CLIST(clist)->selection;
2136 nselected = g_list_length(selection);
2137 if (nselected != 1 || GPOINTER_TO_INT (selection->data) != 0)
2139 default_filter = FALSE;
2141 if (filter->property_nfilters[prop] != nselected)
2142 filter_changed = TRUE;
2145 for (i = 0; i < nselected; i++)
2147 row = GPOINTER_TO_INT (selection->data);
2148 index = GPOINTER_TO_INT (gtk_clist_get_row_data (GTK_CLIST (clist), row));
2149 if (filter->property_filters[prop][i] != index)
2150 filter_changed = TRUE;
2151 selection = selection->next;
2157 if (filter->property_nfilters[prop] != 0)
2158 filter_changed = TRUE;
2162 /* If the filter hasn't changed we just return. */
2163 if (!filter_changed)
2166 #ifdef FONTSEL_DEBUG
2167 g_message(" update_fonts: filter has changed\n");
2170 /* Free the old filter data and create the new arrays. */
2171 for (prop = 0; prop < GTK_NUM_FONT_PROPERTIES; prop++)
2173 g_free(filter->property_filters[prop]);
2175 clist = fontsel->filter_clists[prop];
2176 selection = GTK_CLIST(clist)->selection;
2177 nselected = g_list_length(selection);
2178 if (nselected == 1 && GPOINTER_TO_INT (selection->data) == 0)
2180 filter->property_filters[prop] = NULL;
2181 filter->property_nfilters[prop] = 0;
2185 filter->property_filters[prop] = g_new(guint16, nselected);
2186 filter->property_nfilters[prop] = nselected;
2187 for (i = 0; i < nselected; i++)
2189 row = GPOINTER_TO_INT (selection->data);
2190 index = GPOINTER_TO_INT (gtk_clist_get_row_data (GTK_CLIST (clist), row));
2191 filter->property_filters[prop][i] = index;
2192 selection = selection->next;
2197 /* Set the 'Reset Filter' button sensitive if a filter is in effect, and
2198 also set the label above the font list to show this as well. */
2201 gtk_widget_set_sensitive(fontsel->filter_button, FALSE);
2202 gtk_label_set_text(GTK_LABEL(fontsel->font_label), _("Font:"));
2206 gtk_widget_set_sensitive(fontsel->filter_button, TRUE);
2207 gtk_label_set_text(GTK_LABEL(fontsel->font_label), _("Font: (Filter Applied)"));
2209 gtk_font_selection_show_available_fonts(fontsel);
2213 /* This shows all the available fonts in the font clist. */
2215 gtk_font_selection_show_available_fonts (GtkFontSelection *fontsel)
2217 FontInfo *font_info, *font;
2218 GtkFontFilter *filter;
2219 gint nfonts, i, j, k, row, style, font_row = -1;
2220 gchar font_buffer[XLFD_MAX_FIELD_LEN * 2 + 4];
2222 gboolean matched, matched_style;
2224 #ifdef FONTSEL_DEBUG
2225 g_message("In show_available_fonts\n");
2227 font_info = fontsel_info->font_info;
2228 nfonts = fontsel_info->nfonts;
2230 /* Filter the list of fonts. */
2231 gtk_clist_freeze (GTK_CLIST(fontsel->font_clist));
2232 gtk_clist_clear (GTK_CLIST(fontsel->font_clist));
2233 for (i = 0; i < nfonts; i++)
2235 font = &font_info[i];
2237 /* Check if the foundry passes through all filters. */
2239 for (k = 0; k < GTK_NUM_FONT_FILTERS; k++)
2241 filter = &fontsel->filters[k];
2243 if (filter->property_nfilters[FOUNDRY] != 0)
2246 for (j = 0; j < filter->property_nfilters[FOUNDRY]; j++)
2248 if (font->foundry == filter->property_filters[FOUNDRY][j])
2263 /* Now check if the other properties are matched in at least one style.*/
2264 matched_style = FALSE;
2265 for (style = 0; style < font->nstyles; style++)
2267 if (gtk_font_selection_style_visible(fontsel, font, style))
2269 matched_style = TRUE;
2276 /* Insert the font in the clist. */
2277 if ((i > 0 && font->family == font_info[i-1].family)
2278 || (i < nfonts - 1 && font->family == font_info[i+1].family))
2280 sprintf(font_buffer, "%s (%s)", font->family,
2281 fontsel_info->properties[FOUNDRY][font->foundry]);
2282 font_item = font_buffer;
2283 row = gtk_clist_append(GTK_CLIST(fontsel->font_clist), &font_item);
2287 row = gtk_clist_append(GTK_CLIST(fontsel->font_clist),
2290 gtk_clist_set_row_data(GTK_CLIST(fontsel->font_clist), row,
2291 GINT_TO_POINTER (i));
2292 if (fontsel->font_index == i)
2295 gtk_clist_thaw (GTK_CLIST(fontsel->font_clist));
2297 /* If the currently-selected font isn't in the new list, reset the
2301 fontsel->font_index = -1;
2303 gdk_font_unref(fontsel->font);
2304 fontsel->font = NULL;
2305 gtk_entry_set_text(GTK_ENTRY(fontsel->font_entry), "");
2306 gtk_clist_clear (GTK_CLIST(fontsel->font_style_clist));
2307 gtk_entry_set_text(GTK_ENTRY(fontsel->font_style_entry), "");
2311 gtk_clist_select_row(GTK_CLIST(fontsel->font_clist), font_row, 0);
2312 if (gtk_clist_row_is_visible(GTK_CLIST(fontsel->font_clist), font_row)
2313 != GTK_VISIBILITY_FULL)
2314 gtk_clist_moveto(GTK_CLIST(fontsel->font_clist), font_row, -1, 0.5, 0);
2316 gtk_font_selection_show_available_styles (fontsel);
2317 gtk_font_selection_select_best_style (fontsel, FALSE);
2321 /* Returns TRUE if the style is not currently filtered out. */
2323 gtk_font_selection_style_visible(GtkFontSelection *fontsel,
2327 FontStyle *styles, *style;
2328 GtkFontFilter *filter;
2334 styles = &fontsel_info->font_styles[font->style_index];
2335 style = &styles[style_index];
2337 /* Check if font_type of style is filtered. */
2338 type_filter = fontsel->filters[GTK_FONT_FILTER_BASE].font_type
2339 & fontsel->filters[GTK_FONT_FILTER_USER].font_type;
2340 if (!(style->flags & type_filter))
2343 for (prop = 0; prop < GTK_NUM_STYLE_PROPERTIES; prop++)
2345 value = style->properties[prop];
2347 /* Check each filter. */
2348 for (i = 0; i < GTK_NUM_FONT_FILTERS; i++)
2350 filter = &fontsel->filters[i];
2352 if (filter->property_nfilters[prop] != 0)
2355 for (j = 0; j < filter->property_nfilters[prop]; j++)
2357 if (value == filter->property_filters[prop][j])
2372 /* This resets the font type to bitmap or scalable, and sets all the filter
2373 clists to the wildcard '*' options. */
2375 gtk_font_selection_reset_filter (GtkWidget *w,
2376 GtkFontSelection *fontsel)
2378 gint prop, base_font_type;
2380 fontsel->filters[GTK_FONT_FILTER_USER].font_type = GTK_FONT_BITMAP
2381 | GTK_FONT_SCALABLE;
2383 base_font_type = fontsel->filters[GTK_FONT_FILTER_BASE].font_type;
2384 if (base_font_type & GTK_FONT_BITMAP)
2385 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fontsel->type_bitmaps_button), TRUE);
2386 if (base_font_type & GTK_FONT_SCALABLE)
2387 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fontsel->type_scalable_button), TRUE);
2388 if (base_font_type & GTK_FONT_SCALABLE_BITMAP)
2389 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fontsel->type_scaled_bitmaps_button), FALSE);
2391 for (prop = 0; prop < GTK_NUM_FONT_PROPERTIES; prop++)
2392 gtk_clist_select_row(GTK_CLIST(fontsel->filter_clists[prop]), 0, 0);
2396 /* This clears the filter, showing all fonts and styles again. */
2398 gtk_font_selection_on_clear_filter (GtkWidget *w,
2399 GtkFontSelection *fontsel)
2401 gtk_font_selection_clear_filter(fontsel);
2405 /* This resets the user filter, showing all fonts and styles which pass the
2406 base filter again. Note that the font type is set to bitmaps and scalable
2407 fonts - scaled bitmaps are not shown. */
2409 gtk_font_selection_clear_filter (GtkFontSelection *fontsel)
2411 GtkFontFilter *filter;
2414 #ifdef FONTSEL_DEBUG
2415 g_message("In clear_filter\n");
2417 /* Clear the filter data. */
2418 filter = &fontsel->filters[GTK_FONT_FILTER_USER];
2419 filter->font_type = GTK_FONT_BITMAP | GTK_FONT_SCALABLE;
2420 for (prop = 0; prop < GTK_NUM_FONT_PROPERTIES; prop++)
2422 g_free(filter->property_filters[prop]);
2423 filter->property_filters[prop] = NULL;
2424 filter->property_nfilters[prop] = 0;
2427 /* Select all the '*'s on the filter page. */
2428 gtk_font_selection_reset_filter(NULL, fontsel);
2430 /* Update the main notebook page. */
2431 gtk_widget_set_sensitive(fontsel->filter_button, FALSE);
2432 gtk_label_set_text(GTK_LABEL(fontsel->font_label), _("Font:"));
2434 gtk_font_selection_show_available_fonts(fontsel);
2439 gtk_font_selection_set_filter (GtkFontSelection *fontsel,
2440 GtkFontFilterType filter_type,
2441 GtkFontType font_type,
2449 GtkFontFilter *filter;
2450 gchar **filter_strings [GTK_NUM_FONT_PROPERTIES];
2451 gchar *filter_string;
2452 gchar *property, *property_alt;
2453 gint prop, nfilters, i, j, num_found;
2454 gint base_font_type, user_font_type;
2455 gboolean filter_set;
2457 /* Put them into an array so we can use a simple loop. */
2458 filter_strings[FOUNDRY] = foundries;
2459 filter_strings[WEIGHT] = weights;
2460 filter_strings[SLANT] = slants;
2461 filter_strings[SET_WIDTH] = setwidths;
2462 filter_strings[SPACING] = spacings;
2463 filter_strings[CHARSET] = charsets;
2465 filter = &fontsel->filters[filter_type];
2466 filter->font_type = font_type;
2468 /* Free the old filter data, and insert the new. */
2469 for (prop = 0; prop < GTK_NUM_FONT_PROPERTIES; prop++)
2471 g_free(filter->property_filters[prop]);
2472 filter->property_filters[prop] = NULL;
2473 filter->property_nfilters[prop] = 0;
2475 if (filter_strings[prop])
2477 /* Count how many items in the new array. */
2479 while (filter_strings[prop][nfilters])
2482 filter->property_filters[prop] = g_new(guint16, nfilters);
2483 filter->property_nfilters[prop] = 0;
2485 /* Now convert the strings to property indices. */
2487 for (i = 0; i < nfilters; i++)
2489 filter_string = filter_strings[prop][i];
2490 for (j = 0; j < fontsel_info->nproperties[prop]; j++)
2492 property = _(fontsel_info->properties[prop][j]);
2493 property_alt = NULL;
2495 property_alt = gtk_font_selection_expand_slant_code(property);
2496 else if (prop == SPACING)
2497 property_alt = gtk_font_selection_expand_spacing_code(property);
2498 if (!strcmp (filter_string, property)
2499 || (property_alt && !strcmp (filter_string, property_alt)))
2501 filter->property_filters[prop][num_found] = j;
2507 filter->property_nfilters[prop] = num_found;
2511 /* Now set the clists on the filter page according to the new filter. */
2512 gtk_font_selection_update_filter_lists (fontsel);
2514 if (filter_type == GTK_FONT_FILTER_BASE)
2516 user_font_type = fontsel->filters[GTK_FONT_FILTER_USER].font_type;
2517 if (font_type & GTK_FONT_BITMAP)
2519 gtk_widget_set_sensitive (fontsel->type_bitmaps_button, TRUE);
2520 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fontsel->type_bitmaps_button), user_font_type & GTK_FONT_BITMAP);
2524 gtk_widget_set_sensitive (fontsel->type_bitmaps_button, FALSE);
2525 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fontsel->type_bitmaps_button), FALSE);
2528 if (font_type & GTK_FONT_SCALABLE)
2530 gtk_widget_set_sensitive (fontsel->type_scalable_button, TRUE);
2531 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fontsel->type_scalable_button), user_font_type & GTK_FONT_SCALABLE);
2535 gtk_widget_set_sensitive (fontsel->type_scalable_button, FALSE);
2536 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fontsel->type_scalable_button), FALSE);
2539 if (font_type & GTK_FONT_SCALABLE_BITMAP)
2541 gtk_widget_set_sensitive (fontsel->type_scaled_bitmaps_button, TRUE);
2542 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fontsel->type_scaled_bitmaps_button), user_font_type & GTK_FONT_SCALABLE_BITMAP);
2546 gtk_widget_set_sensitive (fontsel->type_scaled_bitmaps_button, FALSE);
2547 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fontsel->type_scaled_bitmaps_button), FALSE);
2552 base_font_type = fontsel->filters[GTK_FONT_FILTER_BASE].font_type;
2553 if (base_font_type & GTK_FONT_BITMAP)
2554 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fontsel->type_bitmaps_button), font_type & GTK_FONT_BITMAP);
2556 if (base_font_type & GTK_FONT_SCALABLE)
2557 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fontsel->type_scalable_button), font_type & GTK_FONT_SCALABLE);
2559 if (base_font_type & GTK_FONT_SCALABLE_BITMAP)
2560 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fontsel->type_scaled_bitmaps_button), font_type & GTK_FONT_SCALABLE_BITMAP);
2562 /* If the user filter is not the default, make the 'Reset Filter' button
2565 if (font_type != (GTK_FONT_BITMAP | GTK_FONT_SCALABLE))
2567 for (prop = 0; prop < GTK_NUM_FONT_PROPERTIES; prop++)
2569 if (filter->property_nfilters[prop] != 0)
2573 gtk_widget_set_sensitive (fontsel->filter_button, TRUE);
2576 gtk_font_selection_show_available_fonts (fontsel);
2580 /* This sets the colour of each property in the filter clists according to
2581 the base filter. i.e. Filtered properties are shown as insensitive. */
2583 gtk_font_selection_update_filter_lists (GtkFontSelection *fontsel)
2586 GdkColor *inactive_fg, *inactive_bg, *fg, *bg;
2587 gint prop, row, index;
2589 /* We have to make sure the clist is realized to use the colours. */
2590 for (prop = 0; prop < GTK_NUM_FONT_PROPERTIES; prop++)
2592 clist = fontsel->filter_clists[prop];
2593 gtk_widget_realize (clist);
2594 inactive_fg = &clist->style->fg[GTK_STATE_INSENSITIVE];
2595 inactive_bg = &clist->style->bg[GTK_STATE_INSENSITIVE];
2596 for (row = 1; row < GTK_CLIST(clist)->rows; row++)
2598 index = GPOINTER_TO_INT (gtk_clist_get_row_data(GTK_CLIST(clist),
2600 /* Set the colour according to the base filter. */
2601 if (gtk_font_selection_filter_state (fontsel, GTK_FONT_FILTER_BASE,
2602 prop, index) == NOT_FILTERED)
2612 gtk_clist_set_foreground(GTK_CLIST(clist), row, fg);
2613 gtk_clist_set_background(GTK_CLIST(clist), row, bg);
2615 /* Set the selection state according to the user filter. */
2616 if (gtk_font_selection_filter_state (fontsel, GTK_FONT_FILTER_USER,
2617 prop, index) == FILTERED
2619 gtk_clist_select_row (GTK_CLIST (clist), row, 0);
2621 gtk_clist_unselect_row (GTK_CLIST (clist), row, 0);
2627 /* Returns whether a property value is in the filter or not, or if the
2628 property has no filter set. */
2629 static GtkFontPropertyFilterState
2630 gtk_font_selection_filter_state (GtkFontSelection *fontsel,
2631 GtkFontFilterType filter_type,
2635 GtkFontFilter *filter;
2638 filter = &fontsel->filters[filter_type];
2639 if (filter->property_nfilters[property] == 0)
2642 for (i = 0; i < filter->property_nfilters[property]; i++)
2644 if (filter->property_filters[property][i] == index)
2647 return NOT_FILTERED;
2651 #ifdef GDK_WINDOWING_WIN32
2653 static gint num_fonts;
2654 static gint font_names_size;
2655 static gchar **xfontnames;
2659 logfont_to_xlfd (const LOGFONT *lfp,
2664 const gchar *weight;
2665 const gchar *registry, *encoding;
2667 static int logpixelsy = 0;
2668 gchar facename[LF_FACESIZE*3];
2672 if (logpixelsy == 0)
2674 HDC hdc = GetDC (NULL);
2675 logpixelsy = GetDeviceCaps (hdc, LOGPIXELSY);
2676 ReleaseDC (NULL, hdc);
2679 /* Don't use _() here, only N_(), the actual translation is done elsewhere */
2680 if (lfp->lfWeight >= FW_HEAVY)
2681 weight = N_("heavy");
2682 else if (lfp->lfWeight >= FW_EXTRABOLD)
2683 weight = N_("extrabold");
2684 else if (lfp->lfWeight >= FW_BOLD)
2685 weight = N_("bold");
2687 else if (lfp->lfWeight >= FW_DEMIBOLD)
2688 weight = N_("demibold");
2690 else if (lfp->lfWeight >= FW_MEDIUM)
2691 weight = N_("medium");
2692 else if (lfp->lfWeight >= FW_NORMAL)
2693 weight = N_("normal");
2694 else if (lfp->lfWeight >= FW_LIGHT)
2695 weight = N_("light");
2696 else if (lfp->lfWeight >= FW_EXTRALIGHT)
2697 weight = N_("extralight");
2698 else if (lfp->lfWeight >= FW_THIN)
2699 weight = N_("thin");
2701 weight = N_("regular");
2703 if (lfp->lfCharSet == ANSI_CHARSET)
2705 registry = "iso8859";
2710 registry = "windows";
2711 if (lfp->lfCharSet == DEFAULT_CHARSET)
2712 encoding = "default";
2713 else if (lfp->lfCharSet == SYMBOL_CHARSET)
2714 encoding = "symbol";
2715 else if (lfp->lfCharSet == SHIFTJIS_CHARSET)
2716 encoding = "shiftjis";
2717 else if (lfp->lfCharSet == GB2312_CHARSET)
2718 encoding = "gb2312";
2719 else if (lfp->lfCharSet == HANGEUL_CHARSET)
2720 encoding = "hangeul";
2721 else if (lfp->lfCharSet == CHINESEBIG5_CHARSET)
2722 encoding = "chinesebig5";
2723 else if (lfp->lfCharSet == OEM_CHARSET)
2725 #ifdef JOHAB_CHARSET
2726 else if (lfp->lfCharSet == JOHAB_CHARSET)
2729 else if (lfp->lfCharSet == HEBREW_CHARSET)
2730 encoding = "hebrew";
2731 else if (lfp->lfCharSet == ARABIC_CHARSET)
2732 encoding = "arabic";
2733 else if (lfp->lfCharSet == GREEK_CHARSET)
2735 else if (lfp->lfCharSet == TURKISH_CHARSET)
2736 encoding = "turkish";
2737 else if (lfp->lfCharSet == THAI_CHARSET)
2739 else if (lfp->lfCharSet == EASTEUROPE_CHARSET)
2740 encoding = "easteurope";
2741 else if (lfp->lfCharSet == RUSSIAN_CHARSET)
2742 encoding = "russian";
2743 else if (lfp->lfCharSet == MAC_CHARSET)
2745 else if (lfp->lfCharSet == BALTIC_CHARSET)
2746 encoding = "baltic";
2748 encoding = "unknown";
2751 point_size = (int) (((double) size/logpixelsy) * 720.);
2756 /* Replace illegal characters with hex escapes. */
2758 q = lfp->lfFaceName;
2761 if (*q == '-' || *q == '*' || *q == '?' || *q == '%')
2762 p += sprintf (p, "%%%.02x", *q);
2769 return g_strdup_printf
2770 ("-%s-%s-%s-%s-%s-%s-%d-%d-%d-%d-%s-%d-%s-%s",
2775 ((lfp->lfPitchAndFamily & 0xF0) == FF_ROMAN
2776 || (lfp->lfPitchAndFamily & 0xF0) == FF_SCRIPT ?
2784 ((lfp->lfPitchAndFamily & 0x03) == FIXED_PITCH ? "m" : "p"),
2786 registry, encoding);
2790 InnerEnumFontFamExProc (const LOGFONT *lfp,
2791 const TEXTMETRIC *metrics,
2797 if (fontType == TRUETYPE_FONTTYPE)
2803 size = lfp->lfHeight;
2807 if (num_fonts == font_names_size)
2809 font_names_size *= 2;
2810 xfontnames = g_realloc (xfontnames, font_names_size * sizeof (gchar *));
2812 xfontnames[num_fonts-1] =
2813 logfont_to_xlfd (lfp, size, 0, 0);
2818 EnumFontFamExProc (const LOGFONT *lfp,
2819 const TEXTMETRIC *metrics,
2823 if (fontType == TRUETYPE_FONTTYPE)
2826 lf.lfPitchAndFamily = 0;
2827 EnumFontFamiliesEx (hdc, &lf, InnerEnumFontFamExProc, 0, 0);
2830 InnerEnumFontFamExProc (lfp, metrics, fontType, lParam);
2836 /*****************************************************************************
2837 * These functions all deal with creating the main class arrays containing
2838 * the data about all available fonts.
2839 *****************************************************************************/
2841 gtk_font_selection_get_fonts (void)
2843 #ifdef GDK_WINDOWING_X11
2846 #elif defined (GDK_WINDOWING_WIN32)
2850 gchar **xfontnames = NULL;
2855 gint i, prop, style, size;
2856 gint npixel_sizes = 0, npoint_sizes = 0;
2858 FontStyle *current_style, *prev_style, *tmp_style;
2859 gboolean matched_style, found_size;
2860 gint pixels, points, res_x, res_y;
2861 gchar field_buffer[XLFD_MAX_FIELD_LEN];
2864 guint16 *pixel_sizes, *point_sizes, *tmp_sizes;
2866 fontsel_info = g_new (GtkFontSelInfo, 1);
2868 #ifdef GDK_WINDOWING_X11
2869 /* Get a maximum of MAX_FONTS fontnames from the X server.
2870 Use "-*" as the pattern rather than "-*-*-*-*-*-*-*-*-*-*-*-*-*-*" since
2871 the latter may result in fonts being returned which don't actually exist.
2872 xlsfonts also uses "*" so I think it's OK. "-*" gets rid of aliases. */
2873 xfontnames = XListFonts (GDK_DISPLAY(), "-*", MAX_FONTS, &num_fonts);
2874 /* Output a warning if we actually get MAX_FONTS fonts. */
2875 if (num_fonts == MAX_FONTS)
2876 g_warning(_("MAX_FONTS exceeded. Some fonts may be missing."));
2878 #elif defined (GDK_WINDOWING_WIN32)
2881 font_names_size = 100;
2882 xfontnames = g_new (gchar *, font_names_size);
2883 logfont.lfCharSet = DEFAULT_CHARSET;
2884 logfont.lfFaceName[0] = '\0';
2885 logfont.lfPitchAndFamily = 0;
2886 EnumFontFamiliesEx (hdc, &logfont, EnumFontFamExProc, 0, 0);
2887 ReleaseDC (NULL, hdc);
2890 /* The maximum size of all these tables is the number of font names
2891 returned. We realloc them later when we know exactly how many
2892 unique entries there are. */
2893 fontsel_info->font_info = g_new (FontInfo, num_fonts);
2894 fontsel_info->font_styles = g_new (FontStyle, num_fonts);
2895 fontsel_info->pixel_sizes = g_new (guint16, num_fonts);
2896 fontsel_info->point_sizes = g_new (guint16, num_fonts);
2898 fontnames = g_new (GSList*, num_fonts);
2900 /* Create the initial arrays for the property value strings, though they
2901 may be realloc'ed later. Put the wildcard '*' in the first elements. */
2902 for (prop = 0; prop < GTK_NUM_FONT_PROPERTIES; prop++)
2904 fontsel_info->properties[prop] = g_new(gchar*, PROPERTY_ARRAY_INCREMENT);
2905 fontsel_info->space_allocated[prop] = PROPERTY_ARRAY_INCREMENT;
2906 fontsel_info->nproperties[prop] = 1;
2907 fontsel_info->properties[prop][0] = "*";
2911 /* Insert the font families into the main table, sorted by family and
2912 foundry (fonts with different foundries are placed in seaparate FontInfos.
2913 All fontnames in each family + foundry are placed into the fontnames
2915 fontsel_info->nfonts = 0;
2916 for (i = 0; i < num_fonts; i++)
2918 #ifdef FONTSEL_DEBUG
2919 g_message("%s\n", xfontnames[i]);
2921 if (gtk_font_selection_is_xlfd_font_name (xfontnames[i]))
2922 gtk_font_selection_insert_font (fontnames, &fontsel_info->nfonts, xfontnames[i]);
2925 #ifdef FONTSEL_DEBUG
2926 g_warning("Skipping invalid font: %s", xfontnames[i]);
2932 /* Since many font names will be in the same FontInfo not all of the
2933 allocated FontInfo table will be used, so we will now reallocate it
2934 with the real size. */
2935 fontsel_info->font_info = g_realloc(fontsel_info->font_info,
2936 sizeof(FontInfo) * fontsel_info->nfonts);
2939 /* Now we work out which choices of weight/slant etc. are valid for each
2941 fontsel_info->nstyles = 0;
2942 current_style = fontsel_info->font_styles;
2943 for (i = 0; i < fontsel_info->nfonts; i++)
2945 font = &fontsel_info->font_info[i];
2947 /* Use the next free position in the styles array. */
2948 font->style_index = fontsel_info->nstyles;
2950 /* Now step through each of the fontnames with this family, and create
2951 a style for each fontname. Each style contains the index into the
2952 weights/slants etc. arrays, and a number of pixel/point sizes. */
2954 temp_list = fontnames[i];
2957 fontname = temp_list->data;
2958 temp_list = temp_list->next;
2960 for (prop = 0; prop < GTK_NUM_STYLE_PROPERTIES; prop++)
2962 current_style->properties[prop]
2963 = gtk_font_selection_insert_field (fontname, prop);
2965 current_style->pixel_sizes_index = npixel_sizes;
2966 current_style->npixel_sizes = 0;
2967 current_style->point_sizes_index = npoint_sizes;
2968 current_style->npoint_sizes = 0;
2969 current_style->flags = 0;
2972 field = gtk_font_selection_get_xlfd_field (fontname, XLFD_PIXELS,
2974 pixels = atoi(field);
2976 field = gtk_font_selection_get_xlfd_field (fontname, XLFD_POINTS,
2978 points = atoi(field);
2980 field = gtk_font_selection_get_xlfd_field (fontname,
2983 res_x = atoi(field);
2985 field = gtk_font_selection_get_xlfd_field (fontname,
2988 res_y = atoi(field);
2990 if (pixels == 0 && points == 0)
2992 if (res_x == 0 && res_y == 0)
2993 flags = GTK_FONT_SCALABLE;
2995 flags = GTK_FONT_SCALABLE_BITMAP;
2998 flags = GTK_FONT_BITMAP;
3000 /* Now we check to make sure that the style is unique. If it isn't
3002 prev_style = fontsel_info->font_styles + font->style_index;
3003 matched_style = FALSE;
3004 while (prev_style < current_style)
3006 matched_style = TRUE;
3007 for (prop = 0; prop < GTK_NUM_STYLE_PROPERTIES; prop++)
3009 if (prev_style->properties[prop]
3010 != current_style->properties[prop])
3012 matched_style = FALSE;
3021 /* If we matched an existing style, we need to add the pixels &
3022 point sizes to the style. If not, we insert the pixel & point
3023 sizes into our new style. Note that we don't add sizes for
3027 prev_style->flags |= flags;
3028 if (flags == GTK_FONT_BITMAP)
3030 pixel_sizes = fontsel_info->pixel_sizes
3031 + prev_style->pixel_sizes_index;
3033 for (size = 0; size < prev_style->npixel_sizes; size++)
3035 if (pixels == *pixel_sizes)
3040 else if (pixels < *pixel_sizes)
3044 /* We need to move all the following pixel sizes up, and also
3045 update the indexes of any following styles. */
3048 for (tmp_sizes = fontsel_info->pixel_sizes + npixel_sizes;
3049 tmp_sizes > pixel_sizes; tmp_sizes--)
3050 *tmp_sizes = *(tmp_sizes - 1);
3052 *pixel_sizes = pixels;
3054 prev_style->npixel_sizes++;
3056 tmp_style = prev_style + 1;
3057 while (tmp_style < current_style)
3059 tmp_style->pixel_sizes_index++;
3064 point_sizes = fontsel_info->point_sizes
3065 + prev_style->point_sizes_index;
3067 for (size = 0; size < prev_style->npoint_sizes; size++)
3069 if (points == *point_sizes)
3074 else if (points < *point_sizes)
3078 /* We need to move all the following point sizes up, and also
3079 update the indexes of any following styles. */
3082 for (tmp_sizes = fontsel_info->point_sizes + npoint_sizes;
3083 tmp_sizes > point_sizes; tmp_sizes--)
3084 *tmp_sizes = *(tmp_sizes - 1);
3086 *point_sizes = points;
3088 prev_style->npoint_sizes++;
3090 tmp_style = prev_style + 1;
3091 while (tmp_style < current_style)
3093 tmp_style->point_sizes_index++;
3101 current_style->flags = flags;
3102 if (flags == GTK_FONT_BITMAP)
3104 fontsel_info->pixel_sizes[npixel_sizes++] = pixels;
3105 current_style->npixel_sizes = 1;
3106 fontsel_info->point_sizes[npoint_sizes++] = points;
3107 current_style->npoint_sizes = 1;
3110 fontsel_info->nstyles++;
3114 g_slist_free(fontnames[i]);
3116 /* Set nstyles to the real value, minus duplicated fontnames.
3117 Note that we aren't using all the allocated memory if fontnames are
3119 font->nstyles = style;
3122 /* Since some repeated styles may be skipped we won't have used all the
3123 allocated space, so we will now reallocate it with the real size. */
3124 fontsel_info->font_styles = g_realloc(fontsel_info->font_styles,
3125 sizeof(FontStyle) * fontsel_info->nstyles);
3126 fontsel_info->pixel_sizes = g_realloc(fontsel_info->pixel_sizes,
3127 sizeof(guint16) * npixel_sizes);
3128 fontsel_info->point_sizes = g_realloc(fontsel_info->point_sizes,
3129 sizeof(guint16) * npoint_sizes);
3132 #ifdef GDK_WINDOWING_X11
3133 XFreeFontNames (xfontnames);
3134 #elif defined (GDK_WINDOWING_WIN32)
3135 for (i = 0; i < num_fonts; i++)
3136 g_free (xfontnames[i]);
3137 g_free (xfontnames);
3140 /* Debugging Output */
3141 /* This outputs all FontInfos. */
3142 #ifdef FONTSEL_DEBUG
3143 g_message("\n\n Font Family Weight Slant Set Width Spacing Charset\n\n");
3144 for (i = 0; i < fontsel_info->nfonts; i++)
3146 FontInfo *font = &fontsel_info->font_info[i];
3147 FontStyle *styles = fontsel_info->font_styles + font->style_index;
3148 for (style = 0; style < font->nstyles; style++)
3150 g_message("%5i %-16.16s ", i, font->family);
3151 for (prop = 0; prop < GTK_NUM_STYLE_PROPERTIES; prop++)
3152 g_message("%-9.9s ",
3153 fontsel_info->properties[prop][styles->properties[prop]]);
3156 if (styles->flags & GTK_FONT_BITMAP)
3157 g_message("Bitmapped font ");
3158 if (styles->flags & GTK_FONT_SCALABLE)
3159 g_message("Scalable font ");
3160 if (styles->flags & GTK_FONT_SCALABLE_BITMAP)
3161 g_message("Scalable-Bitmapped font ");
3164 if (styles->npixel_sizes)
3166 g_message(" Pixel sizes: ");
3167 tmp_sizes = fontsel_info->pixel_sizes + styles->pixel_sizes_index;
3168 for (size = 0; size < styles->npixel_sizes; size++)
3169 g_message("%i ", *tmp_sizes++);
3173 if (styles->npoint_sizes)
3175 g_message(" Point sizes: ");
3176 tmp_sizes = fontsel_info->point_sizes + styles->point_sizes_index;
3177 for (size = 0; size < styles->npoint_sizes; size++)
3178 g_message("%i ", *tmp_sizes++);
3186 /* This outputs all available properties. */
3187 for (prop = 0; prop < GTK_NUM_FONT_PROPERTIES; prop++)
3189 g_message("Property: %s\n", xlfd_field_names[xlfd_index[prop]]);
3190 for (i = 0; i < fontsel_info->nproperties[prop]; i++)
3191 g_message(" %s\n", fontsel_info->properties[prop][i]);
3196 /* This inserts the given fontname into the FontInfo table.
3197 If a FontInfo already exists with the same family and foundry, then the
3198 fontname is added to the FontInfos list of fontnames, else a new FontInfo
3199 is created and inserted in alphabetical order in the table. */
3201 gtk_font_selection_insert_font (GSList *fontnames[],
3207 GSList *temp_fontname;
3209 gboolean family_exists = FALSE;
3213 gchar family_buffer[XLFD_MAX_FIELD_LEN];
3215 table = fontsel_info->font_info;
3217 /* insert a fontname into a table */
3218 family = gtk_font_selection_get_xlfd_field (fontname, XLFD_FAMILY,
3223 foundry = gtk_font_selection_insert_field (fontname, FOUNDRY);
3228 /* Do a binary search to determine if we have already encountered
3229 * a font with this family & foundry. */
3231 while (lower < upper)
3233 middle = (lower + upper) >> 1;
3235 cmp = strcmp (family, table[middle].family);
3236 /* If the family matches we sort by the foundry. */
3239 family_exists = TRUE;
3240 family = table[middle].family;
3241 cmp = strcmp(fontsel_info->properties[FOUNDRY][foundry],
3242 fontsel_info->properties[FOUNDRY][table[middle].foundry]);
3247 fontnames[middle] = g_slist_prepend (fontnames[middle],
3258 /* Add another entry to the table for this new font family */
3259 temp_info.family = family_exists ? family : g_strdup(family);
3260 temp_info.foundry = foundry;
3261 temp_fontname = g_slist_prepend (NULL, fontname);
3265 /* Quickly insert the entry into the table in sorted order
3266 * using a modification of insertion sort and the knowledge
3267 * that the entries proper position in the table was determined
3268 * above in the binary search and is contained in the "lower"
3272 upper = *ntable - 1;
3273 while (lower != upper)
3275 table[upper] = table[upper-1];
3276 fontnames[upper] = fontnames[upper-1];
3280 table[lower] = temp_info;
3281 fontnames[lower] = temp_fontname;
3285 /* This checks that the specified field of the given fontname is in the
3286 appropriate properties array. If not it is added. Thus eventually we get
3287 arrays of all possible weights/slants etc. It returns the array index. */
3289 gtk_font_selection_insert_field (gchar *fontname,
3292 gchar field_buffer[XLFD_MAX_FIELD_LEN];
3296 field = gtk_font_selection_get_xlfd_field (fontname, xlfd_index[prop],
3301 /* If the field is already in the array just return its index. */
3302 for (index = 0; index < fontsel_info->nproperties[prop]; index++)
3303 if (!strcmp(field, fontsel_info->properties[prop][index]))
3306 /* Make sure we have enough space to add the field. */
3307 if (fontsel_info->nproperties[prop] == fontsel_info->space_allocated[prop])
3309 fontsel_info->space_allocated[prop] += PROPERTY_ARRAY_INCREMENT;
3310 fontsel_info->properties[prop] = g_realloc(fontsel_info->properties[prop],
3312 * fontsel_info->space_allocated[prop]);
3315 /* Add the new field. */
3316 index = fontsel_info->nproperties[prop];
3317 fontsel_info->properties[prop][index] = g_strdup(field);
3318 fontsel_info->nproperties[prop]++;
3323 /*****************************************************************************
3324 * These functions are the main public interface for getting/setting the font.
3325 *****************************************************************************/
3328 gtk_font_selection_get_font (GtkFontSelection *fontsel)
3330 g_return_val_if_fail (fontsel != NULL, NULL);
3331 return fontsel->font;
3336 gtk_font_selection_get_font_name (GtkFontSelection *fontsel)
3339 gchar *family_str, *foundry_str;
3340 gchar *property_str[GTK_NUM_STYLE_PROPERTIES];
3343 g_return_val_if_fail (fontsel != NULL, NULL);
3344 g_return_val_if_fail (GTK_IS_FONT_SELECTION (fontsel), NULL);
3346 /* If no family has been selected return NULL. */
3347 if (fontsel->font_index == -1)
3350 font = &fontsel_info->font_info[fontsel->font_index];
3351 family_str = font->family;
3352 foundry_str = fontsel_info->properties[FOUNDRY][font->foundry];
3354 for (prop = 0; prop < GTK_NUM_STYLE_PROPERTIES; prop++)
3357 = fontsel_info->properties[prop][fontsel->property_values[prop]];
3358 if (strcmp (property_str[prop], "(nil)") == 0)
3359 property_str[prop] = "";
3362 return gtk_font_selection_create_xlfd (fontsel->size,
3366 property_str[WEIGHT],
3367 property_str[SLANT],
3368 property_str[SET_WIDTH],
3369 property_str[SPACING],
3370 property_str[CHARSET]);
3374 /* This sets the current font, selecting the appropriate clist rows.
3375 First we check the fontname is valid and try to find the font family
3376 - i.e. the name in the main list. If we can't find that, then just return.
3377 Next we try to set each of the properties according to the fontname.
3378 Finally we select the font family & style in the clists. */
3380 gtk_font_selection_set_font_name (GtkFontSelection *fontsel,
3381 const gchar *fontname)
3383 gchar *family, *field;
3384 gint index, prop, size;
3385 guint16 foundry, value;
3386 gchar family_buffer[XLFD_MAX_FIELD_LEN];
3387 gchar field_buffer[XLFD_MAX_FIELD_LEN];
3390 g_return_val_if_fail (fontsel != NULL, FALSE);
3391 g_return_val_if_fail (GTK_IS_FONT_SELECTION (fontsel), FALSE);
3392 g_return_val_if_fail (fontname != NULL, FALSE);
3394 /* Check it is a valid fontname. */
3395 if (!gtk_font_selection_is_xlfd_font_name(fontname))
3398 family = gtk_font_selection_get_xlfd_field (fontname, XLFD_FAMILY,
3403 field = gtk_font_selection_get_xlfd_field (fontname, XLFD_FOUNDRY,
3405 foundry = gtk_font_selection_field_to_index (fontsel_info->properties[FOUNDRY],
3406 fontsel_info->nproperties[FOUNDRY],
3409 index = gtk_font_selection_find_font(fontsel, family, foundry);
3413 /* Convert the property fields into indices and set them. */
3414 for (prop = 0; prop < GTK_NUM_STYLE_PROPERTIES; prop++)
3416 field = gtk_font_selection_get_xlfd_field (fontname, xlfd_index[prop],
3418 value = gtk_font_selection_field_to_index (fontsel_info->properties[prop],
3419 fontsel_info->nproperties[prop],
3421 fontsel->property_values[prop] = value;
3424 field = gtk_font_selection_get_xlfd_field (fontname, XLFD_POINTS,
3431 fontsel->size = fontsel->selected_size = size;
3432 fontsel->metric = GTK_FONT_METRIC_POINTS;
3433 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(fontsel->points_button),
3436 sprintf (buffer, "%i", size / 10);
3438 sprintf (buffer, "%i.%i", size / 10, size % 10);
3442 field = gtk_font_selection_get_xlfd_field (fontname, XLFD_PIXELS,
3447 fontsel->size = fontsel->selected_size = size;
3448 fontsel->metric = GTK_FONT_METRIC_PIXELS;
3449 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(fontsel->pixels_button),
3451 sprintf (buffer, "%i", size);
3453 gtk_entry_set_text (GTK_ENTRY (fontsel->size_entry), buffer);
3455 /* Clear any current filter. */
3456 gtk_font_selection_clear_filter(fontsel);
3458 /* Now find the best style match. */
3459 fontsel->font_index = index;
3460 gtk_clist_select_row(GTK_CLIST(fontsel->font_clist), index, 0);
3461 if (GTK_WIDGET_MAPPED (fontsel->font_clist))
3462 gtk_clist_moveto(GTK_CLIST(fontsel->font_clist), index, -1, 0.5, 0);
3464 gtk_font_selection_show_available_styles (fontsel);
3465 /* This will load the font. */
3466 gtk_font_selection_select_best_style (fontsel, FALSE);
3472 /* Returns the index of the given family, or -1 if not found */
3474 gtk_font_selection_find_font (GtkFontSelection *fontsel,
3478 FontInfo *font_info;
3479 gint lower, upper, middle = -1, cmp, nfonts;
3480 gint found_family = -1;
3482 font_info = fontsel_info->font_info;
3483 nfonts = fontsel_info->nfonts;
3487 /* Do a binary search to find the font family. */
3490 while (lower < upper)
3492 middle = (lower + upper) >> 1;
3494 cmp = strcmp (family, font_info[middle].family);
3497 found_family = middle;
3498 cmp = strcmp(fontsel_info->properties[FOUNDRY][foundry],
3499 fontsel_info->properties[FOUNDRY][font_info[middle].foundry]);
3510 /* We couldn't find the family and foundry, but we may have just found the
3511 family, so we return that. */
3512 return found_family;
3516 /* This returns the text in the preview entry. You should copy the returned
3517 text if you need it. */
3519 gtk_font_selection_get_preview_text (GtkFontSelection *fontsel)
3521 return gtk_entry_get_text(GTK_ENTRY(fontsel->preview_entry));
3525 /* This sets the text in the preview entry. */
3527 gtk_font_selection_set_preview_text (GtkFontSelection *fontsel,
3530 gtk_entry_set_text(GTK_ENTRY(fontsel->preview_entry), text);
3534 /*****************************************************************************
3535 * These functions all deal with X Logical Font Description (XLFD) fontnames.
3536 * See the freely available documentation about this.
3537 *****************************************************************************/
3540 * Returns TRUE if the fontname is a valid XLFD.
3541 * (It just checks if the number of dashes is 14, and that each
3542 * field < XLFD_MAX_FIELD_LEN characters long - that's not in the XLFD but it
3543 * makes it easier for me).
3546 gtk_font_selection_is_xlfd_font_name (const gchar *fontname)
3553 if (*fontname++ == '-')
3555 if (field_len > XLFD_MAX_FIELD_LEN) return FALSE;
3563 return (i == 14) ? TRUE : FALSE;
3567 * This fills the buffer with the specified field from the X Logical Font
3568 * Description name, and returns it. If fontname is NULL or the field is
3569 * longer than XFLD_MAX_FIELD_LEN it returns NULL.
3570 * Note: For the charset field, we also return the encoding, e.g. 'iso8859-1'.
3573 gtk_font_selection_get_xlfd_field (const gchar *fontname,
3574 FontField field_num,
3577 const gchar *t1, *t2;
3578 gint countdown, len, num_dashes;
3579 #ifdef GDK_WINDOWING_WIN32
3586 /* we assume this is a valid fontname...that is, it has 14 fields */
3588 countdown = field_num;
3590 while (*t1 && (countdown >= 0))
3594 num_dashes = (field_num == XLFD_CHARSET) ? 2 : 1;
3595 for (t2 = t1; *t2; t2++)
3597 if (*t2 == '-' && --num_dashes == 0)
3603 /* Check we don't overflow the buffer */
3604 len = (long) t2 - (long) t1;
3605 if (len > XLFD_MAX_FIELD_LEN - 1)
3607 strncpy (buffer, t1, len);
3609 #ifdef GDK_WINDOWING_X11
3610 /* Convert to lower case. */
3612 #elif defined (GDK_WINDOWING_WIN32)
3613 /* Check for hex escapes in font family */
3614 if (field_num == XLFD_FAMILY)
3619 if (*p == '%' && isxdigit (p[1]) && isxdigit (p[2]))
3622 sscanf (p+1, "%2x", &c);
3632 strcpy(buffer, "(nil)");
3638 * This returns a X Logical Font Description font name, given all the pieces.
3639 * Note: this retval must be freed by the caller.
3642 gtk_font_selection_create_xlfd (gint size,
3643 GtkFontMetricType metric,
3653 gchar *pixel_size = "*", *point_size = "*", *fontname;
3654 gchar *fam = family;
3655 #ifdef GDK_WINDOWING_WIN32
3662 sprintf (buffer, "%d", (int) size);
3663 if (metric == GTK_FONT_METRIC_PIXELS)
3664 pixel_size = buffer;
3666 point_size = buffer;
3668 #ifdef GDK_WINDOWING_WIN32
3669 fam = g_malloc (strlen (family) * 3 + 1);
3674 if (*q == '-' || *q == '*' || *q == '?' || *q == '%')
3675 p += sprintf (p, "%%%.02x", *q);
3682 fontname = g_strdup_printf ("-%s-%s-%s-%s-%s-*-%s-%s-*-*-%s-*-%s",
3683 foundry, fam, weight, slant,
3684 set_width, pixel_size, point_size,
3686 #ifdef GDK_WINDOWING_WIN32
3694 /*****************************************************************************
3695 * GtkFontSelectionDialog
3696 *****************************************************************************/
3699 gtk_font_selection_dialog_get_type (void)
3701 static guint font_selection_dialog_type = 0;
3703 if (!font_selection_dialog_type)
3705 GtkTypeInfo fontsel_diag_info =
3707 "GtkFontSelectionDialog",
3708 sizeof (GtkFontSelectionDialog),
3709 sizeof (GtkFontSelectionDialogClass),
3710 (GtkClassInitFunc) gtk_font_selection_dialog_class_init,
3711 (GtkObjectInitFunc) gtk_font_selection_dialog_init,
3712 /* reserved_1 */ NULL,
3713 /* reserved_2 */ NULL,
3714 (GtkClassInitFunc) NULL,
3717 font_selection_dialog_type = gtk_type_unique (GTK_TYPE_WINDOW, &fontsel_diag_info);
3720 return font_selection_dialog_type;
3724 gtk_font_selection_dialog_class_init (GtkFontSelectionDialogClass *klass)
3726 GtkObjectClass *object_class;
3728 object_class = (GtkObjectClass*) klass;
3730 font_selection_dialog_parent_class = gtk_type_class (GTK_TYPE_WINDOW);
3734 gtk_font_selection_dialog_init (GtkFontSelectionDialog *fontseldiag)
3736 fontseldiag->dialog_width = -1;
3737 fontseldiag->auto_resize = TRUE;
3739 gtk_widget_set_events(GTK_WIDGET(fontseldiag), GDK_STRUCTURE_MASK);
3740 gtk_signal_connect (GTK_OBJECT (fontseldiag), "configure_event",
3741 (GtkSignalFunc) gtk_font_selection_dialog_on_configure,
3744 gtk_container_set_border_width (GTK_CONTAINER (fontseldiag), 4);
3745 gtk_window_set_policy(GTK_WINDOW(fontseldiag), FALSE, TRUE, TRUE);
3747 fontseldiag->main_vbox = gtk_vbox_new (FALSE, 4);
3748 gtk_widget_show (fontseldiag->main_vbox);
3749 gtk_container_add (GTK_CONTAINER (fontseldiag), fontseldiag->main_vbox);
3751 fontseldiag->fontsel = gtk_font_selection_new();
3752 gtk_widget_show (fontseldiag->fontsel);
3753 gtk_box_pack_start (GTK_BOX (fontseldiag->main_vbox),
3754 fontseldiag->fontsel, TRUE, TRUE, 0);
3756 /* Create the action area */
3757 fontseldiag->action_area = gtk_hbutton_box_new ();
3758 gtk_button_box_set_layout(GTK_BUTTON_BOX(fontseldiag->action_area),
3760 gtk_button_box_set_spacing(GTK_BUTTON_BOX(fontseldiag->action_area), 5);
3761 gtk_box_pack_start (GTK_BOX (fontseldiag->main_vbox),
3762 fontseldiag->action_area, FALSE, FALSE, 0);
3763 gtk_widget_show (fontseldiag->action_area);
3765 fontseldiag->ok_button = gtk_button_new_with_label(_("OK"));
3766 GTK_WIDGET_SET_FLAGS (fontseldiag->ok_button, GTK_CAN_DEFAULT);
3767 gtk_widget_show(fontseldiag->ok_button);
3768 gtk_box_pack_start (GTK_BOX (fontseldiag->action_area),
3769 fontseldiag->ok_button, TRUE, TRUE, 0);
3770 gtk_widget_grab_default (fontseldiag->ok_button);
3772 fontseldiag->apply_button = gtk_button_new_with_label(_("Apply"));
3773 GTK_WIDGET_SET_FLAGS (fontseldiag->apply_button, GTK_CAN_DEFAULT);
3774 /*gtk_widget_show(fontseldiag->apply_button);*/
3775 gtk_box_pack_start (GTK_BOX(fontseldiag->action_area),
3776 fontseldiag->apply_button, TRUE, TRUE, 0);
3778 fontseldiag->cancel_button = gtk_button_new_with_label(_("Cancel"));
3779 GTK_WIDGET_SET_FLAGS (fontseldiag->cancel_button, GTK_CAN_DEFAULT);
3780 gtk_widget_show(fontseldiag->cancel_button);
3781 gtk_box_pack_start (GTK_BOX(fontseldiag->action_area),
3782 fontseldiag->cancel_button, TRUE, TRUE, 0);
3788 gtk_font_selection_dialog_new (const gchar *title)
3790 GtkFontSelectionDialog *fontseldiag;
3792 fontseldiag = gtk_type_new (GTK_TYPE_FONT_SELECTION_DIALOG);
3793 gtk_window_set_title (GTK_WINDOW (fontseldiag),
3794 title ? title : _("Font Selection"));
3796 return GTK_WIDGET (fontseldiag);
3800 gtk_font_selection_dialog_get_font_name (GtkFontSelectionDialog *fsd)
3802 return gtk_font_selection_get_font_name(GTK_FONT_SELECTION(fsd->fontsel));
3806 gtk_font_selection_dialog_get_font (GtkFontSelectionDialog *fsd)
3808 return gtk_font_selection_get_font(GTK_FONT_SELECTION(fsd->fontsel));
3812 gtk_font_selection_dialog_set_font_name (GtkFontSelectionDialog *fsd,
3813 const gchar *fontname)
3815 return gtk_font_selection_set_font_name(GTK_FONT_SELECTION(fsd->fontsel),
3820 gtk_font_selection_dialog_set_filter (GtkFontSelectionDialog *fsd,
3821 GtkFontFilterType filter_type,
3822 GtkFontType font_type,
3830 gtk_font_selection_set_filter (GTK_FONT_SELECTION (fsd->fontsel),
3831 filter_type, font_type,
3832 foundries, weights, slants, setwidths,
3833 spacings, charsets);
3837 gtk_font_selection_dialog_get_preview_text (GtkFontSelectionDialog *fsd)
3839 return gtk_font_selection_get_preview_text(GTK_FONT_SELECTION(fsd->fontsel));
3843 gtk_font_selection_dialog_set_preview_text (GtkFontSelectionDialog *fsd,
3846 gtk_font_selection_set_preview_text(GTK_FONT_SELECTION(fsd->fontsel), text);
3850 /* This turns auto-shrink off if the user resizes the width of the dialog.
3851 It also turns it back on again if the user resizes it back to its normal
3854 gtk_font_selection_dialog_on_configure (GtkWidget *widget,
3855 GdkEventConfigure *event,
3856 GtkFontSelectionDialog *fsd)
3858 /* This sets the initial width. */
3859 if (fsd->dialog_width == -1)
3860 fsd->dialog_width = event->width;
3861 else if (fsd->auto_resize && fsd->dialog_width != event->width)
3863 fsd->auto_resize = FALSE;
3864 gtk_window_set_policy(GTK_WINDOW(fsd), FALSE, TRUE, FALSE);
3866 else if (!fsd->auto_resize && fsd->dialog_width == event->width)
3868 fsd->auto_resize = TRUE;
3869 gtk_window_set_policy(GTK_WINDOW(fsd), FALSE, TRUE, TRUE);