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)
1457 if (fontsel->metric == GTK_FONT_METRIC_POINTS)
1459 if (*bitmapped_sizes % 10 != 0)
1461 bitmap_size = *bitmapped_sizes / 10;
1462 bitmap_size_float = *bitmapped_sizes / 10;
1466 bitmap_size = *bitmapped_sizes;
1467 bitmap_size_float = *bitmapped_sizes;
1471 if (can_match && nstandard_sizes && nbitmapped_sizes
1472 && *standard_sizes == bitmap_size)
1474 sprintf(buffer, "%i *", *standard_sizes);
1480 else if (nstandard_sizes
1481 && (!nbitmapped_sizes
1482 || (gfloat)*standard_sizes < bitmap_size_float))
1484 sprintf(buffer, "%i", *standard_sizes);
1490 if (fontsel->metric == GTK_FONT_METRIC_POINTS)
1492 if (*bitmapped_sizes % 10 == 0)
1493 sprintf(buffer, "%i *", *bitmapped_sizes / 10);
1495 sprintf(buffer, "%i.%i *", *bitmapped_sizes / 10,
1496 *bitmapped_sizes % 10);
1500 sprintf(buffer, "%i *", *bitmapped_sizes);
1506 gtk_clist_append(GTK_CLIST(fontsel->size_clist), &size);
1508 gtk_clist_thaw (GTK_CLIST(fontsel->size_clist));
1512 /* If the user hits return in the font size entry, we change to the new font
1515 gtk_font_selection_size_key_press (GtkWidget *w,
1519 GtkFontSelection *fontsel;
1521 gfloat new_size_float;
1524 #ifdef FONTSEL_DEBUG
1525 g_message("In size_key_press\n");
1527 fontsel = GTK_FONT_SELECTION(data);
1529 if (event->keyval == GDK_Return)
1531 text = gtk_entry_get_text (GTK_ENTRY (fontsel->size_entry));
1532 if (fontsel->metric == GTK_FONT_METRIC_PIXELS)
1534 new_size = atoi (text);
1540 new_size_float = atof (text) * 10;
1541 new_size = (gint) new_size_float;
1546 /* Remember that this size was set explicitly. */
1547 fontsel->selected_size = new_size;
1549 /* Check if the font size has changed, and return if it hasn't. */
1550 if (fontsel->size == new_size)
1553 fontsel->size = new_size;
1554 gtk_font_selection_select_best_size (fontsel);
1562 /* This tries to select the closest size to the current size, though it
1563 may have to change the size if only unscaled bitmaps are available.
1564 Note: this will load a font. */
1566 gtk_font_selection_select_best_size(GtkFontSelection *fontsel)
1569 FontStyle *styles, *style;
1571 gint row, best_row = 0, size, size_fraction, best_size = 0, nmatched;
1572 gboolean found = FALSE;
1577 #ifdef FONTSEL_DEBUG
1578 g_message("In select_best_size\n");
1580 font = &fontsel_info->font_info[fontsel->font_index];
1581 styles = &fontsel_info->font_styles[font->style_index];
1582 style = &styles[fontsel->style];
1584 /* Find the closest size available in the size clist. If the exact size is
1585 in the list set found to TRUE. */
1586 for (row = 0; row < GTK_CLIST(fontsel->size_clist)->rows; row++)
1588 gtk_clist_get_text(GTK_CLIST(fontsel->size_clist), row, 0, &text);
1589 nmatched = sscanf(text, "%i.%i", &size, &size_fraction);
1590 if (fontsel->metric == GTK_FONT_METRIC_POINTS)
1594 size += size_fraction;
1597 if (size == fontsel->selected_size)
1604 else if (best_size == 0
1605 || abs(size - fontsel->selected_size)
1606 < (abs(best_size - fontsel->selected_size)))
1613 /* If we aren't scaling bitmapped fonts and this is a bitmapped font, we
1614 need to use the closest size found. */
1615 type_filter = fontsel->filters[GTK_FONT_FILTER_BASE].font_type
1616 & fontsel->filters[GTK_FONT_FILTER_USER].font_type;
1618 if (!((style->flags & GTK_FONT_SCALABLE_BITMAP
1619 && type_filter & GTK_FONT_SCALABLE_BITMAP)
1620 || (style->flags & GTK_FONT_SCALABLE
1621 && type_filter & GTK_FONT_SCALABLE)))
1626 fontsel->size = best_size;
1627 gtk_clist_moveto(GTK_CLIST(fontsel->size_clist), best_row, -1, 0.5, 0);
1628 gtk_clist_select_row(GTK_CLIST(fontsel->size_clist), best_row, 0);
1632 fontsel->size = fontsel->selected_size;
1633 selection = GTK_CLIST(fontsel->size_clist)->selection;
1635 gtk_clist_unselect_row(GTK_CLIST(fontsel->size_clist),
1636 GPOINTER_TO_INT (selection->data), 0);
1637 gtk_clist_moveto(GTK_CLIST(fontsel->size_clist), best_row, -1, 0.5, 0);
1639 /* Show the size in the size entry. */
1640 if (fontsel->metric == GTK_FONT_METRIC_PIXELS)
1641 sprintf(buffer, "%i", fontsel->size);
1644 if (fontsel->size % 10 == 0)
1645 sprintf(buffer, "%i", fontsel->size / 10);
1647 sprintf(buffer, "%i.%i", fontsel->size / 10, fontsel->size % 10);
1649 gtk_entry_set_text (GTK_ENTRY (fontsel->size_entry), buffer);
1651 gtk_font_selection_load_font (fontsel);
1655 /* This is called when a size is selected in the list. */
1657 gtk_font_selection_select_size (GtkWidget *w,
1660 GdkEventButton *bevent,
1663 GtkFontSelection *fontsel;
1669 #ifdef FONTSEL_DEBUG
1670 g_message("In select_size\n");
1672 fontsel = GTK_FONT_SELECTION(data);
1674 if (bevent && !GTK_WIDGET_HAS_FOCUS (w))
1675 gtk_widget_grab_focus (w);
1677 /* Copy the size from the clist to the size entry, but without the bitmapped
1679 gtk_clist_get_text(GTK_CLIST(fontsel->size_clist), row, 0, &text);
1681 while (i < 15 && (text[i] == '.' || (text[i] >= '0' && text[i] <= '9')))
1683 buffer[i] = text[i];
1687 gtk_entry_set_text(GTK_ENTRY(fontsel->size_entry), buffer);
1689 /* Check if the font size has changed, and return if it hasn't. */
1690 new_size = atoi(text);
1691 if (fontsel->metric == GTK_FONT_METRIC_POINTS)
1694 if (fontsel->size == new_size)
1697 /* If the size was selected by the user we set the selected_size. */
1698 fontsel->selected_size = new_size;
1700 fontsel->size = new_size;
1701 gtk_font_selection_load_font (fontsel);
1705 /* This is called when the pixels or points radio buttons are pressed. */
1707 gtk_font_selection_metric_callback (GtkWidget *w,
1710 GtkFontSelection *fontsel = GTK_FONT_SELECTION(data);
1712 #ifdef FONTSEL_DEBUG
1713 g_message("In metric_callback\n");
1715 if (GTK_TOGGLE_BUTTON(fontsel->pixels_button)->active)
1717 if (fontsel->metric == GTK_FONT_METRIC_PIXELS)
1719 fontsel->metric = GTK_FONT_METRIC_PIXELS;
1720 fontsel->size = (fontsel->size + 5) / 10;
1721 fontsel->selected_size = (fontsel->selected_size + 5) / 10;
1725 if (fontsel->metric == GTK_FONT_METRIC_POINTS)
1727 fontsel->metric = GTK_FONT_METRIC_POINTS;
1728 fontsel->size *= 10;
1729 fontsel->selected_size *= 10;
1731 if (fontsel->font_index != -1)
1733 gtk_font_selection_show_available_sizes (fontsel);
1734 gtk_font_selection_select_best_size (fontsel);
1739 /* This searches the given property table and returns the index of the given
1740 string, or 0, which is the wildcard '*' index, if it's not found. */
1742 gtk_font_selection_field_to_index (gchar **table,
1748 for (i = 0; i < ntable; i++)
1749 if (strcmp (field, table[i]) == 0)
1757 /* This attempts to load the current font, and returns TRUE if it succeeds. */
1759 gtk_font_selection_load_font (GtkFontSelection *fontsel)
1762 gchar *fontname, *label_text;
1765 gdk_font_unref (fontsel->font);
1766 fontsel->font = NULL;
1768 /* If no family has been selected yet, just return FALSE. */
1769 if (fontsel->font_index == -1)
1772 fontname = gtk_font_selection_get_font_name (fontsel);
1775 #ifdef FONTSEL_DEBUG
1776 g_message("Loading: %s\n", fontname);
1778 #ifndef GDK_WINDOWING_WIN32
1779 font = gdk_font_load (fontname);
1781 /* Load as a fontset so that gtkentry uses wide chars for it */
1782 font = gdk_fontset_load (fontname);
1788 fontsel->font = font;
1789 /* Make sure the message label is empty, but don't change it unless
1790 it's necessary as it results in a resize of the whole window! */
1791 gtk_label_get(GTK_LABEL(fontsel->message_label), &label_text);
1792 if (strcmp(label_text, ""))
1793 gtk_label_set_text(GTK_LABEL(fontsel->message_label), "");
1794 gtk_font_selection_update_preview (fontsel);
1799 gtk_label_set_text(GTK_LABEL(fontsel->message_label),
1800 _("The selected font is not available."));
1805 gtk_label_set_text(GTK_LABEL(fontsel->message_label),
1806 _("The selected font is not a valid font."));
1813 /* This sets the font in the preview entry to the selected font, and tries to
1814 make sure that the preview entry is a reasonable size, i.e. so that the
1815 text can be seen with a bit of space to spare. But it tries to avoid
1816 resizing the entry every time the font changes.
1817 This also used to shrink the preview if the font size was decreased, but
1818 that made it awkward if the user wanted to resize the window themself. */
1820 gtk_font_selection_update_preview (GtkFontSelection *fontsel)
1822 GtkWidget *preview_entry;
1824 gint text_height, new_height;
1826 #ifdef GDK_WINDOWING_X11
1830 #ifdef FONTSEL_DEBUG
1831 g_message("In update_preview\n");
1833 style = gtk_style_new ();
1834 gdk_font_unref (style->font);
1835 style->font = fontsel->font;
1836 gdk_font_ref (style->font);
1838 preview_entry = fontsel->preview_entry;
1839 gtk_widget_set_style (preview_entry, style);
1840 gtk_style_unref(style);
1842 text_height = preview_entry->style->font->ascent
1843 + preview_entry->style->font->descent;
1844 /* We don't ever want to be over MAX_PREVIEW_HEIGHT pixels high. */
1845 new_height = text_height + 20;
1846 if (new_height < INITIAL_PREVIEW_HEIGHT)
1847 new_height = INITIAL_PREVIEW_HEIGHT;
1848 if (new_height > MAX_PREVIEW_HEIGHT)
1849 new_height = MAX_PREVIEW_HEIGHT;
1851 if ((preview_entry->requisition.height < text_height + 10)
1852 || (preview_entry->requisition.height > text_height + 40))
1853 gtk_widget_set_usize(preview_entry, -1, new_height);
1855 /* This sets the preview text, if it hasn't been set already. */
1856 text = gtk_entry_get_text(GTK_ENTRY(fontsel->preview_entry));
1857 if (strlen(text) == 0)
1858 gtk_entry_set_text(GTK_ENTRY(fontsel->preview_entry), PREVIEW_TEXT);
1859 gtk_entry_set_position(GTK_ENTRY(fontsel->preview_entry), 0);
1861 #ifdef GDK_WINDOWING_X11
1862 /* If this is a 2-byte font display a message to say it may not be
1863 displayed properly. */
1864 xfs = GDK_FONT_XFONT(fontsel->font);
1865 if (xfs->min_byte1 != 0 || xfs->max_byte1 != 0)
1866 gtk_label_set_text(GTK_LABEL(fontsel->message_label),
1867 _("This is a 2-byte font and may not be displayed correctly."));
1873 gtk_font_selection_switch_page (GtkWidget *w,
1874 GtkNotebookPage *page,
1878 GtkFontSelection *fontsel = GTK_FONT_SELECTION(data);
1880 /* This function strangely gets called when the window is destroyed,
1881 so we check here to see if the notebook is visible. */
1882 if (!GTK_WIDGET_VISIBLE(w))
1886 gtk_font_selection_update_filter(fontsel);
1887 else if (page_num == 1)
1888 gtk_font_selection_show_font_info(fontsel);
1893 gtk_font_selection_show_font_info (GtkFontSelection *fontsel)
1895 #ifdef GDK_WINDOWING_X11
1896 Atom font_atom, atom;
1901 gchar field_buffer[XLFD_MAX_FIELD_LEN];
1904 gboolean shown_actual_fields = FALSE;
1906 fontname = gtk_font_selection_get_font_name(fontsel);
1907 gtk_entry_set_text(GTK_ENTRY(fontsel->requested_font_name),
1908 fontname ? fontname : "");
1910 gtk_clist_freeze (GTK_CLIST(fontsel->info_clist));
1911 for (i = 0; i < GTK_XLFD_NUM_FIELDS; i++)
1914 field = gtk_font_selection_get_xlfd_field (fontname, i, field_buffer);
1919 if (i == XLFD_SLANT)
1920 field = gtk_font_selection_expand_slant_code(field);
1921 else if (i == XLFD_SPACING)
1922 field = gtk_font_selection_expand_spacing_code(field);
1924 gtk_clist_set_text(GTK_CLIST(fontsel->info_clist), i, 1,
1925 field ? field : "");
1927 #ifdef GDK_WINDOWING_X11
1930 font_atom = XInternAtom(GDK_DISPLAY(), "FONT", True);
1931 if (font_atom != None)
1933 status = XGetFontProperty(GDK_FONT_XFONT(fontsel->font), font_atom,
1937 name = XGetAtomName(GDK_DISPLAY(), atom);
1938 gtk_entry_set_text(GTK_ENTRY(fontsel->actual_font_name), name);
1940 for (i = 0; i < GTK_XLFD_NUM_FIELDS; i++)
1942 field = gtk_font_selection_get_xlfd_field (name, i,
1944 if (i == XLFD_SLANT)
1945 field = gtk_font_selection_expand_slant_code(field);
1946 else if (i == XLFD_SPACING)
1947 field = gtk_font_selection_expand_spacing_code(field);
1948 gtk_clist_set_text(GTK_CLIST(fontsel->info_clist), i, 2,
1949 field ? field : "");
1951 shown_actual_fields = TRUE;
1956 #elif defined (GDK_WINDOWING_WIN32)
1961 if (GetObject (GDK_FONT_XFONT (fontsel->font),
1962 sizeof (LOGFONT), &logfont) > 0)
1964 name = logfont_to_xlfd (&logfont, logfont.lfHeight, -1, 0);
1965 gtk_entry_set_text (GTK_ENTRY(fontsel->actual_font_name),name);
1966 for (i = 0; i < GTK_XLFD_NUM_FIELDS; i++)
1968 field = gtk_font_selection_get_xlfd_field (name, i,
1970 if (i == XLFD_SLANT)
1971 field = gtk_font_selection_expand_slant_code(field);
1972 else if (i == XLFD_SPACING)
1973 field = gtk_font_selection_expand_spacing_code(field);
1974 gtk_clist_set_text(GTK_CLIST(fontsel->info_clist), i, 2,
1975 field ? field : "");
1977 shown_actual_fields = TRUE;
1983 if (!shown_actual_fields)
1985 gtk_entry_set_text(GTK_ENTRY(fontsel->actual_font_name), "");
1986 for (i = 0; i < GTK_XLFD_NUM_FIELDS; i++)
1988 gtk_clist_set_text(GTK_CLIST(fontsel->info_clist), i, 2,
1989 fontname ? _("(unknown)") : "");
1992 gtk_clist_thaw (GTK_CLIST(fontsel->info_clist));
1998 gtk_font_selection_expand_slant_code(gchar *slant)
2000 if (!g_strcasecmp(slant, "r")) return(_("roman"));
2001 else if (!g_strcasecmp(slant, "i")) return(_("italic"));
2002 else if (!g_strcasecmp(slant, "o")) return(_("oblique"));
2003 else if (!g_strcasecmp(slant, "ri")) return(_("reverse italic"));
2004 else if (!g_strcasecmp(slant, "ro")) return(_("reverse oblique"));
2005 else if (!g_strcasecmp(slant, "ot")) return(_("other"));
2010 gtk_font_selection_expand_spacing_code(gchar *spacing)
2012 if (!g_strcasecmp(spacing, "p")) return(_("proportional"));
2013 else if (!g_strcasecmp(spacing, "m")) return(_("monospaced"));
2014 else if (!g_strcasecmp(spacing, "c")) return(_("char cell"));
2019 /*****************************************************************************
2020 * These functions all deal with the Filter page and filtering the fonts.
2021 *****************************************************************************/
2023 /* This is called when an item is selected in one of the filter clists.
2024 We make sure that the first row of the clist, i.e. the wildcard '*', is
2025 selected if and only if none of the other items are selected.
2026 Also doesn't allow selections of values filtered out by base filter.
2027 We may need to be careful about triggering other signals. */
2029 gtk_font_selection_select_filter (GtkWidget *w,
2032 GdkEventButton *bevent,
2033 GtkFontSelection *fontsel)
2035 gint i, prop, index;
2039 for (i = 1; i < GTK_CLIST(w)->rows; i++)
2040 gtk_clist_unselect_row(GTK_CLIST(w), i, 0);
2044 /* Find out which property this is. */
2045 for (prop = 0; prop < GTK_NUM_FONT_PROPERTIES; prop++)
2046 if (fontsel->filter_clists[prop] == w)
2048 index = GPOINTER_TO_INT (gtk_clist_get_row_data(GTK_CLIST(w), row));
2049 if (gtk_font_selection_filter_state (fontsel, GTK_FONT_FILTER_BASE,
2050 prop, index) == NOT_FILTERED)
2051 gtk_clist_unselect_row(GTK_CLIST(w), row, 0);
2053 gtk_clist_unselect_row(GTK_CLIST(w), 0, 0);
2058 /* Here a filter item is being deselected. If there are now no items selected
2059 we select the first '*' item, unless that it is the item being deselected,
2060 in which case we select all of the other items. This makes it easy to
2061 select all items in the list except one or two. */
2063 gtk_font_selection_unselect_filter (GtkWidget *w,
2066 GdkEventButton *bevent,
2067 GtkFontSelection *fontsel)
2069 gint i, prop, index;
2071 if (!GTK_CLIST(w)->selection)
2075 /* Find out which property this is. */
2076 for (prop = 0; prop < GTK_NUM_FONT_PROPERTIES; prop++)
2077 if (fontsel->filter_clists[prop] == w)
2080 for (i = 1; i < GTK_CLIST(w)->rows; i++)
2082 index = GPOINTER_TO_INT (gtk_clist_get_row_data(GTK_CLIST(w),
2084 if (gtk_font_selection_filter_state (fontsel,
2085 GTK_FONT_FILTER_BASE,
2088 gtk_clist_select_row(GTK_CLIST(w), i, 0);
2093 gtk_clist_select_row(GTK_CLIST(w), 0, 0);
2099 /* This is called when the main notebook page is selected. It checks if the
2100 filter has changed, an if so it creates the filter settings, and filters the
2101 fonts shown. If an empty filter (all '*'s) is applied, then filtering is
2104 gtk_font_selection_update_filter (GtkFontSelection *fontsel)
2108 gboolean default_filter = TRUE, filter_changed = FALSE;
2109 gint prop, nselected, i, row, index;
2110 GtkFontFilter *filter = &fontsel->filters[GTK_FONT_FILTER_USER];
2111 gint base_font_type, user_font_type, new_font_type;
2113 #ifdef FONTSEL_DEBUG
2114 g_message("In update_filter\n");
2117 /* Check if the user filter has changed, and also if it is the default
2118 filter, i.e. bitmap & scalable fonts and all '*'s selected.
2119 We only look at the bits which are not already filtered out by the base
2120 filter, since that overrides the user filter. */
2121 base_font_type = fontsel->filters[GTK_FONT_FILTER_BASE].font_type
2123 user_font_type = fontsel->filters[GTK_FONT_FILTER_USER].font_type
2125 new_font_type = GTK_TOGGLE_BUTTON(fontsel->type_bitmaps_button)->active
2126 ? GTK_FONT_BITMAP : 0;
2127 new_font_type |= (GTK_TOGGLE_BUTTON(fontsel->type_scalable_button)->active
2128 ? GTK_FONT_SCALABLE : 0);
2129 new_font_type |= (GTK_TOGGLE_BUTTON(fontsel->type_scaled_bitmaps_button)->active ? GTK_FONT_SCALABLE_BITMAP : 0);
2130 new_font_type &= base_font_type;
2131 new_font_type |= (~base_font_type & user_font_type);
2132 if (new_font_type != (GTK_FONT_BITMAP | GTK_FONT_SCALABLE))
2133 default_filter = FALSE;
2135 if (new_font_type != user_font_type)
2136 filter_changed = TRUE;
2137 fontsel->filters[GTK_FONT_FILTER_USER].font_type = new_font_type;
2139 for (prop = 0; prop < GTK_NUM_FONT_PROPERTIES; prop++)
2141 clist = fontsel->filter_clists[prop];
2142 selection = GTK_CLIST(clist)->selection;
2143 nselected = g_list_length(selection);
2144 if (nselected != 1 || GPOINTER_TO_INT (selection->data) != 0)
2146 default_filter = FALSE;
2148 if (filter->property_nfilters[prop] != nselected)
2149 filter_changed = TRUE;
2152 for (i = 0; i < nselected; i++)
2154 row = GPOINTER_TO_INT (selection->data);
2155 index = GPOINTER_TO_INT (gtk_clist_get_row_data (GTK_CLIST (clist), row));
2156 if (filter->property_filters[prop][i] != index)
2157 filter_changed = TRUE;
2158 selection = selection->next;
2164 if (filter->property_nfilters[prop] != 0)
2165 filter_changed = TRUE;
2169 /* If the filter hasn't changed we just return. */
2170 if (!filter_changed)
2173 #ifdef FONTSEL_DEBUG
2174 g_message(" update_fonts: filter has changed\n");
2177 /* Free the old filter data and create the new arrays. */
2178 for (prop = 0; prop < GTK_NUM_FONT_PROPERTIES; prop++)
2180 g_free(filter->property_filters[prop]);
2182 clist = fontsel->filter_clists[prop];
2183 selection = GTK_CLIST(clist)->selection;
2184 nselected = g_list_length(selection);
2185 if (nselected == 1 && GPOINTER_TO_INT (selection->data) == 0)
2187 filter->property_filters[prop] = NULL;
2188 filter->property_nfilters[prop] = 0;
2192 filter->property_filters[prop] = g_new(guint16, nselected);
2193 filter->property_nfilters[prop] = nselected;
2194 for (i = 0; i < nselected; i++)
2196 row = GPOINTER_TO_INT (selection->data);
2197 index = GPOINTER_TO_INT (gtk_clist_get_row_data (GTK_CLIST (clist), row));
2198 filter->property_filters[prop][i] = index;
2199 selection = selection->next;
2204 /* Set the 'Reset Filter' button sensitive if a filter is in effect, and
2205 also set the label above the font list to show this as well. */
2208 gtk_widget_set_sensitive(fontsel->filter_button, FALSE);
2209 gtk_label_set_text(GTK_LABEL(fontsel->font_label), _("Font:"));
2213 gtk_widget_set_sensitive(fontsel->filter_button, TRUE);
2214 gtk_label_set_text(GTK_LABEL(fontsel->font_label), _("Font: (Filter Applied)"));
2216 gtk_font_selection_show_available_fonts(fontsel);
2220 /* This shows all the available fonts in the font clist. */
2222 gtk_font_selection_show_available_fonts (GtkFontSelection *fontsel)
2224 FontInfo *font_info, *font;
2225 GtkFontFilter *filter;
2226 gint nfonts, i, j, k, row, style, font_row = -1;
2227 gchar font_buffer[XLFD_MAX_FIELD_LEN * 2 + 4];
2229 gboolean matched, matched_style;
2231 #ifdef FONTSEL_DEBUG
2232 g_message("In show_available_fonts\n");
2234 font_info = fontsel_info->font_info;
2235 nfonts = fontsel_info->nfonts;
2237 /* Filter the list of fonts. */
2238 gtk_clist_freeze (GTK_CLIST(fontsel->font_clist));
2239 gtk_clist_clear (GTK_CLIST(fontsel->font_clist));
2240 for (i = 0; i < nfonts; i++)
2242 font = &font_info[i];
2244 /* Check if the foundry passes through all filters. */
2246 for (k = 0; k < GTK_NUM_FONT_FILTERS; k++)
2248 filter = &fontsel->filters[k];
2250 if (filter->property_nfilters[FOUNDRY] != 0)
2253 for (j = 0; j < filter->property_nfilters[FOUNDRY]; j++)
2255 if (font->foundry == filter->property_filters[FOUNDRY][j])
2270 /* Now check if the other properties are matched in at least one style.*/
2271 matched_style = FALSE;
2272 for (style = 0; style < font->nstyles; style++)
2274 if (gtk_font_selection_style_visible(fontsel, font, style))
2276 matched_style = TRUE;
2283 /* Insert the font in the clist. */
2284 if ((i > 0 && font->family == font_info[i-1].family)
2285 || (i < nfonts - 1 && font->family == font_info[i+1].family))
2287 sprintf(font_buffer, "%s (%s)", font->family,
2288 fontsel_info->properties[FOUNDRY][font->foundry]);
2289 font_item = font_buffer;
2290 row = gtk_clist_append(GTK_CLIST(fontsel->font_clist), &font_item);
2294 row = gtk_clist_append(GTK_CLIST(fontsel->font_clist),
2297 gtk_clist_set_row_data(GTK_CLIST(fontsel->font_clist), row,
2298 GINT_TO_POINTER (i));
2299 if (fontsel->font_index == i)
2302 gtk_clist_thaw (GTK_CLIST(fontsel->font_clist));
2304 /* If the currently-selected font isn't in the new list, reset the
2308 fontsel->font_index = -1;
2310 gdk_font_unref(fontsel->font);
2311 fontsel->font = NULL;
2312 gtk_entry_set_text(GTK_ENTRY(fontsel->font_entry), "");
2313 gtk_clist_clear (GTK_CLIST(fontsel->font_style_clist));
2314 gtk_entry_set_text(GTK_ENTRY(fontsel->font_style_entry), "");
2318 gtk_clist_select_row(GTK_CLIST(fontsel->font_clist), font_row, 0);
2319 if (gtk_clist_row_is_visible(GTK_CLIST(fontsel->font_clist), font_row)
2320 != GTK_VISIBILITY_FULL)
2321 gtk_clist_moveto(GTK_CLIST(fontsel->font_clist), font_row, -1, 0.5, 0);
2323 gtk_font_selection_show_available_styles (fontsel);
2324 gtk_font_selection_select_best_style (fontsel, FALSE);
2328 /* Returns TRUE if the style is not currently filtered out. */
2330 gtk_font_selection_style_visible(GtkFontSelection *fontsel,
2334 FontStyle *styles, *style;
2335 GtkFontFilter *filter;
2341 styles = &fontsel_info->font_styles[font->style_index];
2342 style = &styles[style_index];
2344 /* Check if font_type of style is filtered. */
2345 type_filter = fontsel->filters[GTK_FONT_FILTER_BASE].font_type
2346 & fontsel->filters[GTK_FONT_FILTER_USER].font_type;
2347 if (!(style->flags & type_filter))
2350 for (prop = 0; prop < GTK_NUM_STYLE_PROPERTIES; prop++)
2352 value = style->properties[prop];
2354 /* Check each filter. */
2355 for (i = 0; i < GTK_NUM_FONT_FILTERS; i++)
2357 filter = &fontsel->filters[i];
2359 if (filter->property_nfilters[prop] != 0)
2362 for (j = 0; j < filter->property_nfilters[prop]; j++)
2364 if (value == filter->property_filters[prop][j])
2379 /* This resets the font type to bitmap or scalable, and sets all the filter
2380 clists to the wildcard '*' options. */
2382 gtk_font_selection_reset_filter (GtkWidget *w,
2383 GtkFontSelection *fontsel)
2385 gint prop, base_font_type;
2387 fontsel->filters[GTK_FONT_FILTER_USER].font_type = GTK_FONT_BITMAP
2388 | GTK_FONT_SCALABLE;
2390 base_font_type = fontsel->filters[GTK_FONT_FILTER_BASE].font_type;
2391 if (base_font_type & GTK_FONT_BITMAP)
2392 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fontsel->type_bitmaps_button), TRUE);
2393 if (base_font_type & GTK_FONT_SCALABLE)
2394 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fontsel->type_scalable_button), TRUE);
2395 if (base_font_type & GTK_FONT_SCALABLE_BITMAP)
2396 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fontsel->type_scaled_bitmaps_button), FALSE);
2398 for (prop = 0; prop < GTK_NUM_FONT_PROPERTIES; prop++)
2399 gtk_clist_select_row(GTK_CLIST(fontsel->filter_clists[prop]), 0, 0);
2403 /* This clears the filter, showing all fonts and styles again. */
2405 gtk_font_selection_on_clear_filter (GtkWidget *w,
2406 GtkFontSelection *fontsel)
2408 gtk_font_selection_clear_filter(fontsel);
2412 /* This resets the user filter, showing all fonts and styles which pass the
2413 base filter again. Note that the font type is set to bitmaps and scalable
2414 fonts - scaled bitmaps are not shown. */
2416 gtk_font_selection_clear_filter (GtkFontSelection *fontsel)
2418 GtkFontFilter *filter;
2421 #ifdef FONTSEL_DEBUG
2422 g_message("In clear_filter\n");
2424 /* Clear the filter data. */
2425 filter = &fontsel->filters[GTK_FONT_FILTER_USER];
2426 filter->font_type = GTK_FONT_BITMAP | GTK_FONT_SCALABLE;
2427 for (prop = 0; prop < GTK_NUM_FONT_PROPERTIES; prop++)
2429 g_free(filter->property_filters[prop]);
2430 filter->property_filters[prop] = NULL;
2431 filter->property_nfilters[prop] = 0;
2434 /* Select all the '*'s on the filter page. */
2435 gtk_font_selection_reset_filter(NULL, fontsel);
2437 /* Update the main notebook page. */
2438 gtk_widget_set_sensitive(fontsel->filter_button, FALSE);
2439 gtk_label_set_text(GTK_LABEL(fontsel->font_label), _("Font:"));
2441 gtk_font_selection_show_available_fonts(fontsel);
2446 gtk_font_selection_set_filter (GtkFontSelection *fontsel,
2447 GtkFontFilterType filter_type,
2448 GtkFontType font_type,
2456 GtkFontFilter *filter;
2457 gchar **filter_strings [GTK_NUM_FONT_PROPERTIES];
2458 gchar *filter_string;
2459 gchar *property, *property_alt;
2460 gint prop, nfilters, i, j, num_found;
2461 gint base_font_type, user_font_type;
2462 gboolean filter_set;
2464 /* Put them into an array so we can use a simple loop. */
2465 filter_strings[FOUNDRY] = foundries;
2466 filter_strings[WEIGHT] = weights;
2467 filter_strings[SLANT] = slants;
2468 filter_strings[SET_WIDTH] = setwidths;
2469 filter_strings[SPACING] = spacings;
2470 filter_strings[CHARSET] = charsets;
2472 filter = &fontsel->filters[filter_type];
2473 filter->font_type = font_type;
2475 /* Free the old filter data, and insert the new. */
2476 for (prop = 0; prop < GTK_NUM_FONT_PROPERTIES; prop++)
2478 g_free(filter->property_filters[prop]);
2479 filter->property_filters[prop] = NULL;
2480 filter->property_nfilters[prop] = 0;
2482 if (filter_strings[prop])
2484 /* Count how many items in the new array. */
2486 while (filter_strings[prop][nfilters])
2489 filter->property_filters[prop] = g_new(guint16, nfilters);
2490 filter->property_nfilters[prop] = 0;
2492 /* Now convert the strings to property indices. */
2494 for (i = 0; i < nfilters; i++)
2496 filter_string = filter_strings[prop][i];
2497 for (j = 0; j < fontsel_info->nproperties[prop]; j++)
2499 property = _(fontsel_info->properties[prop][j]);
2500 property_alt = NULL;
2502 property_alt = gtk_font_selection_expand_slant_code(property);
2503 else if (prop == SPACING)
2504 property_alt = gtk_font_selection_expand_spacing_code(property);
2505 if (!strcmp (filter_string, property)
2506 || (property_alt && !strcmp (filter_string, property_alt)))
2508 filter->property_filters[prop][num_found] = j;
2514 filter->property_nfilters[prop] = num_found;
2518 /* Now set the clists on the filter page according to the new filter. */
2519 gtk_font_selection_update_filter_lists (fontsel);
2521 if (filter_type == GTK_FONT_FILTER_BASE)
2523 user_font_type = fontsel->filters[GTK_FONT_FILTER_USER].font_type;
2524 if (font_type & GTK_FONT_BITMAP)
2526 gtk_widget_set_sensitive (fontsel->type_bitmaps_button, TRUE);
2527 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fontsel->type_bitmaps_button), user_font_type & GTK_FONT_BITMAP);
2531 gtk_widget_set_sensitive (fontsel->type_bitmaps_button, FALSE);
2532 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fontsel->type_bitmaps_button), FALSE);
2535 if (font_type & GTK_FONT_SCALABLE)
2537 gtk_widget_set_sensitive (fontsel->type_scalable_button, TRUE);
2538 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fontsel->type_scalable_button), user_font_type & GTK_FONT_SCALABLE);
2542 gtk_widget_set_sensitive (fontsel->type_scalable_button, FALSE);
2543 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fontsel->type_scalable_button), FALSE);
2546 if (font_type & GTK_FONT_SCALABLE_BITMAP)
2548 gtk_widget_set_sensitive (fontsel->type_scaled_bitmaps_button, TRUE);
2549 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fontsel->type_scaled_bitmaps_button), user_font_type & GTK_FONT_SCALABLE_BITMAP);
2553 gtk_widget_set_sensitive (fontsel->type_scaled_bitmaps_button, FALSE);
2554 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fontsel->type_scaled_bitmaps_button), FALSE);
2559 base_font_type = fontsel->filters[GTK_FONT_FILTER_BASE].font_type;
2560 if (base_font_type & GTK_FONT_BITMAP)
2561 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fontsel->type_bitmaps_button), font_type & GTK_FONT_BITMAP);
2563 if (base_font_type & GTK_FONT_SCALABLE)
2564 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fontsel->type_scalable_button), font_type & GTK_FONT_SCALABLE);
2566 if (base_font_type & GTK_FONT_SCALABLE_BITMAP)
2567 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fontsel->type_scaled_bitmaps_button), font_type & GTK_FONT_SCALABLE_BITMAP);
2569 /* If the user filter is not the default, make the 'Reset Filter' button
2572 if (font_type != (GTK_FONT_BITMAP | GTK_FONT_SCALABLE))
2574 for (prop = 0; prop < GTK_NUM_FONT_PROPERTIES; prop++)
2576 if (filter->property_nfilters[prop] != 0)
2580 gtk_widget_set_sensitive (fontsel->filter_button, TRUE);
2583 gtk_font_selection_show_available_fonts (fontsel);
2587 /* This sets the colour of each property in the filter clists according to
2588 the base filter. i.e. Filtered properties are shown as insensitive. */
2590 gtk_font_selection_update_filter_lists (GtkFontSelection *fontsel)
2593 GdkColor *inactive_fg, *inactive_bg, *fg, *bg;
2594 gint prop, row, index;
2596 /* We have to make sure the clist is realized to use the colours. */
2597 for (prop = 0; prop < GTK_NUM_FONT_PROPERTIES; prop++)
2599 clist = fontsel->filter_clists[prop];
2600 gtk_widget_realize (clist);
2601 inactive_fg = &clist->style->fg[GTK_STATE_INSENSITIVE];
2602 inactive_bg = &clist->style->bg[GTK_STATE_INSENSITIVE];
2603 for (row = 1; row < GTK_CLIST(clist)->rows; row++)
2605 index = GPOINTER_TO_INT (gtk_clist_get_row_data(GTK_CLIST(clist),
2607 /* Set the colour according to the base filter. */
2608 if (gtk_font_selection_filter_state (fontsel, GTK_FONT_FILTER_BASE,
2609 prop, index) == NOT_FILTERED)
2619 gtk_clist_set_foreground(GTK_CLIST(clist), row, fg);
2620 gtk_clist_set_background(GTK_CLIST(clist), row, bg);
2622 /* Set the selection state according to the user filter. */
2623 if (gtk_font_selection_filter_state (fontsel, GTK_FONT_FILTER_USER,
2624 prop, index) == FILTERED
2626 gtk_clist_select_row (GTK_CLIST (clist), row, 0);
2628 gtk_clist_unselect_row (GTK_CLIST (clist), row, 0);
2634 /* Returns whether a property value is in the filter or not, or if the
2635 property has no filter set. */
2636 static GtkFontPropertyFilterState
2637 gtk_font_selection_filter_state (GtkFontSelection *fontsel,
2638 GtkFontFilterType filter_type,
2642 GtkFontFilter *filter;
2645 filter = &fontsel->filters[filter_type];
2646 if (filter->property_nfilters[property] == 0)
2649 for (i = 0; i < filter->property_nfilters[property]; i++)
2651 if (filter->property_filters[property][i] == index)
2654 return NOT_FILTERED;
2658 #ifdef GDK_WINDOWING_WIN32
2660 static gint num_fonts;
2661 static gint font_names_size;
2662 static gchar **xfontnames;
2666 logfont_to_xlfd (const LOGFONT *lfp,
2671 const gchar *weight;
2672 const gchar *registry, *encoding;
2674 static int logpixelsy = 0;
2675 gchar facename[LF_FACESIZE*3];
2679 if (logpixelsy == 0)
2681 HDC hdc = GetDC (NULL);
2682 logpixelsy = GetDeviceCaps (hdc, LOGPIXELSY);
2683 ReleaseDC (NULL, hdc);
2686 /* Don't use _() here, only N_(), the actual translation is done elsewhere */
2687 if (lfp->lfWeight >= FW_HEAVY)
2688 weight = N_("heavy");
2689 else if (lfp->lfWeight >= FW_EXTRABOLD)
2690 weight = N_("extrabold");
2691 else if (lfp->lfWeight >= FW_BOLD)
2692 weight = N_("bold");
2694 else if (lfp->lfWeight >= FW_DEMIBOLD)
2695 weight = N_("demibold");
2697 else if (lfp->lfWeight >= FW_MEDIUM)
2698 weight = N_("medium");
2699 else if (lfp->lfWeight >= FW_NORMAL)
2700 weight = N_("normal");
2701 else if (lfp->lfWeight >= FW_LIGHT)
2702 weight = N_("light");
2703 else if (lfp->lfWeight >= FW_EXTRALIGHT)
2704 weight = N_("extralight");
2705 else if (lfp->lfWeight >= FW_THIN)
2706 weight = N_("thin");
2708 weight = N_("regular");
2710 if (lfp->lfCharSet == ANSI_CHARSET)
2712 registry = "iso8859";
2717 registry = "windows";
2718 if (lfp->lfCharSet == DEFAULT_CHARSET)
2719 encoding = "default";
2720 else if (lfp->lfCharSet == SYMBOL_CHARSET)
2721 encoding = "symbol";
2722 else if (lfp->lfCharSet == SHIFTJIS_CHARSET)
2723 encoding = "shiftjis";
2724 else if (lfp->lfCharSet == GB2312_CHARSET)
2725 encoding = "gb2312";
2726 else if (lfp->lfCharSet == HANGEUL_CHARSET)
2727 encoding = "hangeul";
2728 else if (lfp->lfCharSet == CHINESEBIG5_CHARSET)
2729 encoding = "chinesebig5";
2730 else if (lfp->lfCharSet == OEM_CHARSET)
2732 #ifdef JOHAB_CHARSET
2733 else if (lfp->lfCharSet == JOHAB_CHARSET)
2736 else if (lfp->lfCharSet == HEBREW_CHARSET)
2737 encoding = "hebrew";
2738 else if (lfp->lfCharSet == ARABIC_CHARSET)
2739 encoding = "arabic";
2740 else if (lfp->lfCharSet == GREEK_CHARSET)
2742 else if (lfp->lfCharSet == TURKISH_CHARSET)
2743 encoding = "turkish";
2744 else if (lfp->lfCharSet == THAI_CHARSET)
2746 else if (lfp->lfCharSet == EASTEUROPE_CHARSET)
2747 encoding = "easteurope";
2748 else if (lfp->lfCharSet == RUSSIAN_CHARSET)
2749 encoding = "russian";
2750 else if (lfp->lfCharSet == MAC_CHARSET)
2752 else if (lfp->lfCharSet == BALTIC_CHARSET)
2753 encoding = "baltic";
2755 encoding = "unknown";
2758 point_size = (int) (((double) size/logpixelsy) * 720.);
2763 /* Replace illegal characters with hex escapes. */
2765 q = lfp->lfFaceName;
2768 if (*q == '-' || *q == '*' || *q == '?' || *q == '%')
2769 p += sprintf (p, "%%%.02x", *q);
2776 return g_strdup_printf
2777 ("-%s-%s-%s-%s-%s-%s-%d-%d-%d-%d-%s-%d-%s-%s",
2782 ((lfp->lfPitchAndFamily & 0xF0) == FF_ROMAN
2783 || (lfp->lfPitchAndFamily & 0xF0) == FF_SCRIPT ?
2791 ((lfp->lfPitchAndFamily & 0x03) == FIXED_PITCH ? "m" : "p"),
2793 registry, encoding);
2797 InnerEnumFontFamExProc (const LOGFONT *lfp,
2798 const TEXTMETRIC *metrics,
2804 if (fontType == TRUETYPE_FONTTYPE)
2810 size = lfp->lfHeight;
2814 if (num_fonts == font_names_size)
2816 font_names_size *= 2;
2817 xfontnames = g_realloc (xfontnames, font_names_size * sizeof (gchar *));
2819 xfontnames[num_fonts-1] =
2820 logfont_to_xlfd (lfp, size, 0, 0);
2825 EnumFontFamExProc (const LOGFONT *lfp,
2826 const TEXTMETRIC *metrics,
2830 if (fontType == TRUETYPE_FONTTYPE)
2833 lf.lfPitchAndFamily = 0;
2834 EnumFontFamiliesEx (hdc, &lf, InnerEnumFontFamExProc, 0, 0);
2837 InnerEnumFontFamExProc (lfp, metrics, fontType, lParam);
2843 /*****************************************************************************
2844 * These functions all deal with creating the main class arrays containing
2845 * the data about all available fonts.
2846 *****************************************************************************/
2848 gtk_font_selection_get_fonts (void)
2850 #ifdef GDK_WINDOWING_X11
2853 #elif defined (GDK_WINDOWING_WIN32)
2857 gchar **xfontnames = NULL;
2862 gint i, prop, style, size;
2863 gint npixel_sizes = 0, npoint_sizes = 0;
2865 FontStyle *current_style, *prev_style, *tmp_style;
2866 gboolean matched_style, found_size;
2867 gint pixels, points, res_x, res_y;
2868 gchar field_buffer[XLFD_MAX_FIELD_LEN];
2871 guint16 *pixel_sizes, *point_sizes, *tmp_sizes;
2873 fontsel_info = g_new (GtkFontSelInfo, 1);
2875 #ifdef GDK_WINDOWING_X11
2876 /* Get a maximum of MAX_FONTS fontnames from the X server.
2877 Use "-*" as the pattern rather than "-*-*-*-*-*-*-*-*-*-*-*-*-*-*" since
2878 the latter may result in fonts being returned which don't actually exist.
2879 xlsfonts also uses "*" so I think it's OK. "-*" gets rid of aliases. */
2880 xfontnames = XListFonts (GDK_DISPLAY(), "-*", MAX_FONTS, &num_fonts);
2881 /* Output a warning if we actually get MAX_FONTS fonts. */
2882 if (num_fonts == MAX_FONTS)
2883 g_warning(_("MAX_FONTS exceeded. Some fonts may be missing."));
2885 #elif defined (GDK_WINDOWING_WIN32)
2888 font_names_size = 100;
2889 xfontnames = g_new (gchar *, font_names_size);
2890 logfont.lfCharSet = DEFAULT_CHARSET;
2891 logfont.lfFaceName[0] = '\0';
2892 logfont.lfPitchAndFamily = 0;
2893 EnumFontFamiliesEx (hdc, &logfont, EnumFontFamExProc, 0, 0);
2894 ReleaseDC (NULL, hdc);
2897 /* The maximum size of all these tables is the number of font names
2898 returned. We realloc them later when we know exactly how many
2899 unique entries there are. */
2900 fontsel_info->font_info = g_new (FontInfo, num_fonts);
2901 fontsel_info->font_styles = g_new (FontStyle, num_fonts);
2902 fontsel_info->pixel_sizes = g_new (guint16, num_fonts);
2903 fontsel_info->point_sizes = g_new (guint16, num_fonts);
2905 fontnames = g_new (GSList*, num_fonts);
2907 /* Create the initial arrays for the property value strings, though they
2908 may be realloc'ed later. Put the wildcard '*' in the first elements. */
2909 for (prop = 0; prop < GTK_NUM_FONT_PROPERTIES; prop++)
2911 fontsel_info->properties[prop] = g_new(gchar*, PROPERTY_ARRAY_INCREMENT);
2912 fontsel_info->space_allocated[prop] = PROPERTY_ARRAY_INCREMENT;
2913 fontsel_info->nproperties[prop] = 1;
2914 fontsel_info->properties[prop][0] = "*";
2918 /* Insert the font families into the main table, sorted by family and
2919 foundry (fonts with different foundries are placed in seaparate FontInfos.
2920 All fontnames in each family + foundry are placed into the fontnames
2922 fontsel_info->nfonts = 0;
2923 for (i = 0; i < num_fonts; i++)
2925 if (gtk_font_selection_is_xlfd_font_name (xfontnames[i]))
2926 gtk_font_selection_insert_font (fontnames, &fontsel_info->nfonts, xfontnames[i]);
2930 /* Since many font names will be in the same FontInfo not all of the
2931 allocated FontInfo table will be used, so we will now reallocate it
2932 with the real size. */
2933 fontsel_info->font_info = g_realloc(fontsel_info->font_info,
2934 sizeof(FontInfo) * fontsel_info->nfonts);
2937 /* Now we work out which choices of weight/slant etc. are valid for each
2939 fontsel_info->nstyles = 0;
2940 current_style = fontsel_info->font_styles;
2941 for (i = 0; i < fontsel_info->nfonts; i++)
2943 font = &fontsel_info->font_info[i];
2945 /* Use the next free position in the styles array. */
2946 font->style_index = fontsel_info->nstyles;
2948 /* Now step through each of the fontnames with this family, and create
2949 a style for each fontname. Each style contains the index into the
2950 weights/slants etc. arrays, and a number of pixel/point sizes. */
2952 temp_list = fontnames[i];
2955 fontname = temp_list->data;
2956 temp_list = temp_list->next;
2958 for (prop = 0; prop < GTK_NUM_STYLE_PROPERTIES; prop++)
2960 current_style->properties[prop]
2961 = gtk_font_selection_insert_field (fontname, prop);
2963 current_style->pixel_sizes_index = npixel_sizes;
2964 current_style->npixel_sizes = 0;
2965 current_style->point_sizes_index = npoint_sizes;
2966 current_style->npoint_sizes = 0;
2967 current_style->flags = 0;
2970 field = gtk_font_selection_get_xlfd_field (fontname, XLFD_PIXELS,
2972 pixels = atoi(field);
2974 field = gtk_font_selection_get_xlfd_field (fontname, XLFD_POINTS,
2976 points = atoi(field);
2978 field = gtk_font_selection_get_xlfd_field (fontname,
2981 res_x = atoi(field);
2983 field = gtk_font_selection_get_xlfd_field (fontname,
2986 res_y = atoi(field);
2988 if (pixels == 0 && points == 0)
2990 if (res_x == 0 && res_y == 0)
2991 flags = GTK_FONT_SCALABLE;
2993 flags = GTK_FONT_SCALABLE_BITMAP;
2996 flags = GTK_FONT_BITMAP;
2998 /* Now we check to make sure that the style is unique. If it isn't
3000 prev_style = fontsel_info->font_styles + font->style_index;
3001 matched_style = FALSE;
3002 while (prev_style < current_style)
3004 matched_style = TRUE;
3005 for (prop = 0; prop < GTK_NUM_STYLE_PROPERTIES; prop++)
3007 if (prev_style->properties[prop]
3008 != current_style->properties[prop])
3010 matched_style = FALSE;
3019 /* If we matched an existing style, we need to add the pixels &
3020 point sizes to the style. If not, we insert the pixel & point
3021 sizes into our new style. Note that we don't add sizes for
3025 prev_style->flags |= flags;
3026 if (flags == GTK_FONT_BITMAP)
3028 pixel_sizes = fontsel_info->pixel_sizes
3029 + prev_style->pixel_sizes_index;
3031 for (size = 0; size < prev_style->npixel_sizes; size++)
3033 if (pixels == *pixel_sizes)
3038 else if (pixels < *pixel_sizes)
3042 /* We need to move all the following pixel sizes up, and also
3043 update the indexes of any following styles. */
3046 for (tmp_sizes = fontsel_info->pixel_sizes + npixel_sizes;
3047 tmp_sizes > pixel_sizes; tmp_sizes--)
3048 *tmp_sizes = *(tmp_sizes - 1);
3050 *pixel_sizes = pixels;
3052 prev_style->npixel_sizes++;
3054 tmp_style = prev_style + 1;
3055 while (tmp_style < current_style)
3057 tmp_style->pixel_sizes_index++;
3062 point_sizes = fontsel_info->point_sizes
3063 + prev_style->point_sizes_index;
3065 for (size = 0; size < prev_style->npoint_sizes; size++)
3067 if (points == *point_sizes)
3072 else if (points < *point_sizes)
3076 /* We need to move all the following point sizes up, and also
3077 update the indexes of any following styles. */
3080 for (tmp_sizes = fontsel_info->point_sizes + npoint_sizes;
3081 tmp_sizes > point_sizes; tmp_sizes--)
3082 *tmp_sizes = *(tmp_sizes - 1);
3084 *point_sizes = points;
3086 prev_style->npoint_sizes++;
3088 tmp_style = prev_style + 1;
3089 while (tmp_style < current_style)
3091 tmp_style->point_sizes_index++;
3099 current_style->flags = flags;
3100 if (flags == GTK_FONT_BITMAP)
3102 fontsel_info->pixel_sizes[npixel_sizes++] = pixels;
3103 current_style->npixel_sizes = 1;
3104 fontsel_info->point_sizes[npoint_sizes++] = points;
3105 current_style->npoint_sizes = 1;
3108 fontsel_info->nstyles++;
3112 g_slist_free(fontnames[i]);
3114 /* Set nstyles to the real value, minus duplicated fontnames.
3115 Note that we aren't using all the allocated memory if fontnames are
3117 font->nstyles = style;
3120 /* Since some repeated styles may be skipped we won't have used all the
3121 allocated space, so we will now reallocate it with the real size. */
3122 fontsel_info->font_styles = g_realloc(fontsel_info->font_styles,
3123 sizeof(FontStyle) * fontsel_info->nstyles);
3124 fontsel_info->pixel_sizes = g_realloc(fontsel_info->pixel_sizes,
3125 sizeof(guint16) * npixel_sizes);
3126 fontsel_info->point_sizes = g_realloc(fontsel_info->point_sizes,
3127 sizeof(guint16) * npoint_sizes);
3130 #ifdef GDK_WINDOWING_X11
3131 XFreeFontNames (xfontnames);
3132 #elif defined (GDK_WINDOWING_WIN32)
3133 for (i = 0; i < num_fonts; i++)
3134 g_free (xfontnames[i]);
3135 g_free (xfontnames);
3138 /* Debugging Output */
3139 /* This outputs all FontInfos. */
3140 #ifdef FONTSEL_DEBUG
3141 g_message("\n\n Font Family Weight Slant Set Width Spacing Charset\n\n");
3142 for (i = 0; i < fontsel_info->nfonts; i++)
3144 FontInfo *font = &fontsel_info->font_info[i];
3145 FontStyle *styles = fontsel_info->font_styles + font->style_index;
3146 for (style = 0; style < font->nstyles; style++)
3148 g_message("%5i %-16.16s ", i, font->family);
3149 for (prop = 0; prop < GTK_NUM_STYLE_PROPERTIES; prop++)
3150 g_message("%-9.9s ",
3151 fontsel_info->properties[prop][styles->properties[prop]]);
3154 if (styles->flags & GTK_FONT_BITMAP)
3155 g_message("Bitmapped font ");
3156 if (styles->flags & GTK_FONT_SCALABLE)
3157 g_message("Scalable font ");
3158 if (styles->flags & GTK_FONT_SCALABLE_BITMAP)
3159 g_message("Scalable-Bitmapped font ");
3162 if (styles->npixel_sizes)
3164 g_message(" Pixel sizes: ");
3165 tmp_sizes = fontsel_info->pixel_sizes + styles->pixel_sizes_index;
3166 for (size = 0; size < styles->npixel_sizes; size++)
3167 g_message("%i ", *tmp_sizes++);
3171 if (styles->npoint_sizes)
3173 g_message(" Point sizes: ");
3174 tmp_sizes = fontsel_info->point_sizes + styles->point_sizes_index;
3175 for (size = 0; size < styles->npoint_sizes; size++)
3176 g_message("%i ", *tmp_sizes++);
3184 /* This outputs all available properties. */
3185 for (prop = 0; prop < GTK_NUM_FONT_PROPERTIES; prop++)
3187 g_message("Property: %s\n", xlfd_field_names[xlfd_index[prop]]);
3188 for (i = 0; i < fontsel_info->nproperties[prop]; i++)
3189 g_message(" %s\n", fontsel_info->properties[prop][i]);
3194 /* This inserts the given fontname into the FontInfo table.
3195 If a FontInfo already exists with the same family and foundry, then the
3196 fontname is added to the FontInfos list of fontnames, else a new FontInfo
3197 is created and inserted in alphabetical order in the table. */
3199 gtk_font_selection_insert_font (GSList *fontnames[],
3205 GSList *temp_fontname;
3207 gboolean family_exists = FALSE;
3211 gchar family_buffer[XLFD_MAX_FIELD_LEN];
3213 table = fontsel_info->font_info;
3215 /* insert a fontname into a table */
3216 family = gtk_font_selection_get_xlfd_field (fontname, XLFD_FAMILY,
3221 foundry = gtk_font_selection_insert_field (fontname, FOUNDRY);
3226 /* Do a binary search to determine if we have already encountered
3227 * a font with this family & foundry. */
3229 while (lower < upper)
3231 middle = (lower + upper) >> 1;
3233 cmp = strcmp (family, table[middle].family);
3234 /* If the family matches we sort by the foundry. */
3237 family_exists = TRUE;
3238 family = table[middle].family;
3239 cmp = strcmp(fontsel_info->properties[FOUNDRY][foundry],
3240 fontsel_info->properties[FOUNDRY][table[middle].foundry]);
3245 fontnames[middle] = g_slist_prepend (fontnames[middle],
3256 /* Add another entry to the table for this new font family */
3257 temp_info.family = family_exists ? family : g_strdup(family);
3258 temp_info.foundry = foundry;
3259 temp_fontname = g_slist_prepend (NULL, fontname);
3263 /* Quickly insert the entry into the table in sorted order
3264 * using a modification of insertion sort and the knowledge
3265 * that the entries proper position in the table was determined
3266 * above in the binary search and is contained in the "lower"
3270 upper = *ntable - 1;
3271 while (lower != upper)
3273 table[upper] = table[upper-1];
3274 fontnames[upper] = fontnames[upper-1];
3278 table[lower] = temp_info;
3279 fontnames[lower] = temp_fontname;
3283 /* This checks that the specified field of the given fontname is in the
3284 appropriate properties array. If not it is added. Thus eventually we get
3285 arrays of all possible weights/slants etc. It returns the array index. */
3287 gtk_font_selection_insert_field (gchar *fontname,
3290 gchar field_buffer[XLFD_MAX_FIELD_LEN];
3294 field = gtk_font_selection_get_xlfd_field (fontname, xlfd_index[prop],
3299 /* If the field is already in the array just return its index. */
3300 for (index = 0; index < fontsel_info->nproperties[prop]; index++)
3301 if (!strcmp(field, fontsel_info->properties[prop][index]))
3304 /* Make sure we have enough space to add the field. */
3305 if (fontsel_info->nproperties[prop] == fontsel_info->space_allocated[prop])
3307 fontsel_info->space_allocated[prop] += PROPERTY_ARRAY_INCREMENT;
3308 fontsel_info->properties[prop] = g_realloc(fontsel_info->properties[prop],
3310 * fontsel_info->space_allocated[prop]);
3313 /* Add the new field. */
3314 index = fontsel_info->nproperties[prop];
3315 fontsel_info->properties[prop][index] = g_strdup(field);
3316 fontsel_info->nproperties[prop]++;
3321 /*****************************************************************************
3322 * These functions are the main public interface for getting/setting the font.
3323 *****************************************************************************/
3326 gtk_font_selection_get_font (GtkFontSelection *fontsel)
3328 g_return_val_if_fail (fontsel != NULL, NULL);
3329 return fontsel->font;
3334 gtk_font_selection_get_font_name (GtkFontSelection *fontsel)
3337 gchar *family_str, *foundry_str;
3338 gchar *property_str[GTK_NUM_STYLE_PROPERTIES];
3341 g_return_val_if_fail (fontsel != NULL, NULL);
3342 g_return_val_if_fail (GTK_IS_FONT_SELECTION (fontsel), NULL);
3344 /* If no family has been selected return NULL. */
3345 if (fontsel->font_index == -1)
3348 font = &fontsel_info->font_info[fontsel->font_index];
3349 family_str = font->family;
3350 foundry_str = fontsel_info->properties[FOUNDRY][font->foundry];
3352 for (prop = 0; prop < GTK_NUM_STYLE_PROPERTIES; prop++)
3355 = fontsel_info->properties[prop][fontsel->property_values[prop]];
3356 if (strcmp (property_str[prop], "(nil)") == 0)
3357 property_str[prop] = "";
3360 return gtk_font_selection_create_xlfd (fontsel->size,
3364 property_str[WEIGHT],
3365 property_str[SLANT],
3366 property_str[SET_WIDTH],
3367 property_str[SPACING],
3368 property_str[CHARSET]);
3372 /* This sets the current font, selecting the appropriate clist rows.
3373 First we check the fontname is valid and try to find the font family
3374 - i.e. the name in the main list. If we can't find that, then just return.
3375 Next we try to set each of the properties according to the fontname.
3376 Finally we select the font family & style in the clists. */
3378 gtk_font_selection_set_font_name (GtkFontSelection *fontsel,
3379 const gchar *fontname)
3381 gchar *family, *field;
3382 gint index, prop, size;
3383 guint16 foundry, value;
3384 gchar family_buffer[XLFD_MAX_FIELD_LEN];
3385 gchar field_buffer[XLFD_MAX_FIELD_LEN];
3388 g_return_val_if_fail (fontsel != NULL, FALSE);
3389 g_return_val_if_fail (GTK_IS_FONT_SELECTION (fontsel), FALSE);
3390 g_return_val_if_fail (fontname != NULL, FALSE);
3392 /* Check it is a valid fontname. */
3393 if (!gtk_font_selection_is_xlfd_font_name(fontname))
3396 family = gtk_font_selection_get_xlfd_field (fontname, XLFD_FAMILY,
3401 field = gtk_font_selection_get_xlfd_field (fontname, XLFD_FOUNDRY,
3403 foundry = gtk_font_selection_field_to_index (fontsel_info->properties[FOUNDRY],
3404 fontsel_info->nproperties[FOUNDRY],
3407 index = gtk_font_selection_find_font(fontsel, family, foundry);
3411 /* Convert the property fields into indices and set them. */
3412 for (prop = 0; prop < GTK_NUM_STYLE_PROPERTIES; prop++)
3414 field = gtk_font_selection_get_xlfd_field (fontname, xlfd_index[prop],
3416 value = gtk_font_selection_field_to_index (fontsel_info->properties[prop],
3417 fontsel_info->nproperties[prop],
3419 fontsel->property_values[prop] = value;
3422 field = gtk_font_selection_get_xlfd_field (fontname, XLFD_POINTS,
3429 fontsel->size = fontsel->selected_size = size;
3430 fontsel->metric = GTK_FONT_METRIC_POINTS;
3431 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(fontsel->points_button),
3434 sprintf (buffer, "%i", size / 10);
3436 sprintf (buffer, "%i.%i", size / 10, size % 10);
3440 field = gtk_font_selection_get_xlfd_field (fontname, XLFD_PIXELS,
3445 fontsel->size = fontsel->selected_size = size;
3446 fontsel->metric = GTK_FONT_METRIC_PIXELS;
3447 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(fontsel->pixels_button),
3449 sprintf (buffer, "%i", size);
3451 gtk_entry_set_text (GTK_ENTRY (fontsel->size_entry), buffer);
3453 /* Clear any current filter. */
3454 gtk_font_selection_clear_filter(fontsel);
3456 /* Now find the best style match. */
3457 fontsel->font_index = index;
3458 gtk_clist_select_row(GTK_CLIST(fontsel->font_clist), index, 0);
3459 if (GTK_WIDGET_MAPPED (fontsel->font_clist))
3460 gtk_clist_moveto(GTK_CLIST(fontsel->font_clist), index, -1, 0.5, 0);
3462 gtk_font_selection_show_available_styles (fontsel);
3463 /* This will load the font. */
3464 gtk_font_selection_select_best_style (fontsel, FALSE);
3470 /* Returns the index of the given family, or -1 if not found */
3472 gtk_font_selection_find_font (GtkFontSelection *fontsel,
3476 FontInfo *font_info;
3477 gint lower, upper, middle = -1, cmp, nfonts;
3478 gint found_family = -1;
3480 font_info = fontsel_info->font_info;
3481 nfonts = fontsel_info->nfonts;
3485 /* Do a binary search to find the font family. */
3488 while (lower < upper)
3490 middle = (lower + upper) >> 1;
3492 cmp = strcmp (family, font_info[middle].family);
3495 found_family = middle;
3496 cmp = strcmp(fontsel_info->properties[FOUNDRY][foundry],
3497 fontsel_info->properties[FOUNDRY][font_info[middle].foundry]);
3508 /* We couldn't find the family and foundry, but we may have just found the
3509 family, so we return that. */
3510 return found_family;
3514 /* This returns the text in the preview entry. You should copy the returned
3515 text if you need it. */
3517 gtk_font_selection_get_preview_text (GtkFontSelection *fontsel)
3519 return gtk_entry_get_text(GTK_ENTRY(fontsel->preview_entry));
3523 /* This sets the text in the preview entry. */
3525 gtk_font_selection_set_preview_text (GtkFontSelection *fontsel,
3528 gtk_entry_set_text(GTK_ENTRY(fontsel->preview_entry), text);
3532 /*****************************************************************************
3533 * These functions all deal with X Logical Font Description (XLFD) fontnames.
3534 * See the freely available documentation about this.
3535 *****************************************************************************/
3538 * Returns TRUE if the fontname is a valid XLFD.
3539 * (It just checks if the number of dashes is 14, and that each
3540 * field < XLFD_MAX_FIELD_LEN characters long - that's not in the XLFD but it
3541 * makes it easier for me).
3544 gtk_font_selection_is_xlfd_font_name (const gchar *fontname)
3551 if (*fontname++ == '-')
3553 if (field_len > XLFD_MAX_FIELD_LEN) return FALSE;
3561 return (i == 14) ? TRUE : FALSE;
3565 * This fills the buffer with the specified field from the X Logical Font
3566 * Description name, and returns it. If fontname is NULL or the field is
3567 * longer than XFLD_MAX_FIELD_LEN it returns NULL.
3568 * Note: For the charset field, we also return the encoding, e.g. 'iso8859-1'.
3571 gtk_font_selection_get_xlfd_field (const gchar *fontname,
3572 FontField field_num,
3575 const gchar *t1, *t2;
3576 gint countdown, len, num_dashes;
3577 #ifdef GDK_WINDOWING_WIN32
3584 /* we assume this is a valid fontname...that is, it has 14 fields */
3586 countdown = field_num;
3588 while (*t1 && (countdown >= 0))
3592 num_dashes = (field_num == XLFD_CHARSET) ? 2 : 1;
3593 for (t2 = t1; *t2; t2++)
3595 if (*t2 == '-' && --num_dashes == 0)
3601 /* Check we don't overflow the buffer */
3602 len = (long) t2 - (long) t1;
3603 if (len > XLFD_MAX_FIELD_LEN - 1)
3605 strncpy (buffer, t1, len);
3607 #ifdef GDK_WINDOWING_X11
3608 /* Convert to lower case. */
3610 #elif defined (GDK_WINDOWING_WIN32)
3611 /* Check for hex escapes in font family */
3612 if (field_num == XLFD_FAMILY)
3617 if (*p == '%' && isxdigit (p[1]) && isxdigit (p[2]))
3620 sscanf (p+1, "%2x", &c);
3630 strcpy(buffer, "(nil)");
3636 * This returns a X Logical Font Description font name, given all the pieces.
3637 * Note: this retval must be freed by the caller.
3640 gtk_font_selection_create_xlfd (gint size,
3641 GtkFontMetricType metric,
3651 gchar *pixel_size = "*", *point_size = "*", *fontname;
3652 gchar *fam = family;
3653 #ifdef GDK_WINDOWING_WIN32
3660 sprintf (buffer, "%d", (int) size);
3661 if (metric == GTK_FONT_METRIC_PIXELS)
3662 pixel_size = buffer;
3664 point_size = buffer;
3666 #ifdef GDK_WINDOWING_WIN32
3667 fam = g_malloc (strlen (family) * 3 + 1);
3672 if (*q == '-' || *q == '*' || *q == '?' || *q == '%')
3673 p += sprintf (p, "%%%.02x", *q);
3680 fontname = g_strdup_printf ("-%s-%s-%s-%s-%s-*-%s-%s-*-*-%s-*-%s",
3681 foundry, fam, weight, slant,
3682 set_width, pixel_size, point_size,
3684 #ifdef GDK_WINDOWING_WIN32
3692 /*****************************************************************************
3693 * GtkFontSelectionDialog
3694 *****************************************************************************/
3697 gtk_font_selection_dialog_get_type (void)
3699 static guint font_selection_dialog_type = 0;
3701 if (!font_selection_dialog_type)
3703 GtkTypeInfo fontsel_diag_info =
3705 "GtkFontSelectionDialog",
3706 sizeof (GtkFontSelectionDialog),
3707 sizeof (GtkFontSelectionDialogClass),
3708 (GtkClassInitFunc) gtk_font_selection_dialog_class_init,
3709 (GtkObjectInitFunc) gtk_font_selection_dialog_init,
3710 /* reserved_1 */ NULL,
3711 /* reserved_2 */ NULL,
3712 (GtkClassInitFunc) NULL,
3715 font_selection_dialog_type = gtk_type_unique (GTK_TYPE_WINDOW, &fontsel_diag_info);
3718 return font_selection_dialog_type;
3722 gtk_font_selection_dialog_class_init (GtkFontSelectionDialogClass *klass)
3724 GtkObjectClass *object_class;
3726 object_class = (GtkObjectClass*) klass;
3728 font_selection_dialog_parent_class = gtk_type_class (GTK_TYPE_WINDOW);
3732 gtk_font_selection_dialog_init (GtkFontSelectionDialog *fontseldiag)
3734 fontseldiag->dialog_width = -1;
3735 fontseldiag->auto_resize = TRUE;
3737 gtk_widget_set_events(GTK_WIDGET(fontseldiag), GDK_STRUCTURE_MASK);
3738 gtk_signal_connect (GTK_OBJECT (fontseldiag), "configure_event",
3739 (GtkSignalFunc) gtk_font_selection_dialog_on_configure,
3742 gtk_container_set_border_width (GTK_CONTAINER (fontseldiag), 4);
3743 gtk_window_set_policy(GTK_WINDOW(fontseldiag), FALSE, TRUE, TRUE);
3745 fontseldiag->main_vbox = gtk_vbox_new (FALSE, 4);
3746 gtk_widget_show (fontseldiag->main_vbox);
3747 gtk_container_add (GTK_CONTAINER (fontseldiag), fontseldiag->main_vbox);
3749 fontseldiag->fontsel = gtk_font_selection_new();
3750 gtk_widget_show (fontseldiag->fontsel);
3751 gtk_box_pack_start (GTK_BOX (fontseldiag->main_vbox),
3752 fontseldiag->fontsel, TRUE, TRUE, 0);
3754 /* Create the action area */
3755 fontseldiag->action_area = gtk_hbutton_box_new ();
3756 gtk_button_box_set_layout(GTK_BUTTON_BOX(fontseldiag->action_area),
3758 gtk_button_box_set_spacing(GTK_BUTTON_BOX(fontseldiag->action_area), 5);
3759 gtk_box_pack_start (GTK_BOX (fontseldiag->main_vbox),
3760 fontseldiag->action_area, FALSE, FALSE, 0);
3761 gtk_widget_show (fontseldiag->action_area);
3763 fontseldiag->ok_button = gtk_button_new_with_label(_("OK"));
3764 GTK_WIDGET_SET_FLAGS (fontseldiag->ok_button, GTK_CAN_DEFAULT);
3765 gtk_widget_show(fontseldiag->ok_button);
3766 gtk_box_pack_start (GTK_BOX (fontseldiag->action_area),
3767 fontseldiag->ok_button, TRUE, TRUE, 0);
3768 gtk_widget_grab_default (fontseldiag->ok_button);
3770 fontseldiag->apply_button = gtk_button_new_with_label(_("Apply"));
3771 GTK_WIDGET_SET_FLAGS (fontseldiag->apply_button, GTK_CAN_DEFAULT);
3772 /*gtk_widget_show(fontseldiag->apply_button);*/
3773 gtk_box_pack_start (GTK_BOX(fontseldiag->action_area),
3774 fontseldiag->apply_button, TRUE, TRUE, 0);
3776 fontseldiag->cancel_button = gtk_button_new_with_label(_("Cancel"));
3777 GTK_WIDGET_SET_FLAGS (fontseldiag->cancel_button, GTK_CAN_DEFAULT);
3778 gtk_widget_show(fontseldiag->cancel_button);
3779 gtk_box_pack_start (GTK_BOX(fontseldiag->action_area),
3780 fontseldiag->cancel_button, TRUE, TRUE, 0);
3786 gtk_font_selection_dialog_new (const gchar *title)
3788 GtkFontSelectionDialog *fontseldiag;
3790 fontseldiag = gtk_type_new (GTK_TYPE_FONT_SELECTION_DIALOG);
3791 gtk_window_set_title (GTK_WINDOW (fontseldiag),
3792 title ? title : _("Font Selection"));
3794 return GTK_WIDGET (fontseldiag);
3798 gtk_font_selection_dialog_get_font_name (GtkFontSelectionDialog *fsd)
3800 return gtk_font_selection_get_font_name(GTK_FONT_SELECTION(fsd->fontsel));
3804 gtk_font_selection_dialog_get_font (GtkFontSelectionDialog *fsd)
3806 return gtk_font_selection_get_font(GTK_FONT_SELECTION(fsd->fontsel));
3810 gtk_font_selection_dialog_set_font_name (GtkFontSelectionDialog *fsd,
3811 const gchar *fontname)
3813 return gtk_font_selection_set_font_name(GTK_FONT_SELECTION(fsd->fontsel),
3818 gtk_font_selection_dialog_set_filter (GtkFontSelectionDialog *fsd,
3819 GtkFontFilterType filter_type,
3820 GtkFontType font_type,
3828 gtk_font_selection_set_filter (GTK_FONT_SELECTION (fsd->fontsel),
3829 filter_type, font_type,
3830 foundries, weights, slants, setwidths,
3831 spacings, charsets);
3835 gtk_font_selection_dialog_get_preview_text (GtkFontSelectionDialog *fsd)
3837 return gtk_font_selection_get_preview_text(GTK_FONT_SELECTION(fsd->fontsel));
3841 gtk_font_selection_dialog_set_preview_text (GtkFontSelectionDialog *fsd,
3844 gtk_font_selection_set_preview_text(GTK_FONT_SELECTION(fsd->fontsel), text);
3848 /* This turns auto-shrink off if the user resizes the width of the dialog.
3849 It also turns it back on again if the user resizes it back to its normal
3852 gtk_font_selection_dialog_on_configure (GtkWidget *widget,
3853 GdkEventConfigure *event,
3854 GtkFontSelectionDialog *fsd)
3856 /* This sets the initial width. */
3857 if (fsd->dialog_width == -1)
3858 fsd->dialog_width = event->width;
3859 else if (fsd->auto_resize && fsd->dialog_width != event->width)
3861 fsd->auto_resize = FALSE;
3862 gtk_window_set_policy(GTK_WINDOW(fsd), FALSE, TRUE, FALSE);
3864 else if (!fsd->auto_resize && fsd->dialog_width == event->width)
3866 fsd->auto_resize = TRUE;
3867 gtk_window_set_policy(GTK_WINDOW(fsd), FALSE, TRUE, TRUE);