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 #if GDK_WINDOWING == GDK_WINDOWING_WIN32
75 # define CHARSET CHARSETstruct
78 #if GDK_WINDOWING == 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 #if GDK_WINDOWING == GDK_WINDOWING_WIN32
405 static char *logfont_to_xlfd (const LOGFONT *lfp,
411 static GtkWindowClass *font_selection_parent_class = NULL;
412 static GtkNotebookClass *font_selection_dialog_parent_class = NULL;
415 gtk_font_selection_get_type()
417 static GtkType font_selection_type = 0;
419 if(!font_selection_type)
421 static const GtkTypeInfo fontsel_type_info =
424 sizeof (GtkFontSelection),
425 sizeof (GtkFontSelectionClass),
426 (GtkClassInitFunc) gtk_font_selection_class_init,
427 (GtkObjectInitFunc) gtk_font_selection_init,
428 /* reserved_1 */ NULL,
429 /* reserved_2 */ NULL,
430 (GtkClassInitFunc) NULL,
433 font_selection_type = gtk_type_unique (GTK_TYPE_NOTEBOOK,
437 return font_selection_type;
441 gtk_font_selection_class_init(GtkFontSelectionClass *klass)
443 GtkObjectClass *object_class;
445 object_class = (GtkObjectClass *) klass;
447 font_selection_parent_class = gtk_type_class (GTK_TYPE_NOTEBOOK);
449 object_class->destroy = gtk_font_selection_destroy;
451 gtk_font_selection_get_fonts ();
455 gtk_font_selection_init(GtkFontSelection *fontsel)
457 GtkWidget *scrolled_win;
458 GtkWidget *text_frame;
459 GtkWidget *text_box, *frame;
460 GtkWidget *table, *label, *hbox, *hbox2, *clist, *button, *vbox, *alignment;
462 gchar *titles[] = { NULL, NULL, NULL };
467 gchar *property, *text;
470 /* Number of internationalized titles here must match number
471 of NULL initializers above */
472 titles[0] = _("Font Property");
473 titles[1] = _("Requested Value");
474 titles[2] = _("Actual Value");
476 /* Initialize the GtkFontSelection struct. We do this here in case any
477 callbacks are triggered while creating the interface. */
478 fontsel->font = NULL;
479 fontsel->font_index = -1;
481 fontsel->metric = INITIAL_METRIC;
482 fontsel->size = INITIAL_FONT_SIZE;
483 fontsel->selected_size = INITIAL_FONT_SIZE;
485 fontsel->filters[GTK_FONT_FILTER_BASE].font_type = GTK_FONT_ALL;
486 fontsel->filters[GTK_FONT_FILTER_USER].font_type = GTK_FONT_BITMAP
490 for (prop = 0; prop < GTK_NUM_FONT_PROPERTIES; prop++)
492 fontsel->filters[GTK_FONT_FILTER_BASE].property_filters[prop] = NULL;
493 fontsel->filters[GTK_FONT_FILTER_BASE].property_nfilters[prop] = 0;
494 fontsel->filters[GTK_FONT_FILTER_USER].property_filters[prop] = NULL;
495 fontsel->filters[GTK_FONT_FILTER_USER].property_nfilters[prop] = 0;
498 for (prop = 0; prop < GTK_NUM_STYLE_PROPERTIES; prop++)
499 fontsel->property_values[prop] = 0;
501 /* Create the main notebook page. */
502 gtk_notebook_set_homogeneous_tabs (GTK_NOTEBOOK (fontsel), TRUE);
503 gtk_notebook_set_tab_hborder (GTK_NOTEBOOK (fontsel), 8);
504 fontsel->main_vbox = gtk_vbox_new (FALSE, 4);
505 gtk_widget_show (fontsel->main_vbox);
506 gtk_container_set_border_width (GTK_CONTAINER (fontsel->main_vbox), 6);
507 label = gtk_label_new(_("Font"));
508 gtk_notebook_append_page (GTK_NOTEBOOK (fontsel),
509 fontsel->main_vbox, label);
511 /* Create the table of font, style & size. */
512 table = gtk_table_new (3, 3, FALSE);
513 gtk_widget_show (table);
514 gtk_table_set_col_spacings(GTK_TABLE(table), 8);
515 gtk_box_pack_start (GTK_BOX (fontsel->main_vbox), table, TRUE, TRUE, 0);
517 fontsel->font_label = gtk_label_new(_("Font:"));
518 gtk_misc_set_alignment (GTK_MISC (fontsel->font_label), 0.0, 0.5);
519 gtk_widget_show (fontsel->font_label);
520 gtk_table_attach (GTK_TABLE (table), fontsel->font_label, 0, 1, 0, 1,
522 label = gtk_label_new(_("Font Style:"));
523 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
524 gtk_widget_show (label);
525 gtk_table_attach (GTK_TABLE (table), label, 1, 2, 0, 1,
527 label = gtk_label_new(_("Size:"));
528 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
529 gtk_widget_show (label);
530 gtk_table_attach (GTK_TABLE (table), label, 2, 3, 0, 1,
533 fontsel->font_entry = gtk_entry_new();
534 gtk_entry_set_editable(GTK_ENTRY(fontsel->font_entry), FALSE);
535 gtk_widget_set_usize (fontsel->font_entry, 20, -1);
536 gtk_widget_show (fontsel->font_entry);
537 gtk_table_attach (GTK_TABLE (table), fontsel->font_entry, 0, 1, 1, 2,
539 fontsel->font_style_entry = gtk_entry_new();
540 gtk_entry_set_editable(GTK_ENTRY(fontsel->font_style_entry), FALSE);
541 gtk_widget_set_usize (fontsel->font_style_entry, 20, -1);
542 gtk_widget_show (fontsel->font_style_entry);
543 gtk_table_attach (GTK_TABLE (table), fontsel->font_style_entry, 1, 2, 1, 2,
545 fontsel->size_entry = gtk_entry_new();
546 gtk_widget_set_usize (fontsel->size_entry, 20, -1);
547 gtk_widget_show (fontsel->size_entry);
548 gtk_table_attach (GTK_TABLE (table), fontsel->size_entry, 2, 3, 1, 2,
550 gtk_signal_connect (GTK_OBJECT (fontsel->size_entry), "key_press_event",
551 (GtkSignalFunc) gtk_font_selection_size_key_press,
554 /* Create the clists */
555 fontsel->font_clist = gtk_clist_new(1);
556 gtk_clist_column_titles_hide (GTK_CLIST(fontsel->font_clist));
557 gtk_clist_set_column_auto_resize (GTK_CLIST (fontsel->font_clist), 0, TRUE);
558 scrolled_win = gtk_scrolled_window_new (NULL, NULL);
559 gtk_widget_set_usize (scrolled_win, FONT_LIST_WIDTH, FONT_LIST_HEIGHT);
560 gtk_container_add (GTK_CONTAINER (scrolled_win), fontsel->font_clist);
561 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
562 GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
563 gtk_widget_show(fontsel->font_clist);
564 gtk_widget_show(scrolled_win);
566 gtk_table_attach (GTK_TABLE (table), scrolled_win, 0, 1, 2, 3,
567 GTK_EXPAND | GTK_FILL,
568 GTK_EXPAND | GTK_FILL, 0, 0);
570 fontsel->font_style_clist = gtk_clist_new(1);
571 gtk_clist_column_titles_hide (GTK_CLIST(fontsel->font_style_clist));
572 gtk_clist_set_column_auto_resize (GTK_CLIST (fontsel->font_style_clist),
574 scrolled_win = gtk_scrolled_window_new (NULL, NULL);
575 gtk_widget_set_usize (scrolled_win, FONT_STYLE_LIST_WIDTH, -1);
576 gtk_container_add (GTK_CONTAINER (scrolled_win), fontsel->font_style_clist);
577 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
578 GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
579 gtk_widget_show(fontsel->font_style_clist);
580 gtk_widget_show(scrolled_win);
581 gtk_table_attach (GTK_TABLE (table), scrolled_win, 1, 2, 2, 3,
582 GTK_EXPAND | GTK_FILL,
583 GTK_EXPAND | GTK_FILL, 0, 0);
585 fontsel->size_clist = gtk_clist_new(1);
586 gtk_clist_column_titles_hide (GTK_CLIST(fontsel->size_clist));
587 gtk_clist_set_column_width (GTK_CLIST(fontsel->size_clist), 0, 20);
588 scrolled_win = gtk_scrolled_window_new (NULL, NULL);
589 gtk_widget_set_usize (scrolled_win, FONT_SIZE_LIST_WIDTH, -1);
590 gtk_container_add (GTK_CONTAINER (scrolled_win), fontsel->size_clist);
591 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
592 GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
593 gtk_widget_show(fontsel->size_clist);
594 gtk_widget_show(scrolled_win);
595 gtk_table_attach (GTK_TABLE (table), scrolled_win, 2, 3, 2, 3,
596 GTK_FILL, GTK_FILL, 0, 0);
599 /* Insert the fonts. If there exist fonts with the same family but
600 different foundries, then the foundry name is appended in brackets. */
601 gtk_font_selection_show_available_fonts(fontsel);
603 gtk_signal_connect (GTK_OBJECT (fontsel->font_clist), "select_row",
604 GTK_SIGNAL_FUNC(gtk_font_selection_select_font),
606 GTK_WIDGET_SET_FLAGS (fontsel->font_clist, GTK_CAN_FOCUS);
607 gtk_signal_connect (GTK_OBJECT (fontsel->font_clist), "key_press_event",
608 GTK_SIGNAL_FUNC(gtk_font_selection_on_clist_key_press),
610 gtk_signal_connect_after (GTK_OBJECT (fontsel->font_clist), "expose_event",
611 GTK_SIGNAL_FUNC(gtk_font_selection_expose_list),
614 gtk_signal_connect (GTK_OBJECT (fontsel->font_style_clist), "select_row",
615 GTK_SIGNAL_FUNC(gtk_font_selection_select_style),
617 GTK_WIDGET_SET_FLAGS (fontsel->font_style_clist, GTK_CAN_FOCUS);
618 gtk_signal_connect (GTK_OBJECT (fontsel->font_style_clist),
620 GTK_SIGNAL_FUNC(gtk_font_selection_on_clist_key_press),
622 gtk_signal_connect_after (GTK_OBJECT (fontsel->font_style_clist),
624 GTK_SIGNAL_FUNC(gtk_font_selection_realize_list),
627 /* Insert the standard font sizes */
628 gtk_clist_freeze (GTK_CLIST(fontsel->size_clist));
629 size_to_match = INITIAL_FONT_SIZE;
630 if (INITIAL_METRIC == GTK_FONT_METRIC_POINTS)
631 size_to_match = size_to_match / 10;
632 for (i = 0; i < sizeof(font_sizes) / sizeof(font_sizes[0]); i++)
634 sprintf(buffer, "%i", font_sizes[i]);
636 gtk_clist_append(GTK_CLIST(fontsel->size_clist), &size);
637 if (font_sizes[i] == size_to_match)
639 gtk_clist_select_row(GTK_CLIST(fontsel->size_clist), i, 0);
640 gtk_entry_set_text(GTK_ENTRY(fontsel->size_entry), buffer);
643 gtk_clist_thaw (GTK_CLIST(fontsel->size_clist));
645 gtk_signal_connect (GTK_OBJECT (fontsel->size_clist), "select_row",
646 GTK_SIGNAL_FUNC(gtk_font_selection_select_size),
648 GTK_WIDGET_SET_FLAGS (fontsel->size_clist, GTK_CAN_FOCUS);
649 gtk_signal_connect (GTK_OBJECT (fontsel->size_clist), "key_press_event",
650 GTK_SIGNAL_FUNC(gtk_font_selection_on_clist_key_press),
654 /* create the Reset Filter & Metric buttons */
655 hbox = gtk_hbox_new(FALSE, 8);
656 gtk_widget_show (hbox);
657 gtk_box_pack_start (GTK_BOX (fontsel->main_vbox), hbox, FALSE, TRUE, 0);
659 fontsel->filter_button = gtk_button_new_with_label(_("Reset Filter"));
660 gtk_misc_set_padding (GTK_MISC (GTK_BIN (fontsel->filter_button)->child),
662 gtk_widget_show(fontsel->filter_button);
663 gtk_box_pack_start (GTK_BOX (hbox), fontsel->filter_button, FALSE, FALSE, 0);
664 gtk_widget_set_sensitive (fontsel->filter_button, FALSE);
665 gtk_signal_connect (GTK_OBJECT (fontsel->filter_button), "clicked",
666 GTK_SIGNAL_FUNC(gtk_font_selection_on_clear_filter),
669 hbox2 = gtk_hbox_new(FALSE, 0);
670 gtk_widget_show (hbox2);
671 gtk_box_pack_end (GTK_BOX (hbox), hbox2, FALSE, FALSE, 0);
673 label = gtk_label_new(_("Metric:"));
674 gtk_widget_show (label);
675 gtk_box_pack_start (GTK_BOX (hbox2), label, FALSE, TRUE, 8);
677 fontsel->points_button = gtk_radio_button_new_with_label(NULL, _("Points"));
678 gtk_widget_show (fontsel->points_button);
679 gtk_box_pack_start (GTK_BOX (hbox2), fontsel->points_button, FALSE, TRUE, 0);
680 if (INITIAL_METRIC == GTK_FONT_METRIC_POINTS)
681 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(fontsel->points_button),
684 fontsel->pixels_button = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(fontsel->points_button), _("Pixels"));
685 gtk_widget_show (fontsel->pixels_button);
686 gtk_box_pack_start (GTK_BOX (hbox2), fontsel->pixels_button, FALSE, TRUE, 0);
687 if (INITIAL_METRIC == GTK_FONT_METRIC_PIXELS)
688 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(fontsel->pixels_button),
691 gtk_signal_connect(GTK_OBJECT(fontsel->points_button), "toggled",
692 (GtkSignalFunc) gtk_font_selection_metric_callback,
694 gtk_signal_connect(GTK_OBJECT(fontsel->pixels_button), "toggled",
695 (GtkSignalFunc) gtk_font_selection_metric_callback,
699 /* create the text entry widget */
700 text_frame = gtk_frame_new (_("Preview:"));
701 gtk_widget_show (text_frame);
702 gtk_frame_set_shadow_type(GTK_FRAME(text_frame), GTK_SHADOW_ETCHED_IN);
703 gtk_box_pack_start (GTK_BOX (fontsel->main_vbox), text_frame,
706 /* This is just used to get a 4-pixel space around the preview entry. */
707 text_box = gtk_hbox_new (FALSE, 0);
708 gtk_widget_show (text_box);
709 gtk_container_add (GTK_CONTAINER (text_frame), text_box);
710 gtk_container_set_border_width (GTK_CONTAINER (text_box), 4);
712 fontsel->preview_entry = gtk_entry_new ();
713 gtk_widget_show (fontsel->preview_entry);
714 gtk_widget_set_usize (fontsel->preview_entry, -1, INITIAL_PREVIEW_HEIGHT);
715 gtk_box_pack_start (GTK_BOX (text_box), fontsel->preview_entry,
718 /* Create the message area */
719 fontsel->message_label = gtk_label_new("");
720 gtk_widget_show (fontsel->message_label);
721 gtk_box_pack_start (GTK_BOX (fontsel->main_vbox), fontsel->message_label,
725 /* Create the font info page */
726 fontsel->info_vbox = gtk_vbox_new (FALSE, 4);
727 gtk_widget_show (fontsel->info_vbox);
728 gtk_container_set_border_width (GTK_CONTAINER (fontsel->info_vbox), 2);
729 label = gtk_label_new(_("Font Information"));
730 gtk_notebook_append_page (GTK_NOTEBOOK (fontsel),
731 fontsel->info_vbox, label);
733 fontsel->info_clist = gtk_clist_new_with_titles (3, titles);
734 gtk_widget_set_usize (fontsel->info_clist, 390, 150);
735 gtk_clist_set_column_width(GTK_CLIST(fontsel->info_clist), 0, 130);
736 gtk_clist_set_column_width(GTK_CLIST(fontsel->info_clist), 1, 130);
737 gtk_clist_set_column_width(GTK_CLIST(fontsel->info_clist), 2, 130);
738 gtk_clist_column_titles_passive(GTK_CLIST(fontsel->info_clist));
739 scrolled_win = gtk_scrolled_window_new (NULL, NULL);
740 gtk_container_add (GTK_CONTAINER (scrolled_win), fontsel->info_clist);
741 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
742 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
743 gtk_widget_show(fontsel->info_clist);
744 gtk_widget_show(scrolled_win);
745 gtk_box_pack_start (GTK_BOX (fontsel->info_vbox), scrolled_win,
748 /* Insert the property names */
749 gtk_clist_freeze (GTK_CLIST(fontsel->info_clist));
752 for (i = 0; i < GTK_XLFD_NUM_FIELDS; i++)
754 row_text[0] = _(xlfd_field_names[i]);
755 gtk_clist_append(GTK_CLIST(fontsel->info_clist), row_text);
756 gtk_clist_set_shift(GTK_CLIST(fontsel->info_clist), i, 0, 0, 4);
757 gtk_clist_set_shift(GTK_CLIST(fontsel->info_clist), i, 1, 0, 4);
758 gtk_clist_set_shift(GTK_CLIST(fontsel->info_clist), i, 2, 0, 4);
760 gtk_clist_thaw (GTK_CLIST(fontsel->info_clist));
762 label = gtk_label_new(_("Requested Font Name:"));
763 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
764 gtk_widget_show (label);
765 gtk_box_pack_start (GTK_BOX (fontsel->info_vbox), label, FALSE, TRUE, 0);
767 fontsel->requested_font_name = gtk_entry_new();
768 gtk_entry_set_editable(GTK_ENTRY(fontsel->requested_font_name), FALSE);
769 gtk_widget_show (fontsel->requested_font_name);
770 gtk_box_pack_start (GTK_BOX (fontsel->info_vbox),
771 fontsel->requested_font_name, FALSE, TRUE, 0);
773 label = gtk_label_new(_("Actual Font Name:"));
774 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
775 gtk_widget_show (label);
776 gtk_box_pack_start (GTK_BOX (fontsel->info_vbox), label, FALSE, TRUE, 0);
778 fontsel->actual_font_name = gtk_entry_new();
779 gtk_entry_set_editable(GTK_ENTRY(fontsel->actual_font_name), FALSE);
780 gtk_widget_show (fontsel->actual_font_name);
781 gtk_box_pack_start (GTK_BOX (fontsel->info_vbox),
782 fontsel->actual_font_name, FALSE, TRUE, 0);
784 sprintf(buffer, _("%i fonts available with a total of %i styles."),
785 fontsel_info->nfonts, fontsel_info->nstyles);
786 label = gtk_label_new(buffer);
787 gtk_widget_show (label);
788 gtk_box_pack_start (GTK_BOX (fontsel->info_vbox), label, FALSE, FALSE, 0);
790 gtk_signal_connect (GTK_OBJECT (fontsel), "switch_page",
791 GTK_SIGNAL_FUNC(gtk_font_selection_switch_page),
795 /* Create the Filter page. */
796 fontsel->filter_vbox = gtk_vbox_new (FALSE, 4);
797 gtk_widget_show (fontsel->filter_vbox);
798 gtk_container_set_border_width (GTK_CONTAINER (fontsel->filter_vbox), 2);
799 label = gtk_label_new(_("Filter"));
800 gtk_notebook_append_page (GTK_NOTEBOOK (fontsel),
801 fontsel->filter_vbox, label);
803 /* Create the font type checkbuttons. */
804 frame = gtk_frame_new (NULL);
805 gtk_widget_show (frame);
806 gtk_box_pack_start (GTK_BOX (fontsel->filter_vbox), frame, FALSE, TRUE, 0);
808 hbox = gtk_hbox_new (FALSE, 20);
809 gtk_widget_show (hbox);
810 gtk_container_add (GTK_CONTAINER (frame), hbox);
812 label = gtk_label_new(_("Font Types:"));
813 gtk_widget_show (label);
814 gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 10);
816 hbox2 = gtk_hbox_new (TRUE, 0);
817 gtk_widget_show (hbox2);
818 gtk_box_pack_start (GTK_BOX (hbox), hbox2, FALSE, TRUE, 0);
820 fontsel->type_bitmaps_button = gtk_check_button_new_with_label (_("Bitmap"));
821 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fontsel->type_bitmaps_button), TRUE);
822 gtk_widget_show (fontsel->type_bitmaps_button);
823 gtk_box_pack_start (GTK_BOX (hbox2), fontsel->type_bitmaps_button,
826 fontsel->type_scalable_button = gtk_check_button_new_with_label (_("Scalable"));
827 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fontsel->type_scalable_button), TRUE);
828 gtk_widget_show (fontsel->type_scalable_button);
829 gtk_box_pack_start (GTK_BOX (hbox2), fontsel->type_scalable_button,
832 fontsel->type_scaled_bitmaps_button = gtk_check_button_new_with_label (_("Scaled Bitmap"));
833 gtk_widget_show (fontsel->type_scaled_bitmaps_button);
834 gtk_box_pack_start (GTK_BOX (hbox2), fontsel->type_scaled_bitmaps_button,
837 table = gtk_table_new (4, 3, FALSE);
838 gtk_table_set_col_spacings(GTK_TABLE(table), 2);
839 gtk_widget_show (table);
840 gtk_box_pack_start (GTK_BOX (fontsel->filter_vbox), table, TRUE, TRUE, 0);
842 for (prop = 0; prop < GTK_NUM_FONT_PROPERTIES; prop++)
844 gint left = filter_positions[prop][0];
845 gint top = filter_positions[prop][1];
847 label = gtk_label_new(_(xlfd_field_names[xlfd_index[prop]]));
848 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 1.0);
849 gtk_misc_set_padding (GTK_MISC (label), 0, 2);
850 gtk_widget_show(label);
851 gtk_table_attach (GTK_TABLE (table), label, left, left + 1,
852 top, top + 1, GTK_FILL, GTK_FILL, 0, 0);
854 clist = gtk_clist_new(1);
855 gtk_widget_set_usize (clist, 100, filter_heights[prop]);
856 gtk_clist_set_selection_mode(GTK_CLIST(clist), GTK_SELECTION_MULTIPLE);
857 gtk_clist_column_titles_hide(GTK_CLIST(clist));
858 gtk_clist_set_column_auto_resize (GTK_CLIST (clist), 0, TRUE);
859 scrolled_win = gtk_scrolled_window_new (NULL, NULL);
860 gtk_container_add (GTK_CONTAINER (scrolled_win), clist);
861 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
862 GTK_POLICY_AUTOMATIC,
863 GTK_POLICY_AUTOMATIC);
864 gtk_widget_show(clist);
865 gtk_widget_show(scrolled_win);
867 /* For the bottom-right cell we add the 'Reset Filter' button. */
868 if (top == 2 && left == 2)
870 vbox = gtk_vbox_new(FALSE, 0);
871 gtk_widget_show(vbox);
872 gtk_table_attach (GTK_TABLE (table), vbox, left, left + 1,
873 top + 1, top + 2, GTK_FILL, GTK_FILL, 0, 0);
875 gtk_box_pack_start (GTK_BOX (vbox), scrolled_win, TRUE, TRUE, 0);
877 alignment = gtk_alignment_new(0.5, 0.0, 0.8, 0.0);
878 gtk_widget_show(alignment);
879 gtk_box_pack_start (GTK_BOX (vbox), alignment, FALSE, TRUE, 4);
881 button = gtk_button_new_with_label(_("Reset Filter"));
882 gtk_widget_show(button);
883 gtk_container_add(GTK_CONTAINER(alignment), button);
884 gtk_signal_connect (GTK_OBJECT (button), "clicked",
885 GTK_SIGNAL_FUNC(gtk_font_selection_reset_filter),
889 gtk_table_attach (GTK_TABLE (table), scrolled_win,
890 left, left + 1, top + 1, top + 2,
891 GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
893 gtk_signal_connect (GTK_OBJECT (clist), "select_row",
894 GTK_SIGNAL_FUNC(gtk_font_selection_select_filter),
896 gtk_signal_connect (GTK_OBJECT (clist), "unselect_row",
897 GTK_SIGNAL_FUNC(gtk_font_selection_unselect_filter),
900 /* Insert the property names, expanded, and in sorted order.
901 But we make sure that the wildcard '*' is first. */
902 gtk_clist_freeze (GTK_CLIST(clist));
904 gtk_clist_append(GTK_CLIST(clist), &property);
906 for (i = 1; i < fontsel_info->nproperties[prop]; i++) {
907 property = _(fontsel_info->properties[prop][i]);
909 property = gtk_font_selection_expand_slant_code(property);
910 else if (prop == SPACING)
911 property = gtk_font_selection_expand_spacing_code(property);
914 for (row = 1; row < GTK_CLIST(clist)->rows; row++)
916 gtk_clist_get_text(GTK_CLIST(clist), row, 0, &text);
917 if (strcmp(property, text) < 0)
920 gtk_clist_insert(GTK_CLIST(clist), row, &property);
925 row = gtk_clist_append(GTK_CLIST(clist), &property);
926 gtk_clist_set_row_data(GTK_CLIST(clist), row, GINT_TO_POINTER (i));
928 gtk_clist_select_row(GTK_CLIST(clist), 0, 0);
929 gtk_clist_thaw (GTK_CLIST(clist));
930 fontsel->filter_clists[prop] = clist;
935 gtk_font_selection_new()
937 GtkFontSelection *fontsel;
939 fontsel = gtk_type_new (GTK_TYPE_FONT_SELECTION);
941 return GTK_WIDGET (fontsel);
945 gtk_font_selection_destroy (GtkObject *object)
947 GtkFontSelection *fontsel;
949 g_return_if_fail (object != NULL);
950 g_return_if_fail (GTK_IS_FONT_SELECTION (object));
952 fontsel = GTK_FONT_SELECTION (object);
954 /* All we have to do is unref the font, if we have one. */
956 gdk_font_unref (fontsel->font);
958 if (GTK_OBJECT_CLASS (font_selection_parent_class)->destroy)
959 (* GTK_OBJECT_CLASS (font_selection_parent_class)->destroy) (object);
963 /* This is called when the clist is exposed. Here we scroll to the current
964 font if necessary. */
966 gtk_font_selection_expose_list (GtkWidget *widget,
967 GdkEventExpose *event,
970 GtkFontSelection *fontsel;
976 g_message("In expose_list\n");
978 fontsel = GTK_FONT_SELECTION(data);
980 font_info = fontsel_info->font_info;
982 /* Try to scroll the font family clist to the selected item */
983 selection = GTK_CLIST(fontsel->font_clist)->selection;
986 index = GPOINTER_TO_INT (selection->data);
987 if (gtk_clist_row_is_visible(GTK_CLIST(fontsel->font_clist), index)
988 != GTK_VISIBILITY_FULL)
989 gtk_clist_moveto(GTK_CLIST(fontsel->font_clist), index, -1, 0.5, 0);
992 /* Try to scroll the font style clist to the selected item */
993 selection = GTK_CLIST(fontsel->font_style_clist)->selection;
996 index = GPOINTER_TO_INT (selection->data);
997 if (gtk_clist_row_is_visible(GTK_CLIST(fontsel->font_style_clist), index)
998 != GTK_VISIBILITY_FULL)
999 gtk_clist_moveto(GTK_CLIST(fontsel->font_style_clist), index, -1,
1003 /* Try to scroll the font size clist to the selected item */
1004 selection = GTK_CLIST(fontsel->size_clist)->selection;
1007 index = GPOINTER_TO_INT (selection->data);
1008 if (gtk_clist_row_is_visible(GTK_CLIST(fontsel->size_clist), index)
1009 != GTK_VISIBILITY_FULL)
1010 gtk_clist_moveto(GTK_CLIST(fontsel->size_clist), index, -1, 0.5, 0);
1015 /* This is called when the style clist is realized. We need to set any
1016 charset rows to insensitive colours. */
1018 gtk_font_selection_realize_list (GtkWidget *widget,
1021 GtkFontSelection *fontsel;
1023 GdkColor *inactive_fg, *inactive_bg;
1025 #ifdef FONTSEL_DEBUG
1026 g_message("In realize_list\n");
1028 fontsel = GTK_FONT_SELECTION (data);
1030 /* Set the colours for any charset rows to insensitive. */
1031 inactive_fg = &fontsel->font_style_clist->style->fg[GTK_STATE_INSENSITIVE];
1032 inactive_bg = &fontsel->font_style_clist->style->bg[GTK_STATE_INSENSITIVE];
1034 for (row = 0; row < GTK_CLIST (fontsel->font_style_clist)->rows; row++)
1036 if (GPOINTER_TO_INT (gtk_clist_get_row_data (GTK_CLIST (fontsel->font_style_clist), row)) == -1)
1038 gtk_clist_set_foreground (GTK_CLIST (fontsel->font_style_clist),
1040 gtk_clist_set_background (GTK_CLIST (fontsel->font_style_clist),
1047 /* This is called when a family is selected in the list. */
1049 gtk_font_selection_select_font (GtkWidget *w,
1052 GdkEventButton *bevent,
1055 GtkFontSelection *fontsel;
1056 FontInfo *font_info;
1059 #ifdef FONTSEL_DEBUG
1060 g_message("In select_font\n");
1062 fontsel = GTK_FONT_SELECTION(data);
1063 font_info = fontsel_info->font_info;
1065 if (bevent && !GTK_WIDGET_HAS_FOCUS (w))
1066 gtk_widget_grab_focus (w);
1068 row = GPOINTER_TO_INT (gtk_clist_get_row_data (GTK_CLIST (fontsel->font_clist), row));
1069 font = &font_info[row];
1070 gtk_entry_set_text(GTK_ENTRY(fontsel->font_entry), font->family);
1072 /* If it is already the current font, just return. */
1073 if (fontsel->font_index == row)
1076 fontsel->font_index = row;
1077 gtk_font_selection_show_available_styles (fontsel);
1078 gtk_font_selection_select_best_style (fontsel, TRUE);
1083 gtk_font_selection_on_clist_key_press (GtkWidget *clist,
1085 GtkFontSelection *fontsel)
1087 #ifdef FONTSEL_DEBUG
1088 g_message("In on_clist_key_press\n");
1090 if (event->keyval == GDK_Up)
1091 return gtk_font_selection_select_next (fontsel, clist, -1);
1092 else if (event->keyval == GDK_Down)
1093 return gtk_font_selection_select_next (fontsel, clist, 1);
1100 gtk_font_selection_select_next (GtkFontSelection *fontsel,
1105 gint current_row, row;
1107 selection = GTK_CLIST(clist)->selection;
1110 current_row = GPOINTER_TO_INT (selection->data);
1112 /* Stop the normal clist key handler from being run. */
1113 gtk_signal_emit_stop_by_name (GTK_OBJECT (clist), "key_press_event");
1115 for (row = current_row + step;
1116 row >= 0 && row < GTK_CLIST(clist)->rows;
1119 /* If this is the style clist, make sure that the item is not a charset
1121 if (clist == fontsel->font_style_clist)
1122 if (GPOINTER_TO_INT (gtk_clist_get_row_data(GTK_CLIST(clist), row)) == -1)
1125 /* Now we've found the row to select. */
1126 if (gtk_clist_row_is_visible(GTK_CLIST(clist), row)
1127 != GTK_VISIBILITY_FULL)
1128 gtk_clist_moveto(GTK_CLIST(clist), row, -1, (step < 0) ? 0 : 1, 0);
1129 gtk_clist_select_row(GTK_CLIST(clist), row, 0);
1136 /* This fills the font style clist with all the possible style combinations
1137 for the current font family. */
1139 gtk_font_selection_show_available_styles (GtkFontSelection *fontsel)
1143 gint style, tmpstyle, row;
1144 gint weight_index, slant_index, set_width_index, spacing_index;
1146 gchar *weight, *slant, *set_width, *spacing;
1147 gchar *charset = NULL;
1149 gchar buffer[XLFD_MAX_FIELD_LEN * 6 + 2];
1150 GdkColor *inactive_fg, *inactive_bg;
1151 gboolean show_charset;
1153 #ifdef FONTSEL_DEBUG
1154 g_message("In show_available_styles\n");
1156 font = &fontsel_info->font_info[fontsel->font_index];
1157 styles = &fontsel_info->font_styles[font->style_index];
1159 gtk_clist_freeze (GTK_CLIST(fontsel->font_style_clist));
1160 gtk_clist_clear (GTK_CLIST(fontsel->font_style_clist));
1162 /* First we mark all visible styles as not having been displayed yet,
1163 and check if every style has the same charset. If not then we will
1164 display the charset in the list before the styles. */
1165 show_charset = FALSE;
1167 for (style = 0; style < font->nstyles; style++)
1169 if (gtk_font_selection_style_visible(fontsel, font, style))
1171 styles[style].flags &= ~GTK_FONT_DISPLAYED;
1173 if (charset_index == -1)
1174 charset_index = styles[style].properties[CHARSET];
1175 else if (charset_index != styles[style].properties[CHARSET])
1176 show_charset = TRUE;
1179 styles[style].flags |= GTK_FONT_DISPLAYED;
1182 /* Step through the undisplayed styles, finding the next charset which
1183 hasn't been displayed yet. Then display the charset on one line, if
1184 necessary, and the visible styles indented beneath it. */
1185 inactive_fg = &fontsel->font_style_clist->style->fg[GTK_STATE_INSENSITIVE];
1186 inactive_bg = &fontsel->font_style_clist->style->bg[GTK_STATE_INSENSITIVE];
1188 for (style = 0; style < font->nstyles; style++)
1190 if (styles[style].flags & GTK_FONT_DISPLAYED)
1195 charset_index = styles[style].properties[CHARSET];
1196 charset = fontsel_info->properties[CHARSET] [charset_index];
1197 row = gtk_clist_append(GTK_CLIST(fontsel->font_style_clist),
1199 gtk_clist_set_row_data(GTK_CLIST(fontsel->font_style_clist), row,
1201 if (GTK_WIDGET_REALIZED (fontsel->font_style_clist))
1203 gtk_clist_set_foreground(GTK_CLIST(fontsel->font_style_clist),
1205 gtk_clist_set_background(GTK_CLIST(fontsel->font_style_clist),
1210 for (tmpstyle = style; tmpstyle < font->nstyles; tmpstyle++)
1212 if (styles[tmpstyle].flags & GTK_FONT_DISPLAYED
1213 || charset_index != styles[tmpstyle].properties[CHARSET])
1216 styles[tmpstyle].flags |= GTK_FONT_DISPLAYED;
1218 weight_index = styles[tmpstyle].properties[WEIGHT];
1219 slant_index = styles[tmpstyle].properties[SLANT];
1220 set_width_index = styles[tmpstyle].properties[SET_WIDTH];
1221 spacing_index = styles[tmpstyle].properties[SPACING];
1222 weight = fontsel_info->properties[WEIGHT] [weight_index];
1223 slant = fontsel_info->properties[SLANT] [slant_index];
1224 set_width = fontsel_info->properties[SET_WIDTH][set_width_index];
1225 spacing = fontsel_info->properties[SPACING] [spacing_index];
1227 /* Convert '(nil)' weights to 'regular', since it looks nicer. */
1228 if (!g_strcasecmp(weight, N_("(nil)"))) weight = N_("regular");
1230 /* We don't show default values or (nil) in the other properties. */
1231 if (!g_strcasecmp(slant, "r")) slant = NULL;
1232 else if (!g_strcasecmp(slant, "(nil)")) slant = NULL;
1233 else if (!g_strcasecmp(slant, "i")) slant = N_("italic");
1234 else if (!g_strcasecmp(slant, "o")) slant = N_("oblique");
1235 else if (!g_strcasecmp(slant, "ri")) slant = N_("reverse italic");
1236 else if (!g_strcasecmp(slant, "ro")) slant = N_("reverse oblique");
1237 else if (!g_strcasecmp(slant, "ot")) slant = N_("other");
1239 if (!g_strcasecmp(set_width, "normal")) set_width = NULL;
1240 else if (!g_strcasecmp(set_width, "(nil)")) set_width = NULL;
1242 if (!g_strcasecmp(spacing, "p")) spacing = NULL;
1243 else if (!g_strcasecmp(spacing, "(nil)")) spacing = NULL;
1244 else if (!g_strcasecmp(spacing, "m")) spacing = N_("[M]");
1245 else if (!g_strcasecmp(spacing, "c")) spacing = N_("[C]");
1247 /* Add the strings together, making sure there is 1 space between
1249 strcpy(buffer, _(weight));
1252 strcat(buffer, " ");
1253 strcat(buffer, _(slant));
1257 strcat(buffer, " ");
1258 strcat(buffer, _(set_width));
1262 strcat(buffer, " ");
1263 strcat(buffer, _(spacing));
1267 row = gtk_clist_append(GTK_CLIST(fontsel->font_style_clist),
1270 gtk_clist_set_shift(GTK_CLIST(fontsel->font_style_clist), row, 0,
1272 gtk_clist_set_row_data(GTK_CLIST(fontsel->font_style_clist), row,
1273 GINT_TO_POINTER (tmpstyle));
1277 gtk_clist_thaw (GTK_CLIST(fontsel->font_style_clist));
1281 /* This selects a style when the user selects a font. It just uses the first
1282 available style at present. I was thinking of trying to maintain the
1283 selected style, e.g. bold italic, when the user selects different fonts.
1284 However, the interface is so easy to use now I'm not sure it's worth it.
1285 Note: This will load a font. */
1287 gtk_font_selection_select_best_style(GtkFontSelection *fontsel,
1292 gint row, prop, style, matched;
1293 gint best_matched = -1, best_style = -1, best_row = -1;
1295 #ifdef FONTSEL_DEBUG
1296 g_message("In select_best_style\n");
1298 font = &fontsel_info->font_info[fontsel->font_index];
1299 styles = &fontsel_info->font_styles[font->style_index];
1301 for (row = 0; row < GTK_CLIST(fontsel->font_style_clist)->rows; row++)
1303 style = GPOINTER_TO_INT (gtk_clist_get_row_data (GTK_CLIST (fontsel->font_style_clist), row));
1304 /* Skip charset rows. */
1308 /* If we just want the first style, we've got it. */
1317 for (prop = 0; prop < GTK_NUM_STYLE_PROPERTIES; prop++)
1319 if (fontsel->property_values[prop] == styles[style].properties[prop])
1322 if (matched > best_matched)
1324 best_matched = matched;
1329 g_return_if_fail (best_style != -1);
1330 g_return_if_fail (best_row != -1);
1332 fontsel->style = best_style;
1334 for (prop = 0; prop < GTK_NUM_STYLE_PROPERTIES; prop++)
1335 fontsel->property_values[prop] = styles[fontsel->style].properties[prop];
1337 gtk_clist_select_row(GTK_CLIST(fontsel->font_style_clist), best_row, 0);
1338 if (gtk_clist_row_is_visible(GTK_CLIST(fontsel->font_style_clist), best_row)
1339 != GTK_VISIBILITY_FULL)
1340 gtk_clist_moveto(GTK_CLIST(fontsel->font_style_clist), best_row, -1,
1342 gtk_font_selection_show_available_sizes (fontsel);
1343 gtk_font_selection_select_best_size (fontsel);
1347 /* This is called when a style is selected in the list. */
1349 gtk_font_selection_select_style (GtkWidget *w,
1352 GdkEventButton *bevent,
1355 GtkFontSelection *fontsel;
1356 FontInfo *font_info;
1362 #ifdef FONTSEL_DEBUG
1363 g_message("In select_style\n");
1365 fontsel = GTK_FONT_SELECTION(data);
1366 font_info = fontsel_info->font_info;
1367 font = &font_info[fontsel->font_index];
1368 styles = &fontsel_info->font_styles[font->style_index];
1370 if (bevent && !GTK_WIDGET_HAS_FOCUS (w))
1371 gtk_widget_grab_focus (w);
1373 /* The style index is stored in the row data, so we just need to copy
1374 the style values into the fontsel and reload the font. */
1375 style = GPOINTER_TO_INT (gtk_clist_get_row_data(GTK_CLIST(fontsel->font_style_clist), row));
1377 /* Don't allow selection of charset rows. */
1380 gtk_clist_unselect_row(GTK_CLIST(fontsel->font_style_clist), row, 0);
1384 gtk_clist_get_text(GTK_CLIST(fontsel->font_style_clist), row, 0, &text);
1385 gtk_entry_set_text(GTK_ENTRY(fontsel->font_style_entry), text);
1387 for (prop = 0; prop < GTK_NUM_STYLE_PROPERTIES; prop++)
1388 fontsel->property_values[prop] = styles[style].properties[prop];
1390 if (fontsel->style == style)
1393 fontsel->style = style;
1394 gtk_font_selection_show_available_sizes (fontsel);
1395 gtk_font_selection_select_best_size (fontsel);
1399 /* This shows all the available sizes in the size clist, according to the
1400 current metric and the current font & style. */
1402 gtk_font_selection_show_available_sizes (GtkFontSelection *fontsel)
1405 FontStyle *styles, *style;
1406 const guint16 *standard_sizes;
1407 guint16 *bitmapped_sizes;
1408 gint nstandard_sizes, nbitmapped_sizes;
1409 gchar buffer[16], *size;
1410 gfloat bitmap_size_float = 0.;
1411 guint16 bitmap_size = 0;
1415 #ifdef FONTSEL_DEBUG
1416 g_message("In show_available_sizes\n");
1418 font = &fontsel_info->font_info[fontsel->font_index];
1419 styles = &fontsel_info->font_styles[font->style_index];
1420 style = &styles[fontsel->style];
1422 standard_sizes = font_sizes;
1423 nstandard_sizes = sizeof(font_sizes) / sizeof(font_sizes[0]);
1424 if (fontsel->metric == GTK_FONT_METRIC_POINTS)
1426 bitmapped_sizes = &fontsel_info->point_sizes[style->point_sizes_index];
1427 nbitmapped_sizes = style->npoint_sizes;
1431 bitmapped_sizes = &fontsel_info->pixel_sizes[style->pixel_sizes_index];
1432 nbitmapped_sizes = style->npixel_sizes;
1435 /* Only show the standard sizes if a scalable font is available. */
1436 type_filter = fontsel->filters[GTK_FONT_FILTER_BASE].font_type
1437 & fontsel->filters[GTK_FONT_FILTER_USER].font_type;
1439 if (!((style->flags & GTK_FONT_SCALABLE_BITMAP
1440 && type_filter & GTK_FONT_SCALABLE_BITMAP)
1441 || (style->flags & GTK_FONT_SCALABLE
1442 && type_filter & GTK_FONT_SCALABLE)))
1443 nstandard_sizes = 0;
1445 gtk_clist_freeze (GTK_CLIST(fontsel->size_clist));
1446 gtk_clist_clear (GTK_CLIST(fontsel->size_clist));
1448 /* Interleave the standard sizes with the bitmapped sizes so we get a list
1449 of ascending sizes. If the metric is points, we have to convert the
1450 decipoints to points. */
1451 while (nstandard_sizes || nbitmapped_sizes)
1455 if (nbitmapped_sizes)
1456 if (fontsel->metric == GTK_FONT_METRIC_POINTS)
1458 if (*bitmapped_sizes % 10 != 0)
1460 bitmap_size = *bitmapped_sizes / 10;
1461 bitmap_size_float = *bitmapped_sizes / 10;
1465 bitmap_size = *bitmapped_sizes;
1466 bitmap_size_float = *bitmapped_sizes;
1469 if (can_match && nstandard_sizes && nbitmapped_sizes
1470 && *standard_sizes == bitmap_size)
1472 sprintf(buffer, "%i *", *standard_sizes);
1478 else if (nstandard_sizes
1479 && (!nbitmapped_sizes
1480 || (gfloat)*standard_sizes < bitmap_size_float))
1482 sprintf(buffer, "%i", *standard_sizes);
1488 if (fontsel->metric == GTK_FONT_METRIC_POINTS)
1490 if (*bitmapped_sizes % 10 == 0)
1491 sprintf(buffer, "%i *", *bitmapped_sizes / 10);
1493 sprintf(buffer, "%i.%i *", *bitmapped_sizes / 10,
1494 *bitmapped_sizes % 10);
1498 sprintf(buffer, "%i *", *bitmapped_sizes);
1504 gtk_clist_append(GTK_CLIST(fontsel->size_clist), &size);
1506 gtk_clist_thaw (GTK_CLIST(fontsel->size_clist));
1510 /* If the user hits return in the font size entry, we change to the new font
1513 gtk_font_selection_size_key_press (GtkWidget *w,
1517 GtkFontSelection *fontsel;
1519 gfloat new_size_float;
1522 #ifdef FONTSEL_DEBUG
1523 g_message("In size_key_press\n");
1525 fontsel = GTK_FONT_SELECTION(data);
1527 if (event->keyval == GDK_Return)
1529 text = gtk_entry_get_text (GTK_ENTRY (fontsel->size_entry));
1530 if (fontsel->metric == GTK_FONT_METRIC_PIXELS)
1532 new_size = atoi (text);
1538 new_size_float = atof (text) * 10;
1539 new_size = (gint) new_size_float;
1544 /* Remember that this size was set explicitly. */
1545 fontsel->selected_size = new_size;
1547 /* Check if the font size has changed, and return if it hasn't. */
1548 if (fontsel->size == new_size)
1551 fontsel->size = new_size;
1552 gtk_font_selection_select_best_size (fontsel);
1560 /* This tries to select the closest size to the current size, though it
1561 may have to change the size if only unscaled bitmaps are available.
1562 Note: this will load a font. */
1564 gtk_font_selection_select_best_size(GtkFontSelection *fontsel)
1567 FontStyle *styles, *style;
1569 gint row, best_row = 0, size, size_fraction, best_size = 0, nmatched;
1570 gboolean found = FALSE;
1575 #ifdef FONTSEL_DEBUG
1576 g_message("In select_best_size\n");
1578 font = &fontsel_info->font_info[fontsel->font_index];
1579 styles = &fontsel_info->font_styles[font->style_index];
1580 style = &styles[fontsel->style];
1582 /* Find the closest size available in the size clist. If the exact size is
1583 in the list set found to TRUE. */
1584 for (row = 0; row < GTK_CLIST(fontsel->size_clist)->rows; row++)
1586 gtk_clist_get_text(GTK_CLIST(fontsel->size_clist), row, 0, &text);
1587 nmatched = sscanf(text, "%i.%i", &size, &size_fraction);
1588 if (fontsel->metric == GTK_FONT_METRIC_POINTS)
1592 size += size_fraction;
1595 if (size == fontsel->selected_size)
1602 else if (best_size == 0
1603 || abs(size - fontsel->selected_size)
1604 < (abs(best_size - fontsel->selected_size)))
1611 /* If we aren't scaling bitmapped fonts and this is a bitmapped font, we
1612 need to use the closest size found. */
1613 type_filter = fontsel->filters[GTK_FONT_FILTER_BASE].font_type
1614 & fontsel->filters[GTK_FONT_FILTER_USER].font_type;
1616 if (!((style->flags & GTK_FONT_SCALABLE_BITMAP
1617 && type_filter & GTK_FONT_SCALABLE_BITMAP)
1618 || (style->flags & GTK_FONT_SCALABLE
1619 && type_filter & GTK_FONT_SCALABLE)))
1624 fontsel->size = best_size;
1625 gtk_clist_moveto(GTK_CLIST(fontsel->size_clist), best_row, -1, 0.5, 0);
1626 gtk_clist_select_row(GTK_CLIST(fontsel->size_clist), best_row, 0);
1630 fontsel->size = fontsel->selected_size;
1631 selection = GTK_CLIST(fontsel->size_clist)->selection;
1633 gtk_clist_unselect_row(GTK_CLIST(fontsel->size_clist),
1634 GPOINTER_TO_INT (selection->data), 0);
1635 gtk_clist_moveto(GTK_CLIST(fontsel->size_clist), best_row, -1, 0.5, 0);
1637 /* Show the size in the size entry. */
1638 if (fontsel->metric == GTK_FONT_METRIC_PIXELS)
1639 sprintf(buffer, "%i", fontsel->size);
1642 if (fontsel->size % 10 == 0)
1643 sprintf(buffer, "%i", fontsel->size / 10);
1645 sprintf(buffer, "%i.%i", fontsel->size / 10, fontsel->size % 10);
1647 gtk_entry_set_text (GTK_ENTRY (fontsel->size_entry), buffer);
1649 gtk_font_selection_load_font (fontsel);
1653 /* This is called when a size is selected in the list. */
1655 gtk_font_selection_select_size (GtkWidget *w,
1658 GdkEventButton *bevent,
1661 GtkFontSelection *fontsel;
1667 #ifdef FONTSEL_DEBUG
1668 g_message("In select_size\n");
1670 fontsel = GTK_FONT_SELECTION(data);
1672 if (bevent && !GTK_WIDGET_HAS_FOCUS (w))
1673 gtk_widget_grab_focus (w);
1675 /* Copy the size from the clist to the size entry, but without the bitmapped
1677 gtk_clist_get_text(GTK_CLIST(fontsel->size_clist), row, 0, &text);
1679 while (i < 15 && (text[i] == '.' || (text[i] >= '0' && text[i] <= '9')))
1681 buffer[i] = text[i];
1685 gtk_entry_set_text(GTK_ENTRY(fontsel->size_entry), buffer);
1687 /* Check if the font size has changed, and return if it hasn't. */
1688 new_size = atoi(text);
1689 if (fontsel->metric == GTK_FONT_METRIC_POINTS)
1692 if (fontsel->size == new_size)
1695 /* If the size was selected by the user we set the selected_size. */
1696 fontsel->selected_size = new_size;
1698 fontsel->size = new_size;
1699 gtk_font_selection_load_font (fontsel);
1703 /* This is called when the pixels or points radio buttons are pressed. */
1705 gtk_font_selection_metric_callback (GtkWidget *w,
1708 GtkFontSelection *fontsel = GTK_FONT_SELECTION(data);
1710 #ifdef FONTSEL_DEBUG
1711 g_message("In metric_callback\n");
1713 if (GTK_TOGGLE_BUTTON(fontsel->pixels_button)->active)
1715 if (fontsel->metric == GTK_FONT_METRIC_PIXELS)
1717 fontsel->metric = GTK_FONT_METRIC_PIXELS;
1718 fontsel->size = (fontsel->size + 5) / 10;
1719 fontsel->selected_size = (fontsel->selected_size + 5) / 10;
1723 if (fontsel->metric == GTK_FONT_METRIC_POINTS)
1725 fontsel->metric = GTK_FONT_METRIC_POINTS;
1726 fontsel->size *= 10;
1727 fontsel->selected_size *= 10;
1729 if (fontsel->font_index != -1)
1731 gtk_font_selection_show_available_sizes (fontsel);
1732 gtk_font_selection_select_best_size (fontsel);
1737 /* This searches the given property table and returns the index of the given
1738 string, or 0, which is the wildcard '*' index, if it's not found. */
1740 gtk_font_selection_field_to_index (gchar **table,
1746 for (i = 0; i < ntable; i++)
1747 if (strcmp (field, table[i]) == 0)
1755 /* This attempts to load the current font, and returns TRUE if it succeeds. */
1757 gtk_font_selection_load_font (GtkFontSelection *fontsel)
1760 gchar *fontname, *label_text;
1763 gdk_font_unref (fontsel->font);
1764 fontsel->font = NULL;
1766 /* If no family has been selected yet, just return FALSE. */
1767 if (fontsel->font_index == -1)
1770 fontname = gtk_font_selection_get_font_name (fontsel);
1773 #ifdef FONTSEL_DEBUG
1774 g_message("Loading: %s\n", fontname);
1776 font = gdk_font_load (fontname);
1781 fontsel->font = font;
1782 /* Make sure the message label is empty, but don't change it unless
1783 it's necessary as it results in a resize of the whole window! */
1784 gtk_label_get(GTK_LABEL(fontsel->message_label), &label_text);
1785 if (strcmp(label_text, ""))
1786 gtk_label_set_text(GTK_LABEL(fontsel->message_label), "");
1787 gtk_font_selection_update_preview (fontsel);
1792 gtk_label_set_text(GTK_LABEL(fontsel->message_label),
1793 _("The selected font is not available."));
1798 gtk_label_set_text(GTK_LABEL(fontsel->message_label),
1799 _("The selected font is not a valid font."));
1806 /* This sets the font in the preview entry to the selected font, and tries to
1807 make sure that the preview entry is a reasonable size, i.e. so that the
1808 text can be seen with a bit of space to spare. But it tries to avoid
1809 resizing the entry every time the font changes.
1810 This also used to shrink the preview if the font size was decreased, but
1811 that made it awkward if the user wanted to resize the window themself. */
1813 gtk_font_selection_update_preview (GtkFontSelection *fontsel)
1815 GtkWidget *preview_entry;
1817 gint text_height, new_height;
1819 #if GDK_WINDOWING == GDK_WINDOWING_X11
1823 #ifdef FONTSEL_DEBUG
1824 g_message("In update_preview\n");
1826 style = gtk_style_new ();
1827 gdk_font_unref (style->font);
1828 style->font = fontsel->font;
1829 gdk_font_ref (style->font);
1831 preview_entry = fontsel->preview_entry;
1832 gtk_widget_set_style (preview_entry, style);
1833 gtk_style_unref(style);
1835 text_height = preview_entry->style->font->ascent
1836 + preview_entry->style->font->descent;
1837 /* We don't ever want to be over MAX_PREVIEW_HEIGHT pixels high. */
1838 new_height = text_height + 20;
1839 if (new_height < INITIAL_PREVIEW_HEIGHT)
1840 new_height = INITIAL_PREVIEW_HEIGHT;
1841 if (new_height > MAX_PREVIEW_HEIGHT)
1842 new_height = MAX_PREVIEW_HEIGHT;
1844 if ((preview_entry->requisition.height < text_height + 10)
1845 || (preview_entry->requisition.height > text_height + 40))
1846 gtk_widget_set_usize(preview_entry, -1, new_height);
1848 /* This sets the preview text, if it hasn't been set already. */
1849 text = gtk_entry_get_text(GTK_ENTRY(fontsel->preview_entry));
1850 if (strlen(text) == 0)
1851 gtk_entry_set_text(GTK_ENTRY(fontsel->preview_entry), PREVIEW_TEXT);
1852 gtk_entry_set_position(GTK_ENTRY(fontsel->preview_entry), 0);
1854 #if GDK_WINDOWING == GDK_WINDOWING_X11
1855 /* If this is a 2-byte font display a message to say it may not be
1856 displayed properly. */
1857 xfs = GDK_FONT_XFONT(fontsel->font);
1858 if (xfs->min_byte1 != 0 || xfs->max_byte1 != 0)
1859 gtk_label_set_text(GTK_LABEL(fontsel->message_label),
1860 _("This is a 2-byte font and may not be displayed correctly."));
1866 gtk_font_selection_switch_page (GtkWidget *w,
1867 GtkNotebookPage *page,
1871 GtkFontSelection *fontsel = GTK_FONT_SELECTION(data);
1873 /* This function strangely gets called when the window is destroyed,
1874 so we check here to see if the notebook is visible. */
1875 if (!GTK_WIDGET_VISIBLE(w))
1879 gtk_font_selection_update_filter(fontsel);
1880 else if (page_num == 1)
1881 gtk_font_selection_show_font_info(fontsel);
1886 gtk_font_selection_show_font_info (GtkFontSelection *fontsel)
1888 #if GDK_WINDOWING == GDK_WINDOWING_X11
1889 Atom font_atom, atom;
1894 gchar field_buffer[XLFD_MAX_FIELD_LEN];
1897 gboolean shown_actual_fields = FALSE;
1899 fontname = gtk_font_selection_get_font_name(fontsel);
1900 gtk_entry_set_text(GTK_ENTRY(fontsel->requested_font_name),
1901 fontname ? fontname : "");
1903 gtk_clist_freeze (GTK_CLIST(fontsel->info_clist));
1904 for (i = 0; i < GTK_XLFD_NUM_FIELDS; i++)
1907 field = gtk_font_selection_get_xlfd_field (fontname, i, field_buffer);
1912 if (i == XLFD_SLANT)
1913 field = gtk_font_selection_expand_slant_code(field);
1914 else if (i == XLFD_SPACING)
1915 field = gtk_font_selection_expand_spacing_code(field);
1917 gtk_clist_set_text(GTK_CLIST(fontsel->info_clist), i, 1,
1918 field ? field : "");
1920 #if GDK_WINDOWING == GDK_WINDOWING_X11
1923 font_atom = XInternAtom(GDK_DISPLAY(), "FONT", True);
1924 if (font_atom != None)
1926 status = XGetFontProperty(GDK_FONT_XFONT(fontsel->font), font_atom,
1930 name = XGetAtomName(GDK_DISPLAY(), atom);
1931 gtk_entry_set_text(GTK_ENTRY(fontsel->actual_font_name), name);
1933 for (i = 0; i < GTK_XLFD_NUM_FIELDS; i++)
1935 field = gtk_font_selection_get_xlfd_field (name, i,
1937 if (i == XLFD_SLANT)
1938 field = gtk_font_selection_expand_slant_code(field);
1939 else if (i == XLFD_SPACING)
1940 field = gtk_font_selection_expand_spacing_code(field);
1941 gtk_clist_set_text(GTK_CLIST(fontsel->info_clist), i, 2,
1942 field ? field : "");
1944 shown_actual_fields = TRUE;
1949 #elif GDK_WINDOWING == GDK_WINDOWING_WIN32
1954 if (GetObject (GDK_FONT_XFONT (fontsel->font),
1955 sizeof (LOGFONT), &logfont) > 0)
1957 name = logfont_to_xlfd (&logfont, logfont.lfHeight, -1, 0);
1958 gtk_entry_set_text (GTK_ENTRY(fontsel->actual_font_name),name);
1959 for (i = 0; i < GTK_XLFD_NUM_FIELDS; i++)
1961 field = gtk_font_selection_get_xlfd_field (name, i,
1963 if (i == XLFD_SLANT)
1964 field = gtk_font_selection_expand_slant_code(field);
1965 else if (i == XLFD_SPACING)
1966 field = gtk_font_selection_expand_spacing_code(field);
1967 gtk_clist_set_text(GTK_CLIST(fontsel->info_clist), i, 2,
1968 field ? field : "");
1970 shown_actual_fields = TRUE;
1976 if (!shown_actual_fields)
1978 gtk_entry_set_text(GTK_ENTRY(fontsel->actual_font_name), "");
1979 for (i = 0; i < GTK_XLFD_NUM_FIELDS; i++)
1981 gtk_clist_set_text(GTK_CLIST(fontsel->info_clist), i, 2,
1982 fontname ? _("(unknown)") : "");
1985 gtk_clist_thaw (GTK_CLIST(fontsel->info_clist));
1991 gtk_font_selection_expand_slant_code(gchar *slant)
1993 if (!g_strcasecmp(slant, "r")) return(_("roman"));
1994 else if (!g_strcasecmp(slant, "i")) return(_("italic"));
1995 else if (!g_strcasecmp(slant, "o")) return(_("oblique"));
1996 else if (!g_strcasecmp(slant, "ri")) return(_("reverse italic"));
1997 else if (!g_strcasecmp(slant, "ro")) return(_("reverse oblique"));
1998 else if (!g_strcasecmp(slant, "ot")) return(_("other"));
2003 gtk_font_selection_expand_spacing_code(gchar *spacing)
2005 if (!g_strcasecmp(spacing, "p")) return(_("proportional"));
2006 else if (!g_strcasecmp(spacing, "m")) return(_("monospaced"));
2007 else if (!g_strcasecmp(spacing, "c")) return(_("char cell"));
2012 /*****************************************************************************
2013 * These functions all deal with the Filter page and filtering the fonts.
2014 *****************************************************************************/
2016 /* This is called when an item is selected in one of the filter clists.
2017 We make sure that the first row of the clist, i.e. the wildcard '*', is
2018 selected if and only if none of the other items are selected.
2019 Also doesn't allow selections of values filtered out by base filter.
2020 We may need to be careful about triggering other signals. */
2022 gtk_font_selection_select_filter (GtkWidget *w,
2025 GdkEventButton *bevent,
2026 GtkFontSelection *fontsel)
2028 gint i, prop, index;
2032 for (i = 1; i < GTK_CLIST(w)->rows; i++)
2033 gtk_clist_unselect_row(GTK_CLIST(w), i, 0);
2037 /* Find out which property this is. */
2038 for (prop = 0; prop < GTK_NUM_FONT_PROPERTIES; prop++)
2039 if (fontsel->filter_clists[prop] == w)
2041 index = GPOINTER_TO_INT (gtk_clist_get_row_data(GTK_CLIST(w), row));
2042 if (gtk_font_selection_filter_state (fontsel, GTK_FONT_FILTER_BASE,
2043 prop, index) == NOT_FILTERED)
2044 gtk_clist_unselect_row(GTK_CLIST(w), row, 0);
2046 gtk_clist_unselect_row(GTK_CLIST(w), 0, 0);
2051 /* Here a filter item is being deselected. If there are now no items selected
2052 we select the first '*' item, unless that it is the item being deselected,
2053 in which case we select all of the other items. This makes it easy to
2054 select all items in the list except one or two. */
2056 gtk_font_selection_unselect_filter (GtkWidget *w,
2059 GdkEventButton *bevent,
2060 GtkFontSelection *fontsel)
2062 gint i, prop, index;
2064 if (!GTK_CLIST(w)->selection)
2068 /* Find out which property this is. */
2069 for (prop = 0; prop < GTK_NUM_FONT_PROPERTIES; prop++)
2070 if (fontsel->filter_clists[prop] == w)
2073 for (i = 1; i < GTK_CLIST(w)->rows; i++)
2075 index = GPOINTER_TO_INT (gtk_clist_get_row_data(GTK_CLIST(w),
2077 if (gtk_font_selection_filter_state (fontsel,
2078 GTK_FONT_FILTER_BASE,
2081 gtk_clist_select_row(GTK_CLIST(w), i, 0);
2086 gtk_clist_select_row(GTK_CLIST(w), 0, 0);
2092 /* This is called when the main notebook page is selected. It checks if the
2093 filter has changed, an if so it creates the filter settings, and filters the
2094 fonts shown. If an empty filter (all '*'s) is applied, then filtering is
2097 gtk_font_selection_update_filter (GtkFontSelection *fontsel)
2101 gboolean default_filter = TRUE, filter_changed = FALSE;
2102 gint prop, nselected, i, row, index;
2103 GtkFontFilter *filter = &fontsel->filters[GTK_FONT_FILTER_USER];
2104 gint base_font_type, user_font_type, new_font_type;
2106 #ifdef FONTSEL_DEBUG
2107 g_message("In update_filter\n");
2110 /* Check if the user filter has changed, and also if it is the default
2111 filter, i.e. bitmap & scalable fonts and all '*'s selected.
2112 We only look at the bits which are not already filtered out by the base
2113 filter, since that overrides the user filter. */
2114 base_font_type = fontsel->filters[GTK_FONT_FILTER_BASE].font_type
2116 user_font_type = fontsel->filters[GTK_FONT_FILTER_USER].font_type
2118 new_font_type = GTK_TOGGLE_BUTTON(fontsel->type_bitmaps_button)->active
2119 ? GTK_FONT_BITMAP : 0;
2120 new_font_type |= (GTK_TOGGLE_BUTTON(fontsel->type_scalable_button)->active
2121 ? GTK_FONT_SCALABLE : 0);
2122 new_font_type |= (GTK_TOGGLE_BUTTON(fontsel->type_scaled_bitmaps_button)->active ? GTK_FONT_SCALABLE_BITMAP : 0);
2123 new_font_type &= base_font_type;
2124 new_font_type |= (~base_font_type & user_font_type);
2125 if (new_font_type != (GTK_FONT_BITMAP | GTK_FONT_SCALABLE))
2126 default_filter = FALSE;
2128 if (new_font_type != user_font_type)
2129 filter_changed = TRUE;
2130 fontsel->filters[GTK_FONT_FILTER_USER].font_type = new_font_type;
2132 for (prop = 0; prop < GTK_NUM_FONT_PROPERTIES; prop++)
2134 clist = fontsel->filter_clists[prop];
2135 selection = GTK_CLIST(clist)->selection;
2136 nselected = g_list_length(selection);
2137 if (nselected != 1 || GPOINTER_TO_INT (selection->data) != 0)
2139 default_filter = FALSE;
2141 if (filter->property_nfilters[prop] != nselected)
2142 filter_changed = TRUE;
2145 for (i = 0; i < nselected; i++)
2147 row = GPOINTER_TO_INT (selection->data);
2148 index = GPOINTER_TO_INT (gtk_clist_get_row_data (GTK_CLIST (clist), row));
2149 if (filter->property_filters[prop][i] != index)
2150 filter_changed = TRUE;
2151 selection = selection->next;
2157 if (filter->property_nfilters[prop] != 0)
2158 filter_changed = TRUE;
2162 /* If the filter hasn't changed we just return. */
2163 if (!filter_changed)
2166 #ifdef FONTSEL_DEBUG
2167 g_message(" update_fonts: filter has changed\n");
2170 /* Free the old filter data and create the new arrays. */
2171 for (prop = 0; prop < GTK_NUM_FONT_PROPERTIES; prop++)
2173 g_free(filter->property_filters[prop]);
2175 clist = fontsel->filter_clists[prop];
2176 selection = GTK_CLIST(clist)->selection;
2177 nselected = g_list_length(selection);
2178 if (nselected == 1 && GPOINTER_TO_INT (selection->data) == 0)
2180 filter->property_filters[prop] = NULL;
2181 filter->property_nfilters[prop] = 0;
2185 filter->property_filters[prop] = g_new(guint16, nselected);
2186 filter->property_nfilters[prop] = nselected;
2187 for (i = 0; i < nselected; i++)
2189 row = GPOINTER_TO_INT (selection->data);
2190 index = GPOINTER_TO_INT (gtk_clist_get_row_data (GTK_CLIST (clist), row));
2191 filter->property_filters[prop][i] = index;
2192 selection = selection->next;
2197 /* Set the 'Reset Filter' button sensitive if a filter is in effect, and
2198 also set the label above the font list to show this as well. */
2201 gtk_widget_set_sensitive(fontsel->filter_button, FALSE);
2202 gtk_label_set_text(GTK_LABEL(fontsel->font_label), _("Font:"));
2206 gtk_widget_set_sensitive(fontsel->filter_button, TRUE);
2207 gtk_label_set_text(GTK_LABEL(fontsel->font_label), _("Font: (Filter Applied)"));
2209 gtk_font_selection_show_available_fonts(fontsel);
2213 /* This shows all the available fonts in the font clist. */
2215 gtk_font_selection_show_available_fonts (GtkFontSelection *fontsel)
2217 FontInfo *font_info, *font;
2218 GtkFontFilter *filter;
2219 gint nfonts, i, j, k, row, style, font_row = -1;
2220 gchar font_buffer[XLFD_MAX_FIELD_LEN * 2 + 4];
2222 gboolean matched, matched_style;
2224 #ifdef FONTSEL_DEBUG
2225 g_message("In show_available_fonts\n");
2227 font_info = fontsel_info->font_info;
2228 nfonts = fontsel_info->nfonts;
2230 /* Filter the list of fonts. */
2231 gtk_clist_freeze (GTK_CLIST(fontsel->font_clist));
2232 gtk_clist_clear (GTK_CLIST(fontsel->font_clist));
2233 for (i = 0; i < nfonts; i++)
2235 font = &font_info[i];
2237 /* Check if the foundry passes through all filters. */
2239 for (k = 0; k < GTK_NUM_FONT_FILTERS; k++)
2241 filter = &fontsel->filters[k];
2243 if (filter->property_nfilters[FOUNDRY] != 0)
2246 for (j = 0; j < filter->property_nfilters[FOUNDRY]; j++)
2248 if (font->foundry == filter->property_filters[FOUNDRY][j])
2263 /* Now check if the other properties are matched in at least one style.*/
2264 matched_style = FALSE;
2265 for (style = 0; style < font->nstyles; style++)
2267 if (gtk_font_selection_style_visible(fontsel, font, style))
2269 matched_style = TRUE;
2276 /* Insert the font in the clist. */
2277 if ((i > 0 && font->family == font_info[i-1].family)
2278 || (i < nfonts - 1 && font->family == font_info[i+1].family))
2280 sprintf(font_buffer, "%s (%s)", font->family,
2281 fontsel_info->properties[FOUNDRY][font->foundry]);
2282 font_item = font_buffer;
2283 row = gtk_clist_append(GTK_CLIST(fontsel->font_clist), &font_item);
2287 row = gtk_clist_append(GTK_CLIST(fontsel->font_clist),
2290 gtk_clist_set_row_data(GTK_CLIST(fontsel->font_clist), row,
2291 GINT_TO_POINTER (i));
2292 if (fontsel->font_index == i)
2295 gtk_clist_thaw (GTK_CLIST(fontsel->font_clist));
2297 /* If the currently-selected font isn't in the new list, reset the
2301 fontsel->font_index = -1;
2303 gdk_font_unref(fontsel->font);
2304 fontsel->font = NULL;
2305 gtk_entry_set_text(GTK_ENTRY(fontsel->font_entry), "");
2306 gtk_clist_clear (GTK_CLIST(fontsel->font_style_clist));
2307 gtk_entry_set_text(GTK_ENTRY(fontsel->font_style_entry), "");
2311 gtk_clist_select_row(GTK_CLIST(fontsel->font_clist), font_row, 0);
2312 if (gtk_clist_row_is_visible(GTK_CLIST(fontsel->font_clist), font_row)
2313 != GTK_VISIBILITY_FULL)
2314 gtk_clist_moveto(GTK_CLIST(fontsel->font_clist), font_row, -1, 0.5, 0);
2316 gtk_font_selection_show_available_styles (fontsel);
2317 gtk_font_selection_select_best_style (fontsel, FALSE);
2321 /* Returns TRUE if the style is not currently filtered out. */
2323 gtk_font_selection_style_visible(GtkFontSelection *fontsel,
2327 FontStyle *styles, *style;
2328 GtkFontFilter *filter;
2334 styles = &fontsel_info->font_styles[font->style_index];
2335 style = &styles[style_index];
2337 /* Check if font_type of style is filtered. */
2338 type_filter = fontsel->filters[GTK_FONT_FILTER_BASE].font_type
2339 & fontsel->filters[GTK_FONT_FILTER_USER].font_type;
2340 if (!(style->flags & type_filter))
2343 for (prop = 0; prop < GTK_NUM_STYLE_PROPERTIES; prop++)
2345 value = style->properties[prop];
2347 /* Check each filter. */
2348 for (i = 0; i < GTK_NUM_FONT_FILTERS; i++)
2350 filter = &fontsel->filters[i];
2352 if (filter->property_nfilters[prop] != 0)
2355 for (j = 0; j < filter->property_nfilters[prop]; j++)
2357 if (value == filter->property_filters[prop][j])
2372 /* This resets the font type to bitmap or scalable, and sets all the filter
2373 clists to the wildcard '*' options. */
2375 gtk_font_selection_reset_filter (GtkWidget *w,
2376 GtkFontSelection *fontsel)
2378 gint prop, base_font_type;
2380 fontsel->filters[GTK_FONT_FILTER_USER].font_type = GTK_FONT_BITMAP
2381 | GTK_FONT_SCALABLE;
2383 base_font_type = fontsel->filters[GTK_FONT_FILTER_BASE].font_type;
2384 if (base_font_type & GTK_FONT_BITMAP)
2385 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fontsel->type_bitmaps_button), TRUE);
2386 if (base_font_type & GTK_FONT_SCALABLE)
2387 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fontsel->type_scalable_button), TRUE);
2388 if (base_font_type & GTK_FONT_SCALABLE_BITMAP)
2389 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fontsel->type_scaled_bitmaps_button), FALSE);
2391 for (prop = 0; prop < GTK_NUM_FONT_PROPERTIES; prop++)
2392 gtk_clist_select_row(GTK_CLIST(fontsel->filter_clists[prop]), 0, 0);
2396 /* This clears the filter, showing all fonts and styles again. */
2398 gtk_font_selection_on_clear_filter (GtkWidget *w,
2399 GtkFontSelection *fontsel)
2401 gtk_font_selection_clear_filter(fontsel);
2405 /* This resets the user filter, showing all fonts and styles which pass the
2406 base filter again. Note that the font type is set to bitmaps and scalable
2407 fonts - scaled bitmaps are not shown. */
2409 gtk_font_selection_clear_filter (GtkFontSelection *fontsel)
2411 GtkFontFilter *filter;
2414 #ifdef FONTSEL_DEBUG
2415 g_message("In clear_filter\n");
2417 /* Clear the filter data. */
2418 filter = &fontsel->filters[GTK_FONT_FILTER_USER];
2419 filter->font_type = GTK_FONT_BITMAP | GTK_FONT_SCALABLE;
2420 for (prop = 0; prop < GTK_NUM_FONT_PROPERTIES; prop++)
2422 g_free(filter->property_filters[prop]);
2423 filter->property_filters[prop] = NULL;
2424 filter->property_nfilters[prop] = 0;
2427 /* Select all the '*'s on the filter page. */
2428 gtk_font_selection_reset_filter(NULL, fontsel);
2430 /* Update the main notebook page. */
2431 gtk_widget_set_sensitive(fontsel->filter_button, FALSE);
2432 gtk_label_set_text(GTK_LABEL(fontsel->font_label), _("Font:"));
2434 gtk_font_selection_show_available_fonts(fontsel);
2439 gtk_font_selection_set_filter (GtkFontSelection *fontsel,
2440 GtkFontFilterType filter_type,
2441 GtkFontType font_type,
2449 GtkFontFilter *filter;
2450 gchar **filter_strings [GTK_NUM_FONT_PROPERTIES];
2451 gchar *filter_string;
2452 gchar *property, *property_alt;
2453 gint prop, nfilters, i, j, num_found;
2454 gint base_font_type, user_font_type;
2455 gboolean filter_set;
2457 /* Put them into an array so we can use a simple loop. */
2458 filter_strings[FOUNDRY] = foundries;
2459 filter_strings[WEIGHT] = weights;
2460 filter_strings[SLANT] = slants;
2461 filter_strings[SET_WIDTH] = setwidths;
2462 filter_strings[SPACING] = spacings;
2463 filter_strings[CHARSET] = charsets;
2465 filter = &fontsel->filters[filter_type];
2466 filter->font_type = font_type;
2468 /* Free the old filter data, and insert the new. */
2469 for (prop = 0; prop < GTK_NUM_FONT_PROPERTIES; prop++)
2471 g_free(filter->property_filters[prop]);
2472 filter->property_filters[prop] = NULL;
2473 filter->property_nfilters[prop] = 0;
2475 if (filter_strings[prop])
2477 /* Count how many items in the new array. */
2479 while (filter_strings[prop][nfilters])
2482 filter->property_filters[prop] = g_new(guint16, nfilters);
2483 filter->property_nfilters[prop] = 0;
2485 /* Now convert the strings to property indices. */
2487 for (i = 0; i < nfilters; i++)
2489 filter_string = filter_strings[prop][i];
2490 for (j = 0; j < fontsel_info->nproperties[prop]; j++)
2492 property = _(fontsel_info->properties[prop][j]);
2493 property_alt = NULL;
2495 property_alt = gtk_font_selection_expand_slant_code(property);
2496 else if (prop == SPACING)
2497 property_alt = gtk_font_selection_expand_spacing_code(property);
2498 if (!strcmp (filter_string, property)
2499 || (property_alt && !strcmp (filter_string, property_alt)))
2501 filter->property_filters[prop][num_found] = j;
2507 filter->property_nfilters[prop] = num_found;
2511 /* Now set the clists on the filter page according to the new filter. */
2512 gtk_font_selection_update_filter_lists (fontsel);
2514 if (filter_type == GTK_FONT_FILTER_BASE)
2516 user_font_type = fontsel->filters[GTK_FONT_FILTER_USER].font_type;
2517 if (font_type & GTK_FONT_BITMAP)
2519 gtk_widget_set_sensitive (fontsel->type_bitmaps_button, TRUE);
2520 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fontsel->type_bitmaps_button), user_font_type & GTK_FONT_BITMAP);
2524 gtk_widget_set_sensitive (fontsel->type_bitmaps_button, FALSE);
2525 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fontsel->type_bitmaps_button), FALSE);
2528 if (font_type & GTK_FONT_SCALABLE)
2530 gtk_widget_set_sensitive (fontsel->type_scalable_button, TRUE);
2531 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fontsel->type_scalable_button), user_font_type & GTK_FONT_SCALABLE);
2535 gtk_widget_set_sensitive (fontsel->type_scalable_button, FALSE);
2536 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fontsel->type_scalable_button), FALSE);
2539 if (font_type & GTK_FONT_SCALABLE_BITMAP)
2541 gtk_widget_set_sensitive (fontsel->type_scaled_bitmaps_button, TRUE);
2542 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fontsel->type_scaled_bitmaps_button), user_font_type & GTK_FONT_SCALABLE_BITMAP);
2546 gtk_widget_set_sensitive (fontsel->type_scaled_bitmaps_button, FALSE);
2547 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fontsel->type_scaled_bitmaps_button), FALSE);
2552 base_font_type = fontsel->filters[GTK_FONT_FILTER_BASE].font_type;
2553 if (base_font_type & GTK_FONT_BITMAP)
2554 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fontsel->type_bitmaps_button), font_type & GTK_FONT_BITMAP);
2556 if (base_font_type & GTK_FONT_SCALABLE)
2557 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fontsel->type_scalable_button), font_type & GTK_FONT_SCALABLE);
2559 if (base_font_type & GTK_FONT_SCALABLE_BITMAP)
2560 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fontsel->type_scaled_bitmaps_button), font_type & GTK_FONT_SCALABLE_BITMAP);
2562 /* If the user filter is not the default, make the 'Reset Filter' button
2565 if (font_type != (GTK_FONT_BITMAP | GTK_FONT_SCALABLE))
2567 for (prop = 0; prop < GTK_NUM_FONT_PROPERTIES; prop++)
2569 if (filter->property_nfilters[prop] != 0)
2573 gtk_widget_set_sensitive (fontsel->filter_button, TRUE);
2576 gtk_font_selection_show_available_fonts (fontsel);
2580 /* This sets the colour of each property in the filter clists according to
2581 the base filter. i.e. Filtered properties are shown as insensitive. */
2583 gtk_font_selection_update_filter_lists (GtkFontSelection *fontsel)
2586 GdkColor *inactive_fg, *inactive_bg, *fg, *bg;
2587 gint prop, row, index;
2589 /* We have to make sure the clist is realized to use the colours. */
2590 for (prop = 0; prop < GTK_NUM_FONT_PROPERTIES; prop++)
2592 clist = fontsel->filter_clists[prop];
2593 gtk_widget_realize (clist);
2594 inactive_fg = &clist->style->fg[GTK_STATE_INSENSITIVE];
2595 inactive_bg = &clist->style->bg[GTK_STATE_INSENSITIVE];
2596 for (row = 1; row < GTK_CLIST(clist)->rows; row++)
2598 index = GPOINTER_TO_INT (gtk_clist_get_row_data(GTK_CLIST(clist),
2600 /* Set the colour according to the base filter. */
2601 if (gtk_font_selection_filter_state (fontsel, GTK_FONT_FILTER_BASE,
2602 prop, index) == NOT_FILTERED)
2612 gtk_clist_set_foreground(GTK_CLIST(clist), row, fg);
2613 gtk_clist_set_background(GTK_CLIST(clist), row, bg);
2615 /* Set the selection state according to the user filter. */
2616 if (gtk_font_selection_filter_state (fontsel, GTK_FONT_FILTER_USER,
2617 prop, index) == FILTERED
2619 gtk_clist_select_row (GTK_CLIST (clist), row, 0);
2621 gtk_clist_unselect_row (GTK_CLIST (clist), row, 0);
2627 /* Returns whether a property value is in the filter or not, or if the
2628 property has no filter set. */
2629 static GtkFontPropertyFilterState
2630 gtk_font_selection_filter_state (GtkFontSelection *fontsel,
2631 GtkFontFilterType filter_type,
2635 GtkFontFilter *filter;
2638 filter = &fontsel->filters[filter_type];
2639 if (filter->property_nfilters[property] == 0)
2642 for (i = 0; i < filter->property_nfilters[property]; i++)
2644 if (filter->property_filters[property][i] == index)
2647 return NOT_FILTERED;
2651 #if GDK_WINDOWING == GDK_WINDOWING_WIN32
2653 static gint num_fonts;
2654 static gint font_names_size;
2655 static gchar **xfontnames;
2659 logfont_to_xlfd (const LOGFONT *lfp,
2664 const gchar *weight;
2665 const gchar *registry, *encoding;
2667 static int logpixelsy = 0;
2668 gchar facename[LF_FACESIZE*3];
2671 if (logpixelsy == 0)
2673 HDC hdc = GetDC (NULL);
2674 logpixelsy = GetDeviceCaps (hdc, LOGPIXELSY);
2675 ReleaseDC (NULL, hdc);
2678 /* Don't use _() here, only N_(), the actual translation is done elsewhere */
2679 if (lfp->lfWeight >= FW_HEAVY)
2680 weight = N_("heavy");
2681 else if (lfp->lfWeight >= FW_EXTRABOLD)
2682 weight = N_("extrabold");
2683 else if (lfp->lfWeight >= FW_BOLD)
2684 weight = N_("bold");
2686 else if (lfp->lfWeight >= FW_DEMIBOLD)
2687 weight = N_("demibold");
2689 else if (lfp->lfWeight >= FW_MEDIUM)
2690 weight = N_("medium");
2691 else if (lfp->lfWeight >= FW_NORMAL)
2692 weight = N_("normal");
2693 else if (lfp->lfWeight >= FW_LIGHT)
2694 weight = N_("light");
2695 else if (lfp->lfWeight >= FW_EXTRALIGHT)
2696 weight = N_("extralight");
2697 else if (lfp->lfWeight >= FW_THIN)
2698 weight = N_("thin");
2700 weight = N_("regular");
2702 if (lfp->lfCharSet == ANSI_CHARSET)
2704 registry = "iso8859";
2709 registry = "windows";
2710 if (lfp->lfCharSet == DEFAULT_CHARSET)
2711 encoding = "default";
2712 else if (lfp->lfCharSet == SYMBOL_CHARSET)
2713 encoding = "symbol";
2714 else if (lfp->lfCharSet == SHIFTJIS_CHARSET)
2715 encoding = "shiftjis";
2716 else if (lfp->lfCharSet == GB2312_CHARSET)
2717 encoding = "gb2312";
2718 else if (lfp->lfCharSet == HANGEUL_CHARSET)
2719 encoding = "hangeul";
2720 else if (lfp->lfCharSet == CHINESEBIG5_CHARSET)
2721 encoding = "chinesebig5";
2722 else if (lfp->lfCharSet == OEM_CHARSET)
2724 #ifdef JOHAB_CHARSET
2725 else if (lfp->lfCharSet == JOHAB_CHARSET)
2728 else if (lfp->lfCharSet == HEBREW_CHARSET)
2729 encoding = "hebrew";
2730 else if (lfp->lfCharSet == ARABIC_CHARSET)
2731 encoding = "arabic";
2732 else if (lfp->lfCharSet == GREEK_CHARSET)
2734 else if (lfp->lfCharSet == TURKISH_CHARSET)
2735 encoding = "turkish";
2736 else if (lfp->lfCharSet == THAI_CHARSET)
2738 else if (lfp->lfCharSet == EASTEUROPE_CHARSET)
2739 encoding = "easteurope";
2740 else if (lfp->lfCharSet == RUSSIAN_CHARSET)
2741 encoding = "russian";
2742 else if (lfp->lfCharSet == MAC_CHARSET)
2744 else if (lfp->lfCharSet == BALTIC_CHARSET)
2745 encoding = "baltic";
2747 encoding = "unknown";
2750 point_size = (int) (((double) size/logpixelsy) * 720.);
2755 /* Replace illegal characters with hex escapes. */
2757 q = lfp->lfFaceName;
2760 if (*q == '-' || *q == '*' || *q == '?' || *q == '%')
2761 p += sprintf (p, "%%%.02x", *q);
2768 return g_strdup_printf
2769 ("-%s-%s-%s-%s-%s-%s-%d-%d-%d-%d-%s-%d-%s-%s",
2774 ((lfp->lfPitchAndFamily & 0xF0) == FF_ROMAN
2775 || (lfp->lfPitchAndFamily & 0xF0) == FF_SCRIPT ?
2783 ((lfp->lfPitchAndFamily & 0x03) == FIXED_PITCH ? "m" : "p"),
2785 registry, encoding);
2789 InnerEnumFontFamExProc (const LOGFONT *lfp,
2790 const TEXTMETRIC *metrics,
2796 if (fontType == TRUETYPE_FONTTYPE)
2802 size = lfp->lfHeight;
2806 if (num_fonts == font_names_size)
2808 font_names_size *= 2;
2809 xfontnames = g_realloc (xfontnames, font_names_size * sizeof (gchar *));
2811 xfontnames[num_fonts-1] =
2812 logfont_to_xlfd (lfp, size, 0, 0);
2817 EnumFontFamExProc (const LOGFONT *lfp,
2818 const TEXTMETRIC *metrics,
2822 if (fontType == TRUETYPE_FONTTYPE)
2825 lf.lfPitchAndFamily = 0;
2826 EnumFontFamiliesEx (hdc, &lf, InnerEnumFontFamExProc, 0, 0);
2829 InnerEnumFontFamExProc (lfp, metrics, fontType, lParam);
2835 /*****************************************************************************
2836 * These functions all deal with creating the main class arrays containing
2837 * the data about all available fonts.
2838 *****************************************************************************/
2840 gtk_font_selection_get_fonts (void)
2842 #if GDK_WINDOWING == GDK_WINDOWING_X11
2845 #elif GDK_WINDOWING == GDK_WINDOWING_WIN32
2849 gchar **xfontnames = NULL;
2854 gint i, prop, style, size;
2855 gint npixel_sizes = 0, npoint_sizes = 0;
2857 FontStyle *current_style, *prev_style, *tmp_style;
2858 gboolean matched_style, found_size;
2859 gint pixels, points, res_x, res_y;
2860 gchar field_buffer[XLFD_MAX_FIELD_LEN];
2863 guint16 *pixel_sizes, *point_sizes, *tmp_sizes;
2865 fontsel_info = g_new (GtkFontSelInfo, 1);
2867 #if GDK_WINDOWING == GDK_WINDOWING_X11
2868 /* Get a maximum of MAX_FONTS fontnames from the X server.
2869 Use "-*" as the pattern rather than "-*-*-*-*-*-*-*-*-*-*-*-*-*-*" since
2870 the latter may result in fonts being returned which don't actually exist.
2871 xlsfonts also uses "*" so I think it's OK. "-*" gets rid of aliases. */
2872 xfontnames = XListFonts (GDK_DISPLAY(), "-*", MAX_FONTS, &num_fonts);
2873 /* Output a warning if we actually get MAX_FONTS fonts. */
2874 if (num_fonts == MAX_FONTS)
2875 g_warning(_("MAX_FONTS exceeded. Some fonts may be missing."));
2877 #elif GDK_WINDOWING == GDK_WINDOWING_WIN32
2880 font_names_size = 100;
2881 xfontnames = g_new (gchar *, font_names_size);
2882 logfont.lfCharSet = DEFAULT_CHARSET;
2883 logfont.lfFaceName[0] = '\0';
2884 logfont.lfPitchAndFamily = 0;
2885 EnumFontFamiliesEx (hdc, &logfont, EnumFontFamExProc, 0, 0);
2886 ReleaseDC (NULL, hdc);
2889 /* The maximum size of all these tables is the number of font names
2890 returned. We realloc them later when we know exactly how many
2891 unique entries there are. */
2892 fontsel_info->font_info = g_new (FontInfo, num_fonts);
2893 fontsel_info->font_styles = g_new (FontStyle, num_fonts);
2894 fontsel_info->pixel_sizes = g_new (guint16, num_fonts);
2895 fontsel_info->point_sizes = g_new (guint16, num_fonts);
2897 fontnames = g_new (GSList*, num_fonts);
2899 /* Create the initial arrays for the property value strings, though they
2900 may be realloc'ed later. Put the wildcard '*' in the first elements. */
2901 for (prop = 0; prop < GTK_NUM_FONT_PROPERTIES; prop++)
2903 fontsel_info->properties[prop] = g_new(gchar*, PROPERTY_ARRAY_INCREMENT);
2904 fontsel_info->space_allocated[prop] = PROPERTY_ARRAY_INCREMENT;
2905 fontsel_info->nproperties[prop] = 1;
2906 fontsel_info->properties[prop][0] = "*";
2910 /* Insert the font families into the main table, sorted by family and
2911 foundry (fonts with different foundries are placed in seaparate FontInfos.
2912 All fontnames in each family + foundry are placed into the fontnames
2914 fontsel_info->nfonts = 0;
2915 for (i = 0; i < num_fonts; i++)
2917 #ifdef FONTSEL_DEBUG
2918 g_message("%s\n", xfontnames[i]);
2920 if (gtk_font_selection_is_xlfd_font_name (xfontnames[i]))
2921 gtk_font_selection_insert_font (fontnames, &fontsel_info->nfonts, xfontnames[i]);
2924 #ifdef FONTSEL_DEBUG
2925 g_warning("Skipping invalid font: %s", xfontnames[i]);
2931 /* Since many font names will be in the same FontInfo not all of the
2932 allocated FontInfo table will be used, so we will now reallocate it
2933 with the real size. */
2934 fontsel_info->font_info = g_realloc(fontsel_info->font_info,
2935 sizeof(FontInfo) * fontsel_info->nfonts);
2938 /* Now we work out which choices of weight/slant etc. are valid for each
2940 fontsel_info->nstyles = 0;
2941 current_style = fontsel_info->font_styles;
2942 for (i = 0; i < fontsel_info->nfonts; i++)
2944 font = &fontsel_info->font_info[i];
2946 /* Use the next free position in the styles array. */
2947 font->style_index = fontsel_info->nstyles;
2949 /* Now step through each of the fontnames with this family, and create
2950 a style for each fontname. Each style contains the index into the
2951 weights/slants etc. arrays, and a number of pixel/point sizes. */
2953 temp_list = fontnames[i];
2956 fontname = temp_list->data;
2957 temp_list = temp_list->next;
2959 for (prop = 0; prop < GTK_NUM_STYLE_PROPERTIES; prop++)
2961 current_style->properties[prop]
2962 = gtk_font_selection_insert_field (fontname, prop);
2964 current_style->pixel_sizes_index = npixel_sizes;
2965 current_style->npixel_sizes = 0;
2966 current_style->point_sizes_index = npoint_sizes;
2967 current_style->npoint_sizes = 0;
2968 current_style->flags = 0;
2971 field = gtk_font_selection_get_xlfd_field (fontname, XLFD_PIXELS,
2973 pixels = atoi(field);
2975 field = gtk_font_selection_get_xlfd_field (fontname, XLFD_POINTS,
2977 points = atoi(field);
2979 field = gtk_font_selection_get_xlfd_field (fontname,
2982 res_x = atoi(field);
2984 field = gtk_font_selection_get_xlfd_field (fontname,
2987 res_y = atoi(field);
2989 if (pixels == 0 && points == 0)
2991 if (res_x == 0 && res_y == 0)
2992 flags = GTK_FONT_SCALABLE;
2994 flags = GTK_FONT_SCALABLE_BITMAP;
2997 flags = GTK_FONT_BITMAP;
2999 /* Now we check to make sure that the style is unique. If it isn't
3001 prev_style = fontsel_info->font_styles + font->style_index;
3002 matched_style = FALSE;
3003 while (prev_style < current_style)
3005 matched_style = TRUE;
3006 for (prop = 0; prop < GTK_NUM_STYLE_PROPERTIES; prop++)
3008 if (prev_style->properties[prop]
3009 != current_style->properties[prop])
3011 matched_style = FALSE;
3020 /* If we matched an existing style, we need to add the pixels &
3021 point sizes to the style. If not, we insert the pixel & point
3022 sizes into our new style. Note that we don't add sizes for
3026 prev_style->flags |= flags;
3027 if (flags == GTK_FONT_BITMAP)
3029 pixel_sizes = fontsel_info->pixel_sizes
3030 + prev_style->pixel_sizes_index;
3032 for (size = 0; size < prev_style->npixel_sizes; size++)
3034 if (pixels == *pixel_sizes)
3039 else if (pixels < *pixel_sizes)
3043 /* We need to move all the following pixel sizes up, and also
3044 update the indexes of any following styles. */
3047 for (tmp_sizes = fontsel_info->pixel_sizes + npixel_sizes;
3048 tmp_sizes > pixel_sizes; tmp_sizes--)
3049 *tmp_sizes = *(tmp_sizes - 1);
3051 *pixel_sizes = pixels;
3053 prev_style->npixel_sizes++;
3055 tmp_style = prev_style + 1;
3056 while (tmp_style < current_style)
3058 tmp_style->pixel_sizes_index++;
3063 point_sizes = fontsel_info->point_sizes
3064 + prev_style->point_sizes_index;
3066 for (size = 0; size < prev_style->npoint_sizes; size++)
3068 if (points == *point_sizes)
3073 else if (points < *point_sizes)
3077 /* We need to move all the following point sizes up, and also
3078 update the indexes of any following styles. */
3081 for (tmp_sizes = fontsel_info->point_sizes + npoint_sizes;
3082 tmp_sizes > point_sizes; tmp_sizes--)
3083 *tmp_sizes = *(tmp_sizes - 1);
3085 *point_sizes = points;
3087 prev_style->npoint_sizes++;
3089 tmp_style = prev_style + 1;
3090 while (tmp_style < current_style)
3092 tmp_style->point_sizes_index++;
3100 current_style->flags = flags;
3101 if (flags == GTK_FONT_BITMAP)
3103 fontsel_info->pixel_sizes[npixel_sizes++] = pixels;
3104 current_style->npixel_sizes = 1;
3105 fontsel_info->point_sizes[npoint_sizes++] = points;
3106 current_style->npoint_sizes = 1;
3109 fontsel_info->nstyles++;
3113 g_slist_free(fontnames[i]);
3115 /* Set nstyles to the real value, minus duplicated fontnames.
3116 Note that we aren't using all the allocated memory if fontnames are
3118 font->nstyles = style;
3121 /* Since some repeated styles may be skipped we won't have used all the
3122 allocated space, so we will now reallocate it with the real size. */
3123 fontsel_info->font_styles = g_realloc(fontsel_info->font_styles,
3124 sizeof(FontStyle) * fontsel_info->nstyles);
3125 fontsel_info->pixel_sizes = g_realloc(fontsel_info->pixel_sizes,
3126 sizeof(guint16) * npixel_sizes);
3127 fontsel_info->point_sizes = g_realloc(fontsel_info->point_sizes,
3128 sizeof(guint16) * npoint_sizes);
3131 #if GDK_WINDOWING == GDK_WINDOWING_X11
3132 XFreeFontNames (xfontnames);
3133 #elif GDK_WINDOWING == GDK_WINDOWING_WIN32
3134 for (i = 0; i < num_fonts; i++)
3135 g_free (xfontnames[i]);
3136 g_free (xfontnames);
3139 /* Debugging Output */
3140 /* This outputs all FontInfos. */
3141 #ifdef FONTSEL_DEBUG
3142 g_message("\n\n Font Family Weight Slant Set Width Spacing Charset\n\n");
3143 for (i = 0; i < fontsel_info->nfonts; i++)
3145 FontInfo *font = &fontsel_info->font_info[i];
3146 FontStyle *styles = fontsel_info->font_styles + font->style_index;
3147 for (style = 0; style < font->nstyles; style++)
3149 g_message("%5i %-16.16s ", i, font->family);
3150 for (prop = 0; prop < GTK_NUM_STYLE_PROPERTIES; prop++)
3151 g_message("%-9.9s ",
3152 fontsel_info->properties[prop][styles->properties[prop]]);
3155 if (styles->flags & GTK_FONT_BITMAP)
3156 g_message("Bitmapped font ");
3157 if (styles->flags & GTK_FONT_SCALABLE)
3158 g_message("Scalable font ");
3159 if (styles->flags & GTK_FONT_SCALABLE_BITMAP)
3160 g_message("Scalable-Bitmapped font ");
3163 if (styles->npixel_sizes)
3165 g_message(" Pixel sizes: ");
3166 tmp_sizes = fontsel_info->pixel_sizes + styles->pixel_sizes_index;
3167 for (size = 0; size < styles->npixel_sizes; size++)
3168 g_message("%i ", *tmp_sizes++);
3172 if (styles->npoint_sizes)
3174 g_message(" Point sizes: ");
3175 tmp_sizes = fontsel_info->point_sizes + styles->point_sizes_index;
3176 for (size = 0; size < styles->npoint_sizes; size++)
3177 g_message("%i ", *tmp_sizes++);
3185 /* This outputs all available properties. */
3186 for (prop = 0; prop < GTK_NUM_FONT_PROPERTIES; prop++)
3188 g_message("Property: %s\n", xlfd_field_names[xlfd_index[prop]]);
3189 for (i = 0; i < fontsel_info->nproperties[prop]; i++)
3190 g_message(" %s\n", fontsel_info->properties[prop][i]);
3195 /* This inserts the given fontname into the FontInfo table.
3196 If a FontInfo already exists with the same family and foundry, then the
3197 fontname is added to the FontInfos list of fontnames, else a new FontInfo
3198 is created and inserted in alphabetical order in the table. */
3200 gtk_font_selection_insert_font (GSList *fontnames[],
3206 GSList *temp_fontname;
3208 gboolean family_exists = FALSE;
3212 gchar family_buffer[XLFD_MAX_FIELD_LEN];
3214 table = fontsel_info->font_info;
3216 /* insert a fontname into a table */
3217 family = gtk_font_selection_get_xlfd_field (fontname, XLFD_FAMILY,
3222 foundry = gtk_font_selection_insert_field (fontname, FOUNDRY);
3227 /* Do a binary search to determine if we have already encountered
3228 * a font with this family & foundry. */
3230 while (lower < upper)
3232 middle = (lower + upper) >> 1;
3234 cmp = strcmp (family, table[middle].family);
3235 /* If the family matches we sort by the foundry. */
3238 family_exists = TRUE;
3239 family = table[middle].family;
3240 cmp = strcmp(fontsel_info->properties[FOUNDRY][foundry],
3241 fontsel_info->properties[FOUNDRY][table[middle].foundry]);
3246 fontnames[middle] = g_slist_prepend (fontnames[middle],
3257 /* Add another entry to the table for this new font family */
3258 temp_info.family = family_exists ? family : g_strdup(family);
3259 temp_info.foundry = foundry;
3260 temp_fontname = g_slist_prepend (NULL, fontname);
3264 /* Quickly insert the entry into the table in sorted order
3265 * using a modification of insertion sort and the knowledge
3266 * that the entries proper position in the table was determined
3267 * above in the binary search and is contained in the "lower"
3271 upper = *ntable - 1;
3272 while (lower != upper)
3274 table[upper] = table[upper-1];
3275 fontnames[upper] = fontnames[upper-1];
3279 table[lower] = temp_info;
3280 fontnames[lower] = temp_fontname;
3284 /* This checks that the specified field of the given fontname is in the
3285 appropriate properties array. If not it is added. Thus eventually we get
3286 arrays of all possible weights/slants etc. It returns the array index. */
3288 gtk_font_selection_insert_field (gchar *fontname,
3291 gchar field_buffer[XLFD_MAX_FIELD_LEN];
3295 field = gtk_font_selection_get_xlfd_field (fontname, xlfd_index[prop],
3300 /* If the field is already in the array just return its index. */
3301 for (index = 0; index < fontsel_info->nproperties[prop]; index++)
3302 if (!strcmp(field, fontsel_info->properties[prop][index]))
3305 /* Make sure we have enough space to add the field. */
3306 if (fontsel_info->nproperties[prop] == fontsel_info->space_allocated[prop])
3308 fontsel_info->space_allocated[prop] += PROPERTY_ARRAY_INCREMENT;
3309 fontsel_info->properties[prop] = g_realloc(fontsel_info->properties[prop],
3311 * fontsel_info->space_allocated[prop]);
3314 /* Add the new field. */
3315 index = fontsel_info->nproperties[prop];
3316 fontsel_info->properties[prop][index] = g_strdup(field);
3317 fontsel_info->nproperties[prop]++;
3322 /*****************************************************************************
3323 * These functions are the main public interface for getting/setting the font.
3324 *****************************************************************************/
3327 gtk_font_selection_get_font (GtkFontSelection *fontsel)
3329 g_return_val_if_fail (fontsel != NULL, NULL);
3330 return fontsel->font;
3335 gtk_font_selection_get_font_name (GtkFontSelection *fontsel)
3338 gchar *family_str, *foundry_str;
3339 gchar *property_str[GTK_NUM_STYLE_PROPERTIES];
3342 g_return_val_if_fail (fontsel != NULL, NULL);
3343 g_return_val_if_fail (GTK_IS_FONT_SELECTION (fontsel), NULL);
3345 /* If no family has been selected return NULL. */
3346 if (fontsel->font_index == -1)
3349 font = &fontsel_info->font_info[fontsel->font_index];
3350 family_str = font->family;
3351 foundry_str = fontsel_info->properties[FOUNDRY][font->foundry];
3353 for (prop = 0; prop < GTK_NUM_STYLE_PROPERTIES; prop++)
3356 = fontsel_info->properties[prop][fontsel->property_values[prop]];
3357 if (strcmp (property_str[prop], "(nil)") == 0)
3358 property_str[prop] = "";
3361 return gtk_font_selection_create_xlfd (fontsel->size,
3365 property_str[WEIGHT],
3366 property_str[SLANT],
3367 property_str[SET_WIDTH],
3368 property_str[SPACING],
3369 property_str[CHARSET]);
3373 /* This sets the current font, selecting the appropriate clist rows.
3374 First we check the fontname is valid and try to find the font family
3375 - i.e. the name in the main list. If we can't find that, then just return.
3376 Next we try to set each of the properties according to the fontname.
3377 Finally we select the font family & style in the clists. */
3379 gtk_font_selection_set_font_name (GtkFontSelection *fontsel,
3380 const gchar *fontname)
3382 gchar *family, *field;
3383 gint index, prop, size;
3384 guint16 foundry, value;
3385 gchar family_buffer[XLFD_MAX_FIELD_LEN];
3386 gchar field_buffer[XLFD_MAX_FIELD_LEN];
3389 g_return_val_if_fail (fontsel != NULL, FALSE);
3390 g_return_val_if_fail (GTK_IS_FONT_SELECTION (fontsel), FALSE);
3391 g_return_val_if_fail (fontname != NULL, FALSE);
3393 /* Check it is a valid fontname. */
3394 if (!gtk_font_selection_is_xlfd_font_name(fontname))
3397 family = gtk_font_selection_get_xlfd_field (fontname, XLFD_FAMILY,
3402 field = gtk_font_selection_get_xlfd_field (fontname, XLFD_FOUNDRY,
3404 foundry = gtk_font_selection_field_to_index (fontsel_info->properties[FOUNDRY],
3405 fontsel_info->nproperties[FOUNDRY],
3408 index = gtk_font_selection_find_font(fontsel, family, foundry);
3412 /* Convert the property fields into indices and set them. */
3413 for (prop = 0; prop < GTK_NUM_STYLE_PROPERTIES; prop++)
3415 field = gtk_font_selection_get_xlfd_field (fontname, xlfd_index[prop],
3417 value = gtk_font_selection_field_to_index (fontsel_info->properties[prop],
3418 fontsel_info->nproperties[prop],
3420 fontsel->property_values[prop] = value;
3423 field = gtk_font_selection_get_xlfd_field (fontname, XLFD_POINTS,
3430 fontsel->size = fontsel->selected_size = size;
3431 fontsel->metric = GTK_FONT_METRIC_POINTS;
3432 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(fontsel->points_button),
3435 sprintf (buffer, "%i", size / 10);
3437 sprintf (buffer, "%i.%i", size / 10, size % 10);
3441 field = gtk_font_selection_get_xlfd_field (fontname, XLFD_PIXELS,
3446 fontsel->size = fontsel->selected_size = size;
3447 fontsel->metric = GTK_FONT_METRIC_PIXELS;
3448 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(fontsel->pixels_button),
3450 sprintf (buffer, "%i", size);
3452 gtk_entry_set_text (GTK_ENTRY (fontsel->size_entry), buffer);
3454 /* Clear any current filter. */
3455 gtk_font_selection_clear_filter(fontsel);
3457 /* Now find the best style match. */
3458 fontsel->font_index = index;
3459 gtk_clist_select_row(GTK_CLIST(fontsel->font_clist), index, 0);
3460 if (GTK_WIDGET_MAPPED (fontsel->font_clist))
3461 gtk_clist_moveto(GTK_CLIST(fontsel->font_clist), index, -1, 0.5, 0);
3463 gtk_font_selection_show_available_styles (fontsel);
3464 /* This will load the font. */
3465 gtk_font_selection_select_best_style (fontsel, FALSE);
3471 /* Returns the index of the given family, or -1 if not found */
3473 gtk_font_selection_find_font (GtkFontSelection *fontsel,
3477 FontInfo *font_info;
3478 gint lower, upper, middle = -1, cmp, nfonts;
3479 gint found_family = -1;
3481 font_info = fontsel_info->font_info;
3482 nfonts = fontsel_info->nfonts;
3486 /* Do a binary search to find the font family. */
3489 while (lower < upper)
3491 middle = (lower + upper) >> 1;
3493 cmp = strcmp (family, font_info[middle].family);
3496 found_family = middle;
3497 cmp = strcmp(fontsel_info->properties[FOUNDRY][foundry],
3498 fontsel_info->properties[FOUNDRY][font_info[middle].foundry]);
3509 /* We couldn't find the family and foundry, but we may have just found the
3510 family, so we return that. */
3511 return found_family;
3515 /* This returns the text in the preview entry. You should copy the returned
3516 text if you need it. */
3518 gtk_font_selection_get_preview_text (GtkFontSelection *fontsel)
3520 return gtk_entry_get_text(GTK_ENTRY(fontsel->preview_entry));
3524 /* This sets the text in the preview entry. */
3526 gtk_font_selection_set_preview_text (GtkFontSelection *fontsel,
3529 gtk_entry_set_text(GTK_ENTRY(fontsel->preview_entry), text);
3533 /*****************************************************************************
3534 * These functions all deal with X Logical Font Description (XLFD) fontnames.
3535 * See the freely available documentation about this.
3536 *****************************************************************************/
3539 * Returns TRUE if the fontname is a valid XLFD.
3540 * (It just checks if the number of dashes is 14, and that each
3541 * field < XLFD_MAX_FIELD_LEN characters long - that's not in the XLFD but it
3542 * makes it easier for me).
3545 gtk_font_selection_is_xlfd_font_name (const gchar *fontname)
3552 if (*fontname++ == '-')
3554 if (field_len > XLFD_MAX_FIELD_LEN) return FALSE;
3562 return (i == 14) ? TRUE : FALSE;
3566 * This fills the buffer with the specified field from the X Logical Font
3567 * Description name, and returns it. If fontname is NULL or the field is
3568 * longer than XFLD_MAX_FIELD_LEN it returns NULL.
3569 * Note: For the charset field, we also return the encoding, e.g. 'iso8859-1'.
3572 gtk_font_selection_get_xlfd_field (const gchar *fontname,
3573 FontField field_num,
3576 const gchar *t1, *t2;
3577 gint countdown, len, num_dashes;
3582 /* we assume this is a valid fontname...that is, it has 14 fields */
3584 countdown = field_num;
3586 while (*t1 && (countdown >= 0))
3590 num_dashes = (field_num == XLFD_CHARSET) ? 2 : 1;
3591 for (t2 = t1; *t2; t2++)
3593 if (*t2 == '-' && --num_dashes == 0)
3599 /* Check we don't overflow the buffer */
3600 len = (long) t2 - (long) t1;
3601 if (len > XLFD_MAX_FIELD_LEN - 1)
3603 strncpy (buffer, t1, len);
3606 /* Convert to lower case. */
3610 strcpy(buffer, "(nil)");
3616 * This returns a X Logical Font Description font name, given all the pieces.
3617 * Note: this retval must be freed by the caller.
3620 gtk_font_selection_create_xlfd (gint size,
3621 GtkFontMetricType metric,
3631 gchar *pixel_size = "*", *point_size = "*", *fontname;
3636 sprintf (buffer, "%d", (int) size);
3637 if (metric == GTK_FONT_METRIC_PIXELS)
3638 pixel_size = buffer;
3640 point_size = buffer;
3642 fontname = g_strdup_printf ("-%s-%s-%s-%s-%s-*-%s-%s-*-*-%s-*-%s",
3643 foundry, family, weight, slant,
3644 set_width, pixel_size, point_size,
3651 /*****************************************************************************
3652 * GtkFontSelectionDialog
3653 *****************************************************************************/
3656 gtk_font_selection_dialog_get_type (void)
3658 static guint font_selection_dialog_type = 0;
3660 if (!font_selection_dialog_type)
3662 GtkTypeInfo fontsel_diag_info =
3664 "GtkFontSelectionDialog",
3665 sizeof (GtkFontSelectionDialog),
3666 sizeof (GtkFontSelectionDialogClass),
3667 (GtkClassInitFunc) gtk_font_selection_dialog_class_init,
3668 (GtkObjectInitFunc) gtk_font_selection_dialog_init,
3669 /* reserved_1 */ NULL,
3670 /* reserved_2 */ NULL,
3671 (GtkClassInitFunc) NULL,
3674 font_selection_dialog_type = gtk_type_unique (GTK_TYPE_WINDOW, &fontsel_diag_info);
3677 return font_selection_dialog_type;
3681 gtk_font_selection_dialog_class_init (GtkFontSelectionDialogClass *klass)
3683 GtkObjectClass *object_class;
3685 object_class = (GtkObjectClass*) klass;
3687 font_selection_dialog_parent_class = gtk_type_class (GTK_TYPE_WINDOW);
3691 gtk_font_selection_dialog_init (GtkFontSelectionDialog *fontseldiag)
3693 fontseldiag->dialog_width = -1;
3694 fontseldiag->auto_resize = TRUE;
3696 gtk_widget_set_events(GTK_WIDGET(fontseldiag), GDK_STRUCTURE_MASK);
3697 gtk_signal_connect (GTK_OBJECT (fontseldiag), "configure_event",
3698 (GtkSignalFunc) gtk_font_selection_dialog_on_configure,
3701 gtk_container_set_border_width (GTK_CONTAINER (fontseldiag), 4);
3702 gtk_window_set_policy(GTK_WINDOW(fontseldiag), FALSE, TRUE, TRUE);
3704 fontseldiag->main_vbox = gtk_vbox_new (FALSE, 4);
3705 gtk_widget_show (fontseldiag->main_vbox);
3706 gtk_container_add (GTK_CONTAINER (fontseldiag), fontseldiag->main_vbox);
3708 fontseldiag->fontsel = gtk_font_selection_new();
3709 gtk_widget_show (fontseldiag->fontsel);
3710 gtk_box_pack_start (GTK_BOX (fontseldiag->main_vbox),
3711 fontseldiag->fontsel, TRUE, TRUE, 0);
3713 /* Create the action area */
3714 fontseldiag->action_area = gtk_hbutton_box_new ();
3715 gtk_button_box_set_layout(GTK_BUTTON_BOX(fontseldiag->action_area),
3717 gtk_button_box_set_spacing(GTK_BUTTON_BOX(fontseldiag->action_area), 5);
3718 gtk_box_pack_start (GTK_BOX (fontseldiag->main_vbox),
3719 fontseldiag->action_area, FALSE, FALSE, 0);
3720 gtk_widget_show (fontseldiag->action_area);
3722 fontseldiag->ok_button = gtk_button_new_with_label(_("OK"));
3723 GTK_WIDGET_SET_FLAGS (fontseldiag->ok_button, GTK_CAN_DEFAULT);
3724 gtk_widget_show(fontseldiag->ok_button);
3725 gtk_box_pack_start (GTK_BOX (fontseldiag->action_area),
3726 fontseldiag->ok_button, TRUE, TRUE, 0);
3727 gtk_widget_grab_default (fontseldiag->ok_button);
3729 fontseldiag->apply_button = gtk_button_new_with_label(_("Apply"));
3730 GTK_WIDGET_SET_FLAGS (fontseldiag->apply_button, GTK_CAN_DEFAULT);
3731 /*gtk_widget_show(fontseldiag->apply_button);*/
3732 gtk_box_pack_start (GTK_BOX(fontseldiag->action_area),
3733 fontseldiag->apply_button, TRUE, TRUE, 0);
3735 fontseldiag->cancel_button = gtk_button_new_with_label(_("Cancel"));
3736 GTK_WIDGET_SET_FLAGS (fontseldiag->cancel_button, GTK_CAN_DEFAULT);
3737 gtk_widget_show(fontseldiag->cancel_button);
3738 gtk_box_pack_start (GTK_BOX(fontseldiag->action_area),
3739 fontseldiag->cancel_button, TRUE, TRUE, 0);
3745 gtk_font_selection_dialog_new (const gchar *title)
3747 GtkFontSelectionDialog *fontseldiag;
3749 fontseldiag = gtk_type_new (GTK_TYPE_FONT_SELECTION_DIALOG);
3750 gtk_window_set_title (GTK_WINDOW (fontseldiag),
3751 title ? title : _("Font Selection"));
3753 return GTK_WIDGET (fontseldiag);
3757 gtk_font_selection_dialog_get_font_name (GtkFontSelectionDialog *fsd)
3759 return gtk_font_selection_get_font_name(GTK_FONT_SELECTION(fsd->fontsel));
3763 gtk_font_selection_dialog_get_font (GtkFontSelectionDialog *fsd)
3765 return gtk_font_selection_get_font(GTK_FONT_SELECTION(fsd->fontsel));
3769 gtk_font_selection_dialog_set_font_name (GtkFontSelectionDialog *fsd,
3770 const gchar *fontname)
3772 return gtk_font_selection_set_font_name(GTK_FONT_SELECTION(fsd->fontsel),
3777 gtk_font_selection_dialog_set_filter (GtkFontSelectionDialog *fsd,
3778 GtkFontFilterType filter_type,
3779 GtkFontType font_type,
3787 gtk_font_selection_set_filter (GTK_FONT_SELECTION (fsd->fontsel),
3788 filter_type, font_type,
3789 foundries, weights, slants, setwidths,
3790 spacings, charsets);
3794 gtk_font_selection_dialog_get_preview_text (GtkFontSelectionDialog *fsd)
3796 return gtk_font_selection_get_preview_text(GTK_FONT_SELECTION(fsd->fontsel));
3800 gtk_font_selection_dialog_set_preview_text (GtkFontSelectionDialog *fsd,
3803 gtk_font_selection_set_preview_text(GTK_FONT_SELECTION(fsd->fontsel), text);
3807 /* This turns auto-shrink off if the user resizes the width of the dialog.
3808 It also turns it back on again if the user resizes it back to its normal
3811 gtk_font_selection_dialog_on_configure (GtkWidget *widget,
3812 GdkEventConfigure *event,
3813 GtkFontSelectionDialog *fsd)
3815 /* This sets the initial width. */
3816 if (fsd->dialog_width == -1)
3817 fsd->dialog_width = event->width;
3818 else if (fsd->auto_resize && fsd->dialog_width != event->width)
3820 fsd->auto_resize = FALSE;
3821 gtk_window_set_policy(GTK_WINDOW(fsd), FALSE, TRUE, FALSE);
3823 else if (!fsd->auto_resize && fsd->dialog_width == event->width)
3825 fsd->auto_resize = TRUE;
3826 gtk_window_set_policy(GTK_WINDOW(fsd), FALSE, TRUE, TRUE);