1 | /* GTK - The GIMP Toolkit |
---|
2 | * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald |
---|
3 | * |
---|
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. |
---|
7 | * |
---|
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. |
---|
12 | * |
---|
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. |
---|
17 | * |
---|
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. |
---|
22 | */ |
---|
23 | |
---|
24 | /* |
---|
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/. |
---|
29 | */ |
---|
30 | |
---|
31 | /* |
---|
32 | * Limits: |
---|
33 | * |
---|
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 |
---|
41 | * ignored. |
---|
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). |
---|
49 | */ |
---|
50 | |
---|
51 | /* |
---|
52 | * Possible Improvements: |
---|
53 | * |
---|
54 | * Font Styles - could sort the styles into a reasonable order - regular |
---|
55 | * first, then bold, bold italic etc. |
---|
56 | * |
---|
57 | * I18N - the default preview text is not useful for international |
---|
58 | * fonts. Maybe the first few characters of the font could be |
---|
59 | * displayed instead. |
---|
60 | * - fontsets? should these be handled by the font dialog? |
---|
61 | */ |
---|
62 | |
---|
63 | /* |
---|
64 | * Debugging: compile with -DFONTSEL_DEBUG for lots of debugging output. |
---|
65 | */ |
---|
66 | |
---|
67 | |
---|
68 | #include <stdlib.h> |
---|
69 | #include <stdio.h> |
---|
70 | #include <string.h> |
---|
71 | #include <ctype.h> |
---|
72 | #include <X11/Xlib.h> |
---|
73 | |
---|
74 | #include "gdk/gdkx.h" |
---|
75 | #include "gdk/gdkkeysyms.h" |
---|
76 | |
---|
77 | #include "gtkbutton.h" |
---|
78 | #include "gtkcheckbutton.h" |
---|
79 | #include "gtkclist.h" |
---|
80 | #include "gtkentry.h" |
---|
81 | #include "gtkfontsel.h" |
---|
82 | #include "gtkframe.h" |
---|
83 | #include "gtkhbbox.h" |
---|
84 | #include "gtkhbox.h" |
---|
85 | #include "gtklabel.h" |
---|
86 | #include "gtknotebook.h" |
---|
87 | #include "gtkradiobutton.h" |
---|
88 | #include "gtksignal.h" |
---|
89 | #include "gtktable.h" |
---|
90 | #include "gtkvbox.h" |
---|
91 | #include "gtkscrolledwindow.h" |
---|
92 | #include "gtkintl.h" |
---|
93 | |
---|
94 | /* The maximum number of fontnames requested with XListFonts(). */ |
---|
95 | #define MAX_FONTS 32767 |
---|
96 | |
---|
97 | /* This is the largest field length we will accept. If a fontname has a field |
---|
98 | larger than this we will skip it. */ |
---|
99 | #define XLFD_MAX_FIELD_LEN 64 |
---|
100 | |
---|
101 | /* These are what we use as the standard font sizes, for the size clist. |
---|
102 | Note that when using points we still show these integer point values but |
---|
103 | we work internally in decipoints (and decipoint values can be typed in). */ |
---|
104 | static const guint16 font_sizes[] = { |
---|
105 | 8, 9, 10, 11, 12, 13, 14, 16, 18, 20, 22, 24, 26, 28, |
---|
106 | 32, 36, 40, 48, 56, 64, 72 |
---|
107 | }; |
---|
108 | |
---|
109 | /* Initial font metric & size (Remember point sizes are in decipoints). |
---|
110 | The font size should match one of those in the font_sizes array. */ |
---|
111 | #define INITIAL_METRIC GTK_FONT_METRIC_POINTS |
---|
112 | #define INITIAL_FONT_SIZE 140 |
---|
113 | |
---|
114 | /* This is the default text shown in the preview entry, though the user |
---|
115 | can set it. Remember that some fonts only have capital letters. */ |
---|
116 | #define PREVIEW_TEXT "abcdefghijk ABCDEFGHIJK" |
---|
117 | |
---|
118 | /* This is the initial and maximum height of the preview entry (it expands |
---|
119 | when large font sizes are selected). Initial height is also the minimum. */ |
---|
120 | #define INITIAL_PREVIEW_HEIGHT 44 |
---|
121 | #define MAX_PREVIEW_HEIGHT 300 |
---|
122 | |
---|
123 | /* These are the sizes of the font, style & size clists. */ |
---|
124 | #define FONT_LIST_HEIGHT 136 |
---|
125 | #define FONT_LIST_WIDTH 190 |
---|
126 | #define FONT_STYLE_LIST_WIDTH 170 |
---|
127 | #define FONT_SIZE_LIST_WIDTH 60 |
---|
128 | |
---|
129 | /* This is the number of fields in an X Logical Font Description font name. |
---|
130 | Note that we count the registry & encoding as 1. */ |
---|
131 | #define GTK_XLFD_NUM_FIELDS 13 |
---|
132 | |
---|
133 | typedef struct _GtkFontSelInfo GtkFontSelInfo; |
---|
134 | typedef struct _FontInfo FontInfo; |
---|
135 | typedef struct _FontStyle FontStyle; |
---|
136 | |
---|
137 | /* This struct represents one family of fonts (with one foundry), e.g. adobe |
---|
138 | courier or sony fixed. It stores the family name, the index of the foundry |
---|
139 | name, and the index of and number of available styles. */ |
---|
140 | struct _FontInfo |
---|
141 | { |
---|
142 | gchar *family; |
---|
143 | guint16 foundry; |
---|
144 | gint style_index; |
---|
145 | guint16 nstyles; |
---|
146 | }; |
---|
147 | |
---|
148 | /* This represents one style, as displayed in the Font Style clist. It can |
---|
149 | have a number of available pixel sizes and point sizes. The indexes point |
---|
150 | into the two big fontsel_info->pixel_sizes & fontsel_info->point_sizes |
---|
151 | arrays. The displayed flag is used when displaying styles to remember which |
---|
152 | styles have already been displayed. Note that it is combined with the |
---|
153 | GtkFontType in the flags field. */ |
---|
154 | #define GTK_FONT_DISPLAYED (1 << 7) |
---|
155 | struct _FontStyle |
---|
156 | { |
---|
157 | guint16 properties[GTK_NUM_STYLE_PROPERTIES]; |
---|
158 | gint pixel_sizes_index; |
---|
159 | guint16 npixel_sizes; |
---|
160 | gint point_sizes_index; |
---|
161 | guint16 npoint_sizes; |
---|
162 | guint8 flags; |
---|
163 | }; |
---|
164 | |
---|
165 | struct _GtkFontSelInfo { |
---|
166 | |
---|
167 | /* This is a table with each FontInfo representing one font family+foundry */ |
---|
168 | FontInfo *font_info; |
---|
169 | gint nfonts; |
---|
170 | |
---|
171 | /* This stores all the valid combinations of properties for every family. |
---|
172 | Each FontInfo holds an index into its own space in this one big array. */ |
---|
173 | FontStyle *font_styles; |
---|
174 | gint nstyles; |
---|
175 | |
---|
176 | /* This stores all the font sizes available for every style. |
---|
177 | Each style holds an index into these arrays. */ |
---|
178 | guint16 *pixel_sizes; |
---|
179 | guint16 *point_sizes; |
---|
180 | |
---|
181 | /* These are the arrays of strings of all possible weights, slants, |
---|
182 | set widths, spacings, charsets & foundries, and the amount of space |
---|
183 | allocated for each array. */ |
---|
184 | gchar **properties[GTK_NUM_FONT_PROPERTIES]; |
---|
185 | guint16 nproperties[GTK_NUM_FONT_PROPERTIES]; |
---|
186 | guint16 space_allocated[GTK_NUM_FONT_PROPERTIES]; |
---|
187 | }; |
---|
188 | |
---|
189 | /* These are the field numbers in the X Logical Font Description fontnames, |
---|
190 | e.g. -adobe-courier-bold-o-normal--25-180-100-100-m-150-iso8859-1 */ |
---|
191 | typedef enum |
---|
192 | { |
---|
193 | XLFD_FOUNDRY = 0, |
---|
194 | XLFD_FAMILY = 1, |
---|
195 | XLFD_WEIGHT = 2, |
---|
196 | XLFD_SLANT = 3, |
---|
197 | XLFD_SET_WIDTH = 4, |
---|
198 | XLFD_ADD_STYLE = 5, |
---|
199 | XLFD_PIXELS = 6, |
---|
200 | XLFD_POINTS = 7, |
---|
201 | XLFD_RESOLUTION_X = 8, |
---|
202 | XLFD_RESOLUTION_Y = 9, |
---|
203 | XLFD_SPACING = 10, |
---|
204 | XLFD_AVERAGE_WIDTH = 11, |
---|
205 | XLFD_CHARSET = 12 |
---|
206 | } FontField; |
---|
207 | |
---|
208 | /* These are the names of the fields, used on the info & filter page. */ |
---|
209 | static const gchar* xlfd_field_names[GTK_XLFD_NUM_FIELDS] = { |
---|
210 | N_("Foundry:"), |
---|
211 | N_("Family:"), |
---|
212 | N_("Weight:"), |
---|
213 | N_("Slant:"), |
---|
214 | N_("Set Width:"), |
---|
215 | N_("Add Style:"), |
---|
216 | N_("Pixel Size:"), |
---|
217 | N_("Point Size:"), |
---|
218 | N_("Resolution X:"), |
---|
219 | N_("Resolution Y:"), |
---|
220 | N_("Spacing:"), |
---|
221 | N_("Average Width:"), |
---|
222 | N_("Charset:"), |
---|
223 | }; |
---|
224 | |
---|
225 | /* These are the array indices of the font properties used in several arrays, |
---|
226 | and should match the xlfd_index array below. */ |
---|
227 | typedef enum |
---|
228 | { |
---|
229 | WEIGHT = 0, |
---|
230 | SLANT = 1, |
---|
231 | SET_WIDTH = 2, |
---|
232 | SPACING = 3, |
---|
233 | CHARSET = 4, |
---|
234 | FOUNDRY = 5 |
---|
235 | } PropertyIndexType; |
---|
236 | |
---|
237 | /* This is used to look up a field in a fontname given one of the above |
---|
238 | property indices. */ |
---|
239 | static const FontField xlfd_index[GTK_NUM_FONT_PROPERTIES] = { |
---|
240 | XLFD_WEIGHT, |
---|
241 | XLFD_SLANT, |
---|
242 | XLFD_SET_WIDTH, |
---|
243 | XLFD_SPACING, |
---|
244 | XLFD_CHARSET, |
---|
245 | XLFD_FOUNDRY |
---|
246 | }; |
---|
247 | |
---|
248 | /* These are the positions of the properties in the filter table - x, y. */ |
---|
249 | static const gint filter_positions[GTK_NUM_FONT_PROPERTIES][2] = { |
---|
250 | { 1, 0 }, { 0, 2 }, { 1, 2 }, { 2, 2 }, { 2, 0 }, { 0, 0 } |
---|
251 | }; |
---|
252 | static const gint filter_heights[GTK_NUM_FONT_PROPERTIES] = { |
---|
253 | 100, 70, 70, 40, 100, 100 |
---|
254 | }; |
---|
255 | |
---|
256 | /* This is returned by gtk_font_selection_filter_state to describe if a |
---|
257 | property value is filtered. e.g. if 'bold' has been selected on the filter |
---|
258 | page, then that will return 'FILTERED' and 'black' will be 'NOT_FILTERED'. |
---|
259 | If none of the weight values are selected, they all return 'NOT_SET'. */ |
---|
260 | typedef enum |
---|
261 | { |
---|
262 | FILTERED, |
---|
263 | NOT_FILTERED, |
---|
264 | NOT_SET |
---|
265 | } GtkFontPropertyFilterState; |
---|
266 | |
---|
267 | static GtkFontSelInfo *fontsel_info = NULL; |
---|
268 | |
---|
269 | /* The initial size and increment of each of the arrays of property values. */ |
---|
270 | #define PROPERTY_ARRAY_INCREMENT 16 |
---|
271 | |
---|
272 | static void gtk_font_selection_class_init (GtkFontSelectionClass *klass); |
---|
273 | static void gtk_font_selection_init (GtkFontSelection *fontsel); |
---|
274 | static void gtk_font_selection_destroy (GtkObject *object); |
---|
275 | |
---|
276 | /* These are all used for class initialization - loading in the fonts etc. */ |
---|
277 | static void gtk_font_selection_get_fonts (void); |
---|
278 | static void gtk_font_selection_insert_font (GSList *fontnames[], |
---|
279 | gint *ntable, |
---|
280 | gchar *fontname); |
---|
281 | static gint gtk_font_selection_insert_field (gchar *fontname, |
---|
282 | gint prop); |
---|
283 | |
---|
284 | /* These are the callbacks & related functions. */ |
---|
285 | static void gtk_font_selection_select_font (GtkWidget *w, |
---|
286 | gint row, |
---|
287 | gint column, |
---|
288 | GdkEventButton *bevent, |
---|
289 | gpointer data); |
---|
290 | static gint gtk_font_selection_on_clist_key_press (GtkWidget *clist, |
---|
291 | GdkEventKey *event, |
---|
292 | GtkFontSelection *fs); |
---|
293 | static gboolean gtk_font_selection_select_next (GtkFontSelection *fs, |
---|
294 | GtkWidget *clist, |
---|
295 | gint step); |
---|
296 | static void gtk_font_selection_show_available_styles |
---|
297 | (GtkFontSelection *fs); |
---|
298 | static void gtk_font_selection_select_best_style (GtkFontSelection *fs, |
---|
299 | gboolean use_first); |
---|
300 | |
---|
301 | static void gtk_font_selection_select_style (GtkWidget *w, |
---|
302 | gint row, |
---|
303 | gint column, |
---|
304 | GdkEventButton *bevent, |
---|
305 | gpointer data); |
---|
306 | static void gtk_font_selection_show_available_sizes |
---|
307 | (GtkFontSelection *fs); |
---|
308 | static void gtk_font_selection_size_activate (GtkWidget *w, |
---|
309 | gpointer data); |
---|
310 | |
---|
311 | static void gtk_font_selection_select_best_size (GtkFontSelection *fs); |
---|
312 | static void gtk_font_selection_select_size (GtkWidget *w, |
---|
313 | gint row, |
---|
314 | gint column, |
---|
315 | GdkEventButton *bevent, |
---|
316 | gpointer data); |
---|
317 | |
---|
318 | static void gtk_font_selection_metric_callback (GtkWidget *w, |
---|
319 | gpointer data); |
---|
320 | static void gtk_font_selection_expose_list (GtkWidget *w, |
---|
321 | GdkEventExpose *event, |
---|
322 | gpointer data); |
---|
323 | static void gtk_font_selection_realize_list (GtkWidget *widget, |
---|
324 | gpointer data); |
---|
325 | |
---|
326 | static void gtk_font_selection_switch_page (GtkWidget *w, |
---|
327 | GtkNotebookPage *page, |
---|
328 | gint page_num, |
---|
329 | gpointer data); |
---|
330 | static void gtk_font_selection_show_font_info (GtkFontSelection *fs); |
---|
331 | |
---|
332 | static void gtk_font_selection_select_filter (GtkWidget *w, |
---|
333 | gint row, |
---|
334 | gint column, |
---|
335 | GdkEventButton *bevent, |
---|
336 | GtkFontSelection *fs); |
---|
337 | static void gtk_font_selection_unselect_filter (GtkWidget *w, |
---|
338 | gint row, |
---|
339 | gint column, |
---|
340 | GdkEventButton *bevent, |
---|
341 | GtkFontSelection *fs); |
---|
342 | static void gtk_font_selection_update_filter (GtkFontSelection *fs); |
---|
343 | static gboolean gtk_font_selection_style_visible (GtkFontSelection *fs, |
---|
344 | FontInfo *font, |
---|
345 | gint style); |
---|
346 | static void gtk_font_selection_reset_filter (GtkWidget *w, |
---|
347 | GtkFontSelection *fs); |
---|
348 | static void gtk_font_selection_on_clear_filter (GtkWidget *w, |
---|
349 | GtkFontSelection *fs); |
---|
350 | static void gtk_font_selection_show_available_fonts |
---|
351 | (GtkFontSelection *fs); |
---|
352 | static void gtk_font_selection_clear_filter (GtkFontSelection *fs); |
---|
353 | static void gtk_font_selection_update_filter_lists(GtkFontSelection *fs); |
---|
354 | static GtkFontPropertyFilterState gtk_font_selection_filter_state |
---|
355 | (GtkFontSelection *fs, |
---|
356 | GtkFontFilterType filter_type, |
---|
357 | gint property, |
---|
358 | gint index); |
---|
359 | |
---|
360 | /* Misc. utility functions. */ |
---|
361 | static gboolean gtk_font_selection_load_font (GtkFontSelection *fs); |
---|
362 | static void gtk_font_selection_update_preview (GtkFontSelection *fs); |
---|
363 | |
---|
364 | static gint gtk_font_selection_find_font (GtkFontSelection *fs, |
---|
365 | gchar *family, |
---|
366 | guint16 foundry); |
---|
367 | static guint16 gtk_font_selection_field_to_index (gchar **table, |
---|
368 | gint ntable, |
---|
369 | gchar *field); |
---|
370 | |
---|
371 | static gchar* gtk_font_selection_expand_slant_code (gchar *slant); |
---|
372 | static gchar* gtk_font_selection_expand_spacing_code(gchar *spacing); |
---|
373 | |
---|
374 | /* Functions for handling X Logical Font Description fontnames. */ |
---|
375 | static gboolean gtk_font_selection_is_xlfd_font_name (const gchar *fontname); |
---|
376 | static char* gtk_font_selection_get_xlfd_field (const gchar *fontname, |
---|
377 | FontField field_num, |
---|
378 | gchar *buffer); |
---|
379 | static gchar * gtk_font_selection_create_xlfd (gint size, |
---|
380 | GtkFontMetricType metric, |
---|
381 | gchar *foundry, |
---|
382 | gchar *family, |
---|
383 | gchar *weight, |
---|
384 | gchar *slant, |
---|
385 | gchar *set_width, |
---|
386 | gchar *spacing, |
---|
387 | gchar *charset); |
---|
388 | |
---|
389 | |
---|
390 | /* FontSelectionDialog */ |
---|
391 | static void gtk_font_selection_dialog_class_init (GtkFontSelectionDialogClass *klass); |
---|
392 | static void gtk_font_selection_dialog_init (GtkFontSelectionDialog *fontseldiag); |
---|
393 | |
---|
394 | static gint gtk_font_selection_dialog_on_configure(GtkWidget *widget, |
---|
395 | GdkEventConfigure *event, |
---|
396 | GtkFontSelectionDialog *fsd); |
---|
397 | |
---|
398 | static GtkWindowClass *font_selection_parent_class = NULL; |
---|
399 | static GtkNotebookClass *font_selection_dialog_parent_class = NULL; |
---|
400 | |
---|
401 | GtkType |
---|
402 | gtk_font_selection_get_type() |
---|
403 | { |
---|
404 | static GtkType font_selection_type = 0; |
---|
405 | |
---|
406 | if(!font_selection_type) |
---|
407 | { |
---|
408 | static const GtkTypeInfo fontsel_type_info = |
---|
409 | { |
---|
410 | "GtkFontSelection", |
---|
411 | sizeof (GtkFontSelection), |
---|
412 | sizeof (GtkFontSelectionClass), |
---|
413 | (GtkClassInitFunc) gtk_font_selection_class_init, |
---|
414 | (GtkObjectInitFunc) gtk_font_selection_init, |
---|
415 | /* reserved_1 */ NULL, |
---|
416 | /* reserved_2 */ NULL, |
---|
417 | (GtkClassInitFunc) NULL, |
---|
418 | }; |
---|
419 | |
---|
420 | font_selection_type = gtk_type_unique (GTK_TYPE_NOTEBOOK, |
---|
421 | &fontsel_type_info); |
---|
422 | } |
---|
423 | |
---|
424 | return font_selection_type; |
---|
425 | } |
---|
426 | |
---|
427 | static void |
---|
428 | gtk_font_selection_class_init(GtkFontSelectionClass *klass) |
---|
429 | { |
---|
430 | GtkObjectClass *object_class; |
---|
431 | |
---|
432 | object_class = (GtkObjectClass *) klass; |
---|
433 | |
---|
434 | font_selection_parent_class = gtk_type_class (GTK_TYPE_NOTEBOOK); |
---|
435 | |
---|
436 | object_class->destroy = gtk_font_selection_destroy; |
---|
437 | |
---|
438 | gtk_font_selection_get_fonts (); |
---|
439 | } |
---|
440 | |
---|
441 | static void |
---|
442 | gtk_font_selection_init(GtkFontSelection *fontsel) |
---|
443 | { |
---|
444 | GtkWidget *scrolled_win; |
---|
445 | GtkWidget *text_frame; |
---|
446 | GtkWidget *text_box, *frame; |
---|
447 | GtkWidget *table, *label, *hbox, *hbox2, *clist, *button, *vbox, *alignment; |
---|
448 | gint i, prop, row; |
---|
449 | gchar *titles[] = { NULL, NULL, NULL }; |
---|
450 | gchar buffer[128]; |
---|
451 | gchar *size; |
---|
452 | gint size_to_match; |
---|
453 | gchar *row_text[3]; |
---|
454 | gchar *property, *text; |
---|
455 | gboolean inserted; |
---|
456 | |
---|
457 | /* Number of internationalized titles here must match number |
---|
458 | of NULL initializers above */ |
---|
459 | titles[0] = _("Font Property"); |
---|
460 | titles[1] = _("Requested Value"); |
---|
461 | titles[2] = _("Actual Value"); |
---|
462 | |
---|
463 | /* Initialize the GtkFontSelection struct. We do this here in case any |
---|
464 | callbacks are triggered while creating the interface. */ |
---|
465 | fontsel->font = NULL; |
---|
466 | fontsel->font_index = -1; |
---|
467 | fontsel->style = -1; |
---|
468 | fontsel->metric = INITIAL_METRIC; |
---|
469 | fontsel->size = INITIAL_FONT_SIZE; |
---|
470 | fontsel->selected_size = INITIAL_FONT_SIZE; |
---|
471 | |
---|
472 | fontsel->filters[GTK_FONT_FILTER_BASE].font_type = GTK_FONT_ALL; |
---|
473 | fontsel->filters[GTK_FONT_FILTER_USER].font_type = GTK_FONT_BITMAP |
---|
474 | | GTK_FONT_SCALABLE; |
---|
475 | |
---|
476 | |
---|
477 | for (prop = 0; prop < GTK_NUM_FONT_PROPERTIES; prop++) |
---|
478 | { |
---|
479 | fontsel->filters[GTK_FONT_FILTER_BASE].property_filters[prop] = NULL; |
---|
480 | fontsel->filters[GTK_FONT_FILTER_BASE].property_nfilters[prop] = 0; |
---|
481 | fontsel->filters[GTK_FONT_FILTER_USER].property_filters[prop] = NULL; |
---|
482 | fontsel->filters[GTK_FONT_FILTER_USER].property_nfilters[prop] = 0; |
---|
483 | } |
---|
484 | |
---|
485 | for (prop = 0; prop < GTK_NUM_STYLE_PROPERTIES; prop++) |
---|
486 | fontsel->property_values[prop] = 0; |
---|
487 | |
---|
488 | /* Create the main notebook page. */ |
---|
489 | gtk_notebook_set_homogeneous_tabs (GTK_NOTEBOOK (fontsel), TRUE); |
---|
490 | gtk_notebook_set_tab_hborder (GTK_NOTEBOOK (fontsel), 8); |
---|
491 | fontsel->main_vbox = gtk_vbox_new (FALSE, 4); |
---|
492 | gtk_widget_show (fontsel->main_vbox); |
---|
493 | gtk_container_set_border_width (GTK_CONTAINER (fontsel->main_vbox), 6); |
---|
494 | label = gtk_label_new(_("Font")); |
---|
495 | gtk_notebook_append_page (GTK_NOTEBOOK (fontsel), |
---|
496 | fontsel->main_vbox, label); |
---|
497 | |
---|
498 | /* Create the table of font, style & size. */ |
---|
499 | table = gtk_table_new (3, 3, FALSE); |
---|
500 | gtk_widget_show (table); |
---|
501 | gtk_table_set_col_spacings(GTK_TABLE(table), 8); |
---|
502 | gtk_box_pack_start (GTK_BOX (fontsel->main_vbox), table, TRUE, TRUE, 0); |
---|
503 | |
---|
504 | fontsel->font_label = gtk_label_new(_("Font:")); |
---|
505 | gtk_misc_set_alignment (GTK_MISC (fontsel->font_label), 0.0, 0.5); |
---|
506 | gtk_widget_show (fontsel->font_label); |
---|
507 | gtk_table_attach (GTK_TABLE (table), fontsel->font_label, 0, 1, 0, 1, |
---|
508 | GTK_FILL, 0, 0, 0); |
---|
509 | label = gtk_label_new(_("Font Style:")); |
---|
510 | gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); |
---|
511 | gtk_widget_show (label); |
---|
512 | gtk_table_attach (GTK_TABLE (table), label, 1, 2, 0, 1, |
---|
513 | GTK_FILL, 0, 0, 0); |
---|
514 | label = gtk_label_new(_("Size:")); |
---|
515 | gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); |
---|
516 | gtk_widget_show (label); |
---|
517 | gtk_table_attach (GTK_TABLE (table), label, 2, 3, 0, 1, |
---|
518 | GTK_FILL, 0, 0, 0); |
---|
519 | |
---|
520 | fontsel->font_entry = gtk_entry_new(); |
---|
521 | gtk_entry_set_editable(GTK_ENTRY(fontsel->font_entry), FALSE); |
---|
522 | gtk_widget_set_usize (fontsel->font_entry, 20, -1); |
---|
523 | gtk_widget_show (fontsel->font_entry); |
---|
524 | gtk_table_attach (GTK_TABLE (table), fontsel->font_entry, 0, 1, 1, 2, |
---|
525 | GTK_FILL, 0, 0, 0); |
---|
526 | fontsel->font_style_entry = gtk_entry_new(); |
---|
527 | gtk_entry_set_editable(GTK_ENTRY(fontsel->font_style_entry), FALSE); |
---|
528 | gtk_widget_set_usize (fontsel->font_style_entry, 20, -1); |
---|
529 | gtk_widget_show (fontsel->font_style_entry); |
---|
530 | gtk_table_attach (GTK_TABLE (table), fontsel->font_style_entry, 1, 2, 1, 2, |
---|
531 | GTK_FILL, 0, 0, 0); |
---|
532 | fontsel->size_entry = gtk_entry_new(); |
---|
533 | gtk_widget_set_usize (fontsel->size_entry, 20, -1); |
---|
534 | gtk_widget_show (fontsel->size_entry); |
---|
535 | gtk_table_attach (GTK_TABLE (table), fontsel->size_entry, 2, 3, 1, 2, |
---|
536 | GTK_FILL, 0, 0, 0); |
---|
537 | gtk_signal_connect (GTK_OBJECT (fontsel->size_entry), "activate", |
---|
538 | GTK_SIGNAL_FUNC (gtk_font_selection_size_activate), |
---|
539 | fontsel); |
---|
540 | |
---|
541 | /* Create the clists */ |
---|
542 | fontsel->font_clist = gtk_clist_new(1); |
---|
543 | gtk_clist_column_titles_hide (GTK_CLIST(fontsel->font_clist)); |
---|
544 | gtk_clist_set_column_auto_resize (GTK_CLIST (fontsel->font_clist), 0, TRUE); |
---|
545 | scrolled_win = gtk_scrolled_window_new (NULL, NULL); |
---|
546 | gtk_widget_set_usize (scrolled_win, FONT_LIST_WIDTH, FONT_LIST_HEIGHT); |
---|
547 | gtk_container_add (GTK_CONTAINER (scrolled_win), fontsel->font_clist); |
---|
548 | gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win), |
---|
549 | GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS); |
---|
550 | gtk_widget_show(fontsel->font_clist); |
---|
551 | gtk_widget_show(scrolled_win); |
---|
552 | |
---|
553 | gtk_table_attach (GTK_TABLE (table), scrolled_win, 0, 1, 2, 3, |
---|
554 | GTK_EXPAND | GTK_FILL, |
---|
555 | GTK_EXPAND | GTK_FILL, 0, 0); |
---|
556 | |
---|
557 | fontsel->font_style_clist = gtk_clist_new(1); |
---|
558 | gtk_clist_column_titles_hide (GTK_CLIST(fontsel->font_style_clist)); |
---|
559 | gtk_clist_set_column_auto_resize (GTK_CLIST (fontsel->font_style_clist), |
---|
560 | 0, TRUE); |
---|
561 | scrolled_win = gtk_scrolled_window_new (NULL, NULL); |
---|
562 | gtk_widget_set_usize (scrolled_win, FONT_STYLE_LIST_WIDTH, -1); |
---|
563 | gtk_container_add (GTK_CONTAINER (scrolled_win), fontsel->font_style_clist); |
---|
564 | gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win), |
---|
565 | GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS); |
---|
566 | gtk_widget_show(fontsel->font_style_clist); |
---|
567 | gtk_widget_show(scrolled_win); |
---|
568 | gtk_table_attach (GTK_TABLE (table), scrolled_win, 1, 2, 2, 3, |
---|
569 | GTK_EXPAND | GTK_FILL, |
---|
570 | GTK_EXPAND | GTK_FILL, 0, 0); |
---|
571 | |
---|
572 | fontsel->size_clist = gtk_clist_new(1); |
---|
573 | gtk_clist_column_titles_hide (GTK_CLIST(fontsel->size_clist)); |
---|
574 | gtk_clist_set_column_width (GTK_CLIST(fontsel->size_clist), 0, 20); |
---|
575 | scrolled_win = gtk_scrolled_window_new (NULL, NULL); |
---|
576 | gtk_widget_set_usize (scrolled_win, FONT_SIZE_LIST_WIDTH, -1); |
---|
577 | gtk_container_add (GTK_CONTAINER (scrolled_win), fontsel->size_clist); |
---|
578 | gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win), |
---|
579 | GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS); |
---|
580 | gtk_widget_show(fontsel->size_clist); |
---|
581 | gtk_widget_show(scrolled_win); |
---|
582 | gtk_table_attach (GTK_TABLE (table), scrolled_win, 2, 3, 2, 3, |
---|
583 | GTK_FILL, GTK_FILL, 0, 0); |
---|
584 | |
---|
585 | |
---|
586 | /* Insert the fonts. If there exist fonts with the same family but |
---|
587 | different foundries, then the foundry name is appended in brackets. */ |
---|
588 | gtk_font_selection_show_available_fonts(fontsel); |
---|
589 | |
---|
590 | gtk_signal_connect (GTK_OBJECT (fontsel->font_clist), "select_row", |
---|
591 | GTK_SIGNAL_FUNC(gtk_font_selection_select_font), |
---|
592 | fontsel); |
---|
593 | GTK_WIDGET_SET_FLAGS (fontsel->font_clist, GTK_CAN_FOCUS); |
---|
594 | gtk_signal_connect (GTK_OBJECT (fontsel->font_clist), "key_press_event", |
---|
595 | GTK_SIGNAL_FUNC(gtk_font_selection_on_clist_key_press), |
---|
596 | fontsel); |
---|
597 | gtk_signal_connect_after (GTK_OBJECT (fontsel->font_clist), "expose_event", |
---|
598 | GTK_SIGNAL_FUNC(gtk_font_selection_expose_list), |
---|
599 | fontsel); |
---|
600 | |
---|
601 | gtk_signal_connect (GTK_OBJECT (fontsel->font_style_clist), "select_row", |
---|
602 | GTK_SIGNAL_FUNC(gtk_font_selection_select_style), |
---|
603 | fontsel); |
---|
604 | GTK_WIDGET_SET_FLAGS (fontsel->font_style_clist, GTK_CAN_FOCUS); |
---|
605 | gtk_signal_connect (GTK_OBJECT (fontsel->font_style_clist), |
---|
606 | "key_press_event", |
---|
607 | GTK_SIGNAL_FUNC(gtk_font_selection_on_clist_key_press), |
---|
608 | fontsel); |
---|
609 | gtk_signal_connect_after (GTK_OBJECT (fontsel->font_style_clist), |
---|
610 | "realize", |
---|
611 | GTK_SIGNAL_FUNC(gtk_font_selection_realize_list), |
---|
612 | fontsel); |
---|
613 | |
---|
614 | /* Insert the standard font sizes */ |
---|
615 | gtk_clist_freeze (GTK_CLIST(fontsel->size_clist)); |
---|
616 | size_to_match = INITIAL_FONT_SIZE; |
---|
617 | if (INITIAL_METRIC == GTK_FONT_METRIC_POINTS) |
---|
618 | size_to_match = size_to_match / 10; |
---|
619 | for (i = 0; i < sizeof(font_sizes) / sizeof(font_sizes[0]); i++) |
---|
620 | { |
---|
621 | sprintf(buffer, "%i", font_sizes[i]); |
---|
622 | size = buffer; |
---|
623 | gtk_clist_append(GTK_CLIST(fontsel->size_clist), &size); |
---|
624 | if (font_sizes[i] == size_to_match) |
---|
625 | { |
---|
626 | gtk_clist_select_row(GTK_CLIST(fontsel->size_clist), i, 0); |
---|
627 | gtk_entry_set_text(GTK_ENTRY(fontsel->size_entry), buffer); |
---|
628 | } |
---|
629 | } |
---|
630 | gtk_clist_thaw (GTK_CLIST(fontsel->size_clist)); |
---|
631 | |
---|
632 | gtk_signal_connect (GTK_OBJECT (fontsel->size_clist), "select_row", |
---|
633 | GTK_SIGNAL_FUNC(gtk_font_selection_select_size), |
---|
634 | fontsel); |
---|
635 | GTK_WIDGET_SET_FLAGS (fontsel->size_clist, GTK_CAN_FOCUS); |
---|
636 | gtk_signal_connect (GTK_OBJECT (fontsel->size_clist), "key_press_event", |
---|
637 | GTK_SIGNAL_FUNC(gtk_font_selection_on_clist_key_press), |
---|
638 | fontsel); |
---|
639 | |
---|
640 | |
---|
641 | /* create the Reset Filter & Metric buttons */ |
---|
642 | hbox = gtk_hbox_new(FALSE, 8); |
---|
643 | gtk_widget_show (hbox); |
---|
644 | gtk_box_pack_start (GTK_BOX (fontsel->main_vbox), hbox, FALSE, TRUE, 0); |
---|
645 | |
---|
646 | fontsel->filter_button = gtk_button_new_with_label(_("Reset Filter")); |
---|
647 | gtk_misc_set_padding (GTK_MISC (GTK_BIN (fontsel->filter_button)->child), |
---|
648 | 16, 0); |
---|
649 | gtk_widget_show(fontsel->filter_button); |
---|
650 | gtk_box_pack_start (GTK_BOX (hbox), fontsel->filter_button, FALSE, FALSE, 0); |
---|
651 | gtk_widget_set_sensitive (fontsel->filter_button, FALSE); |
---|
652 | gtk_signal_connect (GTK_OBJECT (fontsel->filter_button), "clicked", |
---|
653 | GTK_SIGNAL_FUNC(gtk_font_selection_on_clear_filter), |
---|
654 | fontsel); |
---|
655 | |
---|
656 | hbox2 = gtk_hbox_new(FALSE, 0); |
---|
657 | gtk_widget_show (hbox2); |
---|
658 | gtk_box_pack_end (GTK_BOX (hbox), hbox2, FALSE, FALSE, 0); |
---|
659 | |
---|
660 | label = gtk_label_new(_("Metric:")); |
---|
661 | gtk_widget_show (label); |
---|
662 | gtk_box_pack_start (GTK_BOX (hbox2), label, FALSE, TRUE, 8); |
---|
663 | |
---|
664 | fontsel->points_button = gtk_radio_button_new_with_label(NULL, _("Points")); |
---|
665 | gtk_widget_show (fontsel->points_button); |
---|
666 | gtk_box_pack_start (GTK_BOX (hbox2), fontsel->points_button, FALSE, TRUE, 0); |
---|
667 | if (INITIAL_METRIC == GTK_FONT_METRIC_POINTS) |
---|
668 | gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(fontsel->points_button), |
---|
669 | TRUE); |
---|
670 | |
---|
671 | fontsel->pixels_button = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(fontsel->points_button), _("Pixels")); |
---|
672 | gtk_widget_show (fontsel->pixels_button); |
---|
673 | gtk_box_pack_start (GTK_BOX (hbox2), fontsel->pixels_button, FALSE, TRUE, 0); |
---|
674 | if (INITIAL_METRIC == GTK_FONT_METRIC_PIXELS) |
---|
675 | gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(fontsel->pixels_button), |
---|
676 | TRUE); |
---|
677 | |
---|
678 | gtk_signal_connect(GTK_OBJECT(fontsel->points_button), "toggled", |
---|
679 | (GtkSignalFunc) gtk_font_selection_metric_callback, |
---|
680 | fontsel); |
---|
681 | gtk_signal_connect(GTK_OBJECT(fontsel->pixels_button), "toggled", |
---|
682 | (GtkSignalFunc) gtk_font_selection_metric_callback, |
---|
683 | fontsel); |
---|
684 | |
---|
685 | |
---|
686 | /* create the text entry widget */ |
---|
687 | text_frame = gtk_frame_new (_("Preview:")); |
---|
688 | gtk_widget_show (text_frame); |
---|
689 | gtk_frame_set_shadow_type(GTK_FRAME(text_frame), GTK_SHADOW_ETCHED_IN); |
---|
690 | gtk_box_pack_start (GTK_BOX (fontsel->main_vbox), text_frame, |
---|
691 | FALSE, TRUE, 0); |
---|
692 | |
---|
693 | /* This is just used to get a 4-pixel space around the preview entry. */ |
---|
694 | text_box = gtk_hbox_new (FALSE, 0); |
---|
695 | gtk_widget_show (text_box); |
---|
696 | gtk_container_add (GTK_CONTAINER (text_frame), text_box); |
---|
697 | gtk_container_set_border_width (GTK_CONTAINER (text_box), 4); |
---|
698 | |
---|
699 | fontsel->preview_entry = gtk_entry_new (); |
---|
700 | gtk_widget_show (fontsel->preview_entry); |
---|
701 | gtk_widget_set_usize (fontsel->preview_entry, -1, INITIAL_PREVIEW_HEIGHT); |
---|
702 | gtk_box_pack_start (GTK_BOX (text_box), fontsel->preview_entry, |
---|
703 | TRUE, TRUE, 0); |
---|
704 | |
---|
705 | /* Create the message area */ |
---|
706 | fontsel->message_label = gtk_label_new(""); |
---|
707 | gtk_widget_show (fontsel->message_label); |
---|
708 | gtk_box_pack_start (GTK_BOX (fontsel->main_vbox), fontsel->message_label, |
---|
709 | FALSE, FALSE, 0); |
---|
710 | |
---|
711 | |
---|
712 | /* Create the font info page */ |
---|
713 | fontsel->info_vbox = gtk_vbox_new (FALSE, 4); |
---|
714 | gtk_widget_show (fontsel->info_vbox); |
---|
715 | gtk_container_set_border_width (GTK_CONTAINER (fontsel->info_vbox), 2); |
---|
716 | label = gtk_label_new(_("Font Information")); |
---|
717 | gtk_notebook_append_page (GTK_NOTEBOOK (fontsel), |
---|
718 | fontsel->info_vbox, label); |
---|
719 | |
---|
720 | fontsel->info_clist = gtk_clist_new_with_titles (3, titles); |
---|
721 | gtk_widget_set_usize (fontsel->info_clist, 390, 150); |
---|
722 | gtk_clist_set_column_width(GTK_CLIST(fontsel->info_clist), 0, 130); |
---|
723 | gtk_clist_set_column_width(GTK_CLIST(fontsel->info_clist), 1, 130); |
---|
724 | gtk_clist_set_column_width(GTK_CLIST(fontsel->info_clist), 2, 130); |
---|
725 | gtk_clist_column_titles_passive(GTK_CLIST(fontsel->info_clist)); |
---|
726 | scrolled_win = gtk_scrolled_window_new (NULL, NULL); |
---|
727 | gtk_container_add (GTK_CONTAINER (scrolled_win), fontsel->info_clist); |
---|
728 | gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win), |
---|
729 | GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); |
---|
730 | gtk_widget_show(fontsel->info_clist); |
---|
731 | gtk_widget_show(scrolled_win); |
---|
732 | gtk_box_pack_start (GTK_BOX (fontsel->info_vbox), scrolled_win, |
---|
733 | TRUE, TRUE, 0); |
---|
734 | |
---|
735 | /* Insert the property names */ |
---|
736 | gtk_clist_freeze (GTK_CLIST(fontsel->info_clist)); |
---|
737 | row_text[1] = ""; |
---|
738 | row_text[2] = ""; |
---|
739 | for (i = 0; i < GTK_XLFD_NUM_FIELDS; i++) |
---|
740 | { |
---|
741 | row_text[0] = _(xlfd_field_names[i]); |
---|
742 | gtk_clist_append(GTK_CLIST(fontsel->info_clist), row_text); |
---|
743 | gtk_clist_set_shift(GTK_CLIST(fontsel->info_clist), i, 0, 0, 4); |
---|
744 | gtk_clist_set_shift(GTK_CLIST(fontsel->info_clist), i, 1, 0, 4); |
---|
745 | gtk_clist_set_shift(GTK_CLIST(fontsel->info_clist), i, 2, 0, 4); |
---|
746 | } |
---|
747 | gtk_clist_thaw (GTK_CLIST(fontsel->info_clist)); |
---|
748 | |
---|
749 | label = gtk_label_new(_("Requested Font Name:")); |
---|
750 | gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); |
---|
751 | gtk_widget_show (label); |
---|
752 | gtk_box_pack_start (GTK_BOX (fontsel->info_vbox), label, FALSE, TRUE, 0); |
---|
753 | |
---|
754 | fontsel->requested_font_name = gtk_entry_new(); |
---|
755 | gtk_entry_set_editable(GTK_ENTRY(fontsel->requested_font_name), FALSE); |
---|
756 | gtk_widget_show (fontsel->requested_font_name); |
---|
757 | gtk_box_pack_start (GTK_BOX (fontsel->info_vbox), |
---|
758 | fontsel->requested_font_name, FALSE, TRUE, 0); |
---|
759 | |
---|
760 | label = gtk_label_new(_("Actual Font Name:")); |
---|
761 | gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); |
---|
762 | gtk_widget_show (label); |
---|
763 | gtk_box_pack_start (GTK_BOX (fontsel->info_vbox), label, FALSE, TRUE, 0); |
---|
764 | |
---|
765 | fontsel->actual_font_name = gtk_entry_new(); |
---|
766 | gtk_entry_set_editable(GTK_ENTRY(fontsel->actual_font_name), FALSE); |
---|
767 | gtk_widget_show (fontsel->actual_font_name); |
---|
768 | gtk_box_pack_start (GTK_BOX (fontsel->info_vbox), |
---|
769 | fontsel->actual_font_name, FALSE, TRUE, 0); |
---|
770 | |
---|
771 | sprintf(buffer, _("%i fonts available with a total of %i styles."), |
---|
772 | fontsel_info->nfonts, fontsel_info->nstyles); |
---|
773 | label = gtk_label_new(buffer); |
---|
774 | gtk_widget_show (label); |
---|
775 | gtk_box_pack_start (GTK_BOX (fontsel->info_vbox), label, FALSE, FALSE, 0); |
---|
776 | |
---|
777 | gtk_signal_connect (GTK_OBJECT (fontsel), "switch_page", |
---|
778 | GTK_SIGNAL_FUNC(gtk_font_selection_switch_page), |
---|
779 | fontsel); |
---|
780 | |
---|
781 | |
---|
782 | /* Create the Filter page. */ |
---|
783 | fontsel->filter_vbox = gtk_vbox_new (FALSE, 4); |
---|
784 | gtk_widget_show (fontsel->filter_vbox); |
---|
785 | gtk_container_set_border_width (GTK_CONTAINER (fontsel->filter_vbox), 2); |
---|
786 | label = gtk_label_new(_("Filter")); |
---|
787 | gtk_notebook_append_page (GTK_NOTEBOOK (fontsel), |
---|
788 | fontsel->filter_vbox, label); |
---|
789 | |
---|
790 | /* Create the font type checkbuttons. */ |
---|
791 | frame = gtk_frame_new (NULL); |
---|
792 | gtk_widget_show (frame); |
---|
793 | gtk_box_pack_start (GTK_BOX (fontsel->filter_vbox), frame, FALSE, TRUE, 0); |
---|
794 | |
---|
795 | hbox = gtk_hbox_new (FALSE, 20); |
---|
796 | gtk_widget_show (hbox); |
---|
797 | gtk_container_add (GTK_CONTAINER (frame), hbox); |
---|
798 | |
---|
799 | label = gtk_label_new(_("Font Types:")); |
---|
800 | gtk_widget_show (label); |
---|
801 | gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 10); |
---|
802 | |
---|
803 | hbox2 = gtk_hbox_new (TRUE, 0); |
---|
804 | gtk_widget_show (hbox2); |
---|
805 | gtk_box_pack_start (GTK_BOX (hbox), hbox2, FALSE, TRUE, 0); |
---|
806 | |
---|
807 | fontsel->type_bitmaps_button = gtk_check_button_new_with_label (_("Bitmap")); |
---|
808 | gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fontsel->type_bitmaps_button), TRUE); |
---|
809 | gtk_widget_show (fontsel->type_bitmaps_button); |
---|
810 | gtk_box_pack_start (GTK_BOX (hbox2), fontsel->type_bitmaps_button, |
---|
811 | FALSE, TRUE, 0); |
---|
812 | |
---|
813 | fontsel->type_scalable_button = gtk_check_button_new_with_label (_("Scalable")); |
---|
814 | gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fontsel->type_scalable_button), TRUE); |
---|
815 | gtk_widget_show (fontsel->type_scalable_button); |
---|
816 | gtk_box_pack_start (GTK_BOX (hbox2), fontsel->type_scalable_button, |
---|
817 | FALSE, TRUE, 0); |
---|
818 | |
---|
819 | fontsel->type_scaled_bitmaps_button = gtk_check_button_new_with_label (_("Scaled Bitmap")); |
---|
820 | gtk_widget_show (fontsel->type_scaled_bitmaps_button); |
---|
821 | gtk_box_pack_start (GTK_BOX (hbox2), fontsel->type_scaled_bitmaps_button, |
---|
822 | FALSE, TRUE, 0); |
---|
823 | |
---|
824 | table = gtk_table_new (4, 3, FALSE); |
---|
825 | gtk_table_set_col_spacings(GTK_TABLE(table), 2); |
---|
826 | gtk_widget_show (table); |
---|
827 | gtk_box_pack_start (GTK_BOX (fontsel->filter_vbox), table, TRUE, TRUE, 0); |
---|
828 | |
---|
829 | for (prop = 0; prop < GTK_NUM_FONT_PROPERTIES; prop++) |
---|
830 | { |
---|
831 | gint left = filter_positions[prop][0]; |
---|
832 | gint top = filter_positions[prop][1]; |
---|
833 | |
---|
834 | label = gtk_label_new(_(xlfd_field_names[xlfd_index[prop]])); |
---|
835 | gtk_misc_set_alignment (GTK_MISC (label), 0.0, 1.0); |
---|
836 | gtk_misc_set_padding (GTK_MISC (label), 0, 2); |
---|
837 | gtk_widget_show(label); |
---|
838 | gtk_table_attach (GTK_TABLE (table), label, left, left + 1, |
---|
839 | top, top + 1, GTK_FILL, GTK_FILL, 0, 0); |
---|
840 | |
---|
841 | clist = gtk_clist_new(1); |
---|
842 | gtk_widget_set_usize (clist, 100, filter_heights[prop]); |
---|
843 | gtk_clist_set_selection_mode(GTK_CLIST(clist), GTK_SELECTION_MULTIPLE); |
---|
844 | gtk_clist_column_titles_hide(GTK_CLIST(clist)); |
---|
845 | gtk_clist_set_column_auto_resize (GTK_CLIST (clist), 0, TRUE); |
---|
846 | scrolled_win = gtk_scrolled_window_new (NULL, NULL); |
---|
847 | gtk_container_add (GTK_CONTAINER (scrolled_win), clist); |
---|
848 | gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win), |
---|
849 | GTK_POLICY_AUTOMATIC, |
---|
850 | GTK_POLICY_AUTOMATIC); |
---|
851 | gtk_widget_show(clist); |
---|
852 | gtk_widget_show(scrolled_win); |
---|
853 | |
---|
854 | /* For the bottom-right cell we add the 'Reset Filter' button. */ |
---|
855 | if (top == 2 && left == 2) |
---|
856 | { |
---|
857 | vbox = gtk_vbox_new(FALSE, 0); |
---|
858 | gtk_widget_show(vbox); |
---|
859 | gtk_table_attach (GTK_TABLE (table), vbox, left, left + 1, |
---|
860 | top + 1, top + 2, GTK_FILL, GTK_FILL, 0, 0); |
---|
861 | |
---|
862 | gtk_box_pack_start (GTK_BOX (vbox), scrolled_win, TRUE, TRUE, 0); |
---|
863 | |
---|
864 | alignment = gtk_alignment_new(0.5, 0.0, 0.8, 0.0); |
---|
865 | gtk_widget_show(alignment); |
---|
866 | gtk_box_pack_start (GTK_BOX (vbox), alignment, FALSE, TRUE, 4); |
---|
867 | |
---|
868 | button = gtk_button_new_with_label(_("Reset Filter")); |
---|
869 | gtk_widget_show(button); |
---|
870 | gtk_container_add(GTK_CONTAINER(alignment), button); |
---|
871 | gtk_signal_connect (GTK_OBJECT (button), "clicked", |
---|
872 | GTK_SIGNAL_FUNC(gtk_font_selection_reset_filter), |
---|
873 | fontsel); |
---|
874 | } |
---|
875 | else |
---|
876 | gtk_table_attach (GTK_TABLE (table), scrolled_win, |
---|
877 | left, left + 1, top + 1, top + 2, |
---|
878 | GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); |
---|
879 | |
---|
880 | gtk_signal_connect (GTK_OBJECT (clist), "select_row", |
---|
881 | GTK_SIGNAL_FUNC(gtk_font_selection_select_filter), |
---|
882 | fontsel); |
---|
883 | gtk_signal_connect (GTK_OBJECT (clist), "unselect_row", |
---|
884 | GTK_SIGNAL_FUNC(gtk_font_selection_unselect_filter), |
---|
885 | fontsel); |
---|
886 | |
---|
887 | /* Insert the property names, expanded, and in sorted order. |
---|
888 | But we make sure that the wildcard '*' is first. */ |
---|
889 | gtk_clist_freeze (GTK_CLIST(clist)); |
---|
890 | property = N_("*"); |
---|
891 | gtk_clist_append(GTK_CLIST(clist), &property); |
---|
892 | |
---|
893 | for (i = 1; i < fontsel_info->nproperties[prop]; i++) { |
---|
894 | property = _(fontsel_info->properties[prop][i]); |
---|
895 | if (prop == SLANT) |
---|
896 | property = gtk_font_selection_expand_slant_code(property); |
---|
897 | else if (prop == SPACING) |
---|
898 | property = gtk_font_selection_expand_spacing_code(property); |
---|
899 | |
---|
900 | inserted = FALSE; |
---|
901 | for (row = 1; row < GTK_CLIST(clist)->rows; row++) |
---|
902 | { |
---|
903 | gtk_clist_get_text(GTK_CLIST(clist), row, 0, &text); |
---|
904 | if (strcmp(property, text) < 0) |
---|
905 | { |
---|
906 | inserted = TRUE; |
---|
907 | gtk_clist_insert(GTK_CLIST(clist), row, &property); |
---|
908 | break; |
---|
909 | } |
---|
910 | } |
---|
911 | if (!inserted) |
---|
912 | row = gtk_clist_append(GTK_CLIST(clist), &property); |
---|
913 | gtk_clist_set_row_data(GTK_CLIST(clist), row, GINT_TO_POINTER (i)); |
---|
914 | } |
---|
915 | gtk_clist_select_row(GTK_CLIST(clist), 0, 0); |
---|
916 | gtk_clist_thaw (GTK_CLIST(clist)); |
---|
917 | fontsel->filter_clists[prop] = clist; |
---|
918 | } |
---|
919 | } |
---|
920 | |
---|
921 | GtkWidget * |
---|
922 | gtk_font_selection_new() |
---|
923 | { |
---|
924 | GtkFontSelection *fontsel; |
---|
925 | |
---|
926 | fontsel = gtk_type_new (GTK_TYPE_FONT_SELECTION); |
---|
927 | |
---|
928 | return GTK_WIDGET (fontsel); |
---|
929 | } |
---|
930 | |
---|
931 | static void |
---|
932 | gtk_font_selection_destroy (GtkObject *object) |
---|
933 | { |
---|
934 | GtkFontSelection *fontsel; |
---|
935 | |
---|
936 | g_return_if_fail (object != NULL); |
---|
937 | g_return_if_fail (GTK_IS_FONT_SELECTION (object)); |
---|
938 | |
---|
939 | fontsel = GTK_FONT_SELECTION (object); |
---|
940 | |
---|
941 | /* All we have to do is unref the font, if we have one. */ |
---|
942 | if (fontsel->font) |
---|
943 | gdk_font_unref (fontsel->font); |
---|
944 | |
---|
945 | if (GTK_OBJECT_CLASS (font_selection_parent_class)->destroy) |
---|
946 | (* GTK_OBJECT_CLASS (font_selection_parent_class)->destroy) (object); |
---|
947 | } |
---|
948 | |
---|
949 | |
---|
950 | /* This is called when the clist is exposed. Here we scroll to the current |
---|
951 | font if necessary. */ |
---|
952 | static void |
---|
953 | gtk_font_selection_expose_list (GtkWidget *widget, |
---|
954 | GdkEventExpose *event, |
---|
955 | gpointer data) |
---|
956 | { |
---|
957 | GtkFontSelection *fontsel; |
---|
958 | FontInfo *font_info; |
---|
959 | GList *selection; |
---|
960 | gint index; |
---|
961 | |
---|
962 | #ifdef FONTSEL_DEBUG |
---|
963 | g_message("In expose_list\n"); |
---|
964 | #endif |
---|
965 | fontsel = GTK_FONT_SELECTION(data); |
---|
966 | |
---|
967 | font_info = fontsel_info->font_info; |
---|
968 | |
---|
969 | /* Try to scroll the font family clist to the selected item */ |
---|
970 | selection = GTK_CLIST(fontsel->font_clist)->selection; |
---|
971 | if (selection) |
---|
972 | { |
---|
973 | index = GPOINTER_TO_INT (selection->data); |
---|
974 | if (gtk_clist_row_is_visible(GTK_CLIST(fontsel->font_clist), index) |
---|
975 | != GTK_VISIBILITY_FULL) |
---|
976 | gtk_clist_moveto(GTK_CLIST(fontsel->font_clist), index, -1, 0.5, 0); |
---|
977 | } |
---|
978 | |
---|
979 | /* Try to scroll the font style clist to the selected item */ |
---|
980 | selection = GTK_CLIST(fontsel->font_style_clist)->selection; |
---|
981 | if (selection) |
---|
982 | { |
---|
983 | index = GPOINTER_TO_INT (selection->data); |
---|
984 | if (gtk_clist_row_is_visible(GTK_CLIST(fontsel->font_style_clist), index) |
---|
985 | != GTK_VISIBILITY_FULL) |
---|
986 | gtk_clist_moveto(GTK_CLIST(fontsel->font_style_clist), index, -1, |
---|
987 | 0.5, 0); |
---|
988 | } |
---|
989 | |
---|
990 | /* Try to scroll the font size clist to the selected item */ |
---|
991 | selection = GTK_CLIST(fontsel->size_clist)->selection; |
---|
992 | if (selection) |
---|
993 | { |
---|
994 | index = GPOINTER_TO_INT (selection->data); |
---|
995 | if (gtk_clist_row_is_visible(GTK_CLIST(fontsel->size_clist), index) |
---|
996 | != GTK_VISIBILITY_FULL) |
---|
997 | gtk_clist_moveto(GTK_CLIST(fontsel->size_clist), index, -1, 0.5, 0); |
---|
998 | } |
---|
999 | } |
---|
1000 | |
---|
1001 | |
---|
1002 | /* This is called when the style clist is realized. We need to set any |
---|
1003 | charset rows to insensitive colours. */ |
---|
1004 | static void |
---|
1005 | gtk_font_selection_realize_list (GtkWidget *widget, |
---|
1006 | gpointer data) |
---|
1007 | { |
---|
1008 | GtkFontSelection *fontsel; |
---|
1009 | gint row; |
---|
1010 | GdkColor *inactive_fg, *inactive_bg; |
---|
1011 | |
---|
1012 | #ifdef FONTSEL_DEBUG |
---|
1013 | g_message("In realize_list\n"); |
---|
1014 | #endif |
---|
1015 | fontsel = GTK_FONT_SELECTION (data); |
---|
1016 | |
---|
1017 | /* Set the colours for any charset rows to insensitive. */ |
---|
1018 | inactive_fg = &fontsel->font_style_clist->style->fg[GTK_STATE_INSENSITIVE]; |
---|
1019 | inactive_bg = &fontsel->font_style_clist->style->bg[GTK_STATE_INSENSITIVE]; |
---|
1020 | |
---|
1021 | for (row = 0; row < GTK_CLIST (fontsel->font_style_clist)->rows; row++) |
---|
1022 | { |
---|
1023 | if (GPOINTER_TO_INT (gtk_clist_get_row_data (GTK_CLIST (fontsel->font_style_clist), row)) == -1) |
---|
1024 | { |
---|
1025 | gtk_clist_set_foreground (GTK_CLIST (fontsel->font_style_clist), |
---|
1026 | row, inactive_fg); |
---|
1027 | gtk_clist_set_background (GTK_CLIST (fontsel->font_style_clist), |
---|
1028 | row, inactive_bg); |
---|
1029 | } |
---|
1030 | } |
---|
1031 | } |
---|
1032 | |
---|
1033 | |
---|
1034 | /* This is called when a family is selected in the list. */ |
---|
1035 | static void |
---|
1036 | gtk_font_selection_select_font (GtkWidget *w, |
---|
1037 | gint row, |
---|
1038 | gint column, |
---|
1039 | GdkEventButton *bevent, |
---|
1040 | gpointer data) |
---|
1041 | { |
---|
1042 | GtkFontSelection *fontsel; |
---|
1043 | FontInfo *font_info; |
---|
1044 | FontInfo *font; |
---|
1045 | |
---|
1046 | #ifdef FONTSEL_DEBUG |
---|
1047 | g_message("In select_font\n"); |
---|
1048 | #endif |
---|
1049 | fontsel = GTK_FONT_SELECTION(data); |
---|
1050 | font_info = fontsel_info->font_info; |
---|
1051 | |
---|
1052 | if (bevent && !GTK_WIDGET_HAS_FOCUS (w)) |
---|
1053 | gtk_widget_grab_focus (w); |
---|
1054 | |
---|
1055 | row = GPOINTER_TO_INT (gtk_clist_get_row_data (GTK_CLIST (fontsel->font_clist), row)); |
---|
1056 | font = &font_info[row]; |
---|
1057 | gtk_entry_set_text(GTK_ENTRY(fontsel->font_entry), font->family); |
---|
1058 | |
---|
1059 | /* If it is already the current font, just return. */ |
---|
1060 | if (fontsel->font_index == row) |
---|
1061 | return; |
---|
1062 | |
---|
1063 | fontsel->font_index = row; |
---|
1064 | gtk_font_selection_show_available_styles (fontsel); |
---|
1065 | gtk_font_selection_select_best_style (fontsel, TRUE); |
---|
1066 | } |
---|
1067 | |
---|
1068 | |
---|
1069 | static gint |
---|
1070 | gtk_font_selection_on_clist_key_press (GtkWidget *clist, |
---|
1071 | GdkEventKey *event, |
---|
1072 | GtkFontSelection *fontsel) |
---|
1073 | { |
---|
1074 | #ifdef FONTSEL_DEBUG |
---|
1075 | g_message("In on_clist_key_press\n"); |
---|
1076 | #endif |
---|
1077 | if (event->keyval == GDK_Up) |
---|
1078 | return gtk_font_selection_select_next (fontsel, clist, -1); |
---|
1079 | else if (event->keyval == GDK_Down) |
---|
1080 | return gtk_font_selection_select_next (fontsel, clist, 1); |
---|
1081 | else |
---|
1082 | return FALSE; |
---|
1083 | } |
---|
1084 | |
---|
1085 | |
---|
1086 | static gboolean |
---|
1087 | gtk_font_selection_select_next (GtkFontSelection *fontsel, |
---|
1088 | GtkWidget *clist, |
---|
1089 | gint step) |
---|
1090 | { |
---|
1091 | GList *selection; |
---|
1092 | gint current_row, row; |
---|
1093 | |
---|
1094 | selection = GTK_CLIST(clist)->selection; |
---|
1095 | if (!selection) |
---|
1096 | return FALSE; |
---|
1097 | current_row = GPOINTER_TO_INT (selection->data); |
---|
1098 | |
---|
1099 | /* Stop the normal clist key handler from being run. */ |
---|
1100 | gtk_signal_emit_stop_by_name (GTK_OBJECT (clist), "key_press_event"); |
---|
1101 | |
---|
1102 | for (row = current_row + step; |
---|
1103 | row >= 0 && row < GTK_CLIST(clist)->rows; |
---|
1104 | row += step) |
---|
1105 | { |
---|
1106 | /* If this is the style clist, make sure that the item is not a charset |
---|
1107 | entry. */ |
---|
1108 | if (clist == fontsel->font_style_clist) |
---|
1109 | if (GPOINTER_TO_INT (gtk_clist_get_row_data(GTK_CLIST(clist), row)) == -1) |
---|
1110 | continue; |
---|
1111 | |
---|
1112 | /* Now we've found the row to select. */ |
---|
1113 | if (gtk_clist_row_is_visible(GTK_CLIST(clist), row) |
---|
1114 | != GTK_VISIBILITY_FULL) |
---|
1115 | gtk_clist_moveto(GTK_CLIST(clist), row, -1, (step < 0) ? 0 : 1, 0); |
---|
1116 | gtk_clist_select_row(GTK_CLIST(clist), row, 0); |
---|
1117 | break; |
---|
1118 | } |
---|
1119 | return TRUE; |
---|
1120 | } |
---|
1121 | |
---|
1122 | |
---|
1123 | /* This fills the font style clist with all the possible style combinations |
---|
1124 | for the current font family. */ |
---|
1125 | static void |
---|
1126 | gtk_font_selection_show_available_styles (GtkFontSelection *fontsel) |
---|
1127 | { |
---|
1128 | FontInfo *font; |
---|
1129 | FontStyle *styles; |
---|
1130 | gint style, tmpstyle, row; |
---|
1131 | gint weight_index, slant_index, set_width_index, spacing_index; |
---|
1132 | gint charset_index; |
---|
1133 | gchar *weight, *slant, *set_width, *spacing; |
---|
1134 | gchar *charset = NULL; |
---|
1135 | gchar *new_item; |
---|
1136 | gchar buffer[XLFD_MAX_FIELD_LEN * 6 + 2]; |
---|
1137 | GdkColor *inactive_fg, *inactive_bg; |
---|
1138 | gboolean show_charset; |
---|
1139 | |
---|
1140 | #ifdef FONTSEL_DEBUG |
---|
1141 | g_message("In show_available_styles\n"); |
---|
1142 | #endif |
---|
1143 | font = &fontsel_info->font_info[fontsel->font_index]; |
---|
1144 | styles = &fontsel_info->font_styles[font->style_index]; |
---|
1145 | |
---|
1146 | gtk_clist_freeze (GTK_CLIST(fontsel->font_style_clist)); |
---|
1147 | gtk_clist_clear (GTK_CLIST(fontsel->font_style_clist)); |
---|
1148 | |
---|
1149 | /* First we mark all visible styles as not having been displayed yet, |
---|
1150 | and check if every style has the same charset. If not then we will |
---|
1151 | display the charset in the list before the styles. */ |
---|
1152 | show_charset = FALSE; |
---|
1153 | charset_index = -1; |
---|
1154 | for (style = 0; style < font->nstyles; style++) |
---|
1155 | { |
---|
1156 | if (gtk_font_selection_style_visible(fontsel, font, style)) |
---|
1157 | { |
---|
1158 | styles[style].flags &= ~GTK_FONT_DISPLAYED; |
---|
1159 | |
---|
1160 | if (charset_index == -1) |
---|
1161 | charset_index = styles[style].properties[CHARSET]; |
---|
1162 | else if (charset_index != styles[style].properties[CHARSET]) |
---|
1163 | show_charset = TRUE; |
---|
1164 | } |
---|
1165 | else |
---|
1166 | styles[style].flags |= GTK_FONT_DISPLAYED; |
---|
1167 | } |
---|
1168 | |
---|
1169 | /* Step through the undisplayed styles, finding the next charset which |
---|
1170 | hasn't been displayed yet. Then display the charset on one line, if |
---|
1171 | necessary, and the visible styles indented beneath it. */ |
---|
1172 | inactive_fg = &fontsel->font_style_clist->style->fg[GTK_STATE_INSENSITIVE]; |
---|
1173 | inactive_bg = &fontsel->font_style_clist->style->bg[GTK_STATE_INSENSITIVE]; |
---|
1174 | |
---|
1175 | for (style = 0; style < font->nstyles; style++) |
---|
1176 | { |
---|
1177 | if (styles[style].flags & GTK_FONT_DISPLAYED) |
---|
1178 | continue; |
---|
1179 | |
---|
1180 | if (show_charset) |
---|
1181 | { |
---|
1182 | charset_index = styles[style].properties[CHARSET]; |
---|
1183 | charset = fontsel_info->properties[CHARSET] [charset_index]; |
---|
1184 | row = gtk_clist_append(GTK_CLIST(fontsel->font_style_clist), |
---|
1185 | &charset); |
---|
1186 | gtk_clist_set_row_data(GTK_CLIST(fontsel->font_style_clist), row, |
---|
1187 | (gpointer) -1); |
---|
1188 | if (GTK_WIDGET_REALIZED (fontsel->font_style_clist)) |
---|
1189 | { |
---|
1190 | gtk_clist_set_foreground(GTK_CLIST(fontsel->font_style_clist), |
---|
1191 | row, inactive_fg); |
---|
1192 | gtk_clist_set_background(GTK_CLIST(fontsel->font_style_clist), |
---|
1193 | row, inactive_bg); |
---|
1194 | } |
---|
1195 | } |
---|
1196 | |
---|
1197 | for (tmpstyle = style; tmpstyle < font->nstyles; tmpstyle++) |
---|
1198 | { |
---|
1199 | if (styles[tmpstyle].flags & GTK_FONT_DISPLAYED |
---|
1200 | || charset_index != styles[tmpstyle].properties[CHARSET]) |
---|
1201 | continue; |
---|
1202 | |
---|
1203 | styles[tmpstyle].flags |= GTK_FONT_DISPLAYED; |
---|
1204 | |
---|
1205 | weight_index = styles[tmpstyle].properties[WEIGHT]; |
---|
1206 | slant_index = styles[tmpstyle].properties[SLANT]; |
---|
1207 | set_width_index = styles[tmpstyle].properties[SET_WIDTH]; |
---|
1208 | spacing_index = styles[tmpstyle].properties[SPACING]; |
---|
1209 | weight = fontsel_info->properties[WEIGHT] [weight_index]; |
---|
1210 | slant = fontsel_info->properties[SLANT] [slant_index]; |
---|
1211 | set_width = fontsel_info->properties[SET_WIDTH][set_width_index]; |
---|
1212 | spacing = fontsel_info->properties[SPACING] [spacing_index]; |
---|
1213 | |
---|
1214 | /* Convert '(nil)' weights to 'regular', since it looks nicer. */ |
---|
1215 | if (!g_strcasecmp(weight, N_("(nil)"))) weight = N_("regular"); |
---|
1216 | |
---|
1217 | /* We don't show default values or (nil) in the other properties. */ |
---|
1218 | if (!g_strcasecmp(slant, "r")) slant = NULL; |
---|
1219 | else if (!g_strcasecmp(slant, "(nil)")) slant = NULL; |
---|
1220 | else if (!g_strcasecmp(slant, "i")) slant = N_("italic"); |
---|
1221 | else if (!g_strcasecmp(slant, "o")) slant = N_("oblique"); |
---|
1222 | else if (!g_strcasecmp(slant, "ri")) slant = N_("reverse italic"); |
---|
1223 | else if (!g_strcasecmp(slant, "ro")) slant = N_("reverse oblique"); |
---|
1224 | else if (!g_strcasecmp(slant, "ot")) slant = N_("other"); |
---|
1225 | |
---|
1226 | if (!g_strcasecmp(set_width, "normal")) set_width = NULL; |
---|
1227 | else if (!g_strcasecmp(set_width, "(nil)")) set_width = NULL; |
---|
1228 | |
---|
1229 | if (!g_strcasecmp(spacing, "p")) spacing = NULL; |
---|
1230 | else if (!g_strcasecmp(spacing, "(nil)")) spacing = NULL; |
---|
1231 | else if (!g_strcasecmp(spacing, "m")) spacing = N_("[M]"); |
---|
1232 | else if (!g_strcasecmp(spacing, "c")) spacing = N_("[C]"); |
---|
1233 | |
---|
1234 | /* Add the strings together, making sure there is 1 space between |
---|
1235 | them */ |
---|
1236 | strcpy(buffer, _(weight)); |
---|
1237 | if (slant) |
---|
1238 | { |
---|
1239 | strcat(buffer, " "); |
---|
1240 | strcat(buffer, _(slant)); |
---|
1241 | } |
---|
1242 | if (set_width) |
---|
1243 | { |
---|
1244 | strcat(buffer, " "); |
---|
1245 | strcat(buffer, _(set_width)); |
---|
1246 | } |
---|
1247 | if (spacing) |
---|
1248 | { |
---|
1249 | strcat(buffer, " "); |
---|
1250 | strcat(buffer, _(spacing)); |
---|
1251 | } |
---|
1252 | |
---|
1253 | new_item = buffer; |
---|
1254 | row = gtk_clist_append(GTK_CLIST(fontsel->font_style_clist), |
---|
1255 | &new_item); |
---|
1256 | if (show_charset) |
---|
1257 | gtk_clist_set_shift(GTK_CLIST(fontsel->font_style_clist), row, 0, |
---|
1258 | 0, 4); |
---|
1259 | gtk_clist_set_row_data(GTK_CLIST(fontsel->font_style_clist), row, |
---|
1260 | GINT_TO_POINTER (tmpstyle)); |
---|
1261 | } |
---|
1262 | } |
---|
1263 | |
---|
1264 | gtk_clist_thaw (GTK_CLIST(fontsel->font_style_clist)); |
---|
1265 | } |
---|
1266 | |
---|
1267 | |
---|
1268 | /* This selects a style when the user selects a font. It just uses the first |
---|
1269 | available style at present. I was thinking of trying to maintain the |
---|
1270 | selected style, e.g. bold italic, when the user selects different fonts. |
---|
1271 | However, the interface is so easy to use now I'm not sure it's worth it. |
---|
1272 | Note: This will load a font. */ |
---|
1273 | static void |
---|
1274 | gtk_font_selection_select_best_style(GtkFontSelection *fontsel, |
---|
1275 | gboolean use_first) |
---|
1276 | { |
---|
1277 | FontInfo *font; |
---|
1278 | FontStyle *styles; |
---|
1279 | gint row, prop, style, matched; |
---|
1280 | gint best_matched = -1, best_style = -1, best_row = -1; |
---|
1281 | |
---|
1282 | #ifdef FONTSEL_DEBUG |
---|
1283 | g_message("In select_best_style\n"); |
---|
1284 | #endif |
---|
1285 | font = &fontsel_info->font_info[fontsel->font_index]; |
---|
1286 | styles = &fontsel_info->font_styles[font->style_index]; |
---|
1287 | |
---|
1288 | for (row = 0; row < GTK_CLIST(fontsel->font_style_clist)->rows; row++) |
---|
1289 | { |
---|
1290 | style = GPOINTER_TO_INT (gtk_clist_get_row_data (GTK_CLIST (fontsel->font_style_clist), row)); |
---|
1291 | /* Skip charset rows. */ |
---|
1292 | if (style == -1) |
---|
1293 | continue; |
---|
1294 | |
---|
1295 | /* If we just want the first style, we've got it. */ |
---|
1296 | if (use_first) |
---|
1297 | { |
---|
1298 | best_style = style; |
---|
1299 | best_row = row; |
---|
1300 | break; |
---|
1301 | } |
---|
1302 | |
---|
1303 | matched = 0; |
---|
1304 | for (prop = 0; prop < GTK_NUM_STYLE_PROPERTIES; prop++) |
---|
1305 | { |
---|
1306 | if (fontsel->property_values[prop] == styles[style].properties[prop]) |
---|
1307 | matched++; |
---|
1308 | } |
---|
1309 | if (matched > best_matched) |
---|
1310 | { |
---|
1311 | best_matched = matched; |
---|
1312 | best_style = style; |
---|
1313 | best_row = row; |
---|
1314 | } |
---|
1315 | } |
---|
1316 | g_return_if_fail (best_style != -1); |
---|
1317 | g_return_if_fail (best_row != -1); |
---|
1318 | |
---|
1319 | fontsel->style = best_style; |
---|
1320 | |
---|
1321 | for (prop = 0; prop < GTK_NUM_STYLE_PROPERTIES; prop++) |
---|
1322 | fontsel->property_values[prop] = styles[fontsel->style].properties[prop]; |
---|
1323 | |
---|
1324 | gtk_clist_select_row(GTK_CLIST(fontsel->font_style_clist), best_row, 0); |
---|
1325 | if (gtk_clist_row_is_visible(GTK_CLIST(fontsel->font_style_clist), best_row) |
---|
1326 | != GTK_VISIBILITY_FULL) |
---|
1327 | gtk_clist_moveto(GTK_CLIST(fontsel->font_style_clist), best_row, -1, |
---|
1328 | 0.5, 0); |
---|
1329 | gtk_font_selection_show_available_sizes (fontsel); |
---|
1330 | gtk_font_selection_select_best_size (fontsel); |
---|
1331 | } |
---|
1332 | |
---|
1333 | |
---|
1334 | /* This is called when a style is selected in the list. */ |
---|
1335 | static void |
---|
1336 | gtk_font_selection_select_style (GtkWidget *w, |
---|
1337 | gint row, |
---|
1338 | gint column, |
---|
1339 | GdkEventButton *bevent, |
---|
1340 | gpointer data) |
---|
1341 | { |
---|
1342 | GtkFontSelection *fontsel; |
---|
1343 | FontInfo *font_info; |
---|
1344 | FontInfo *font; |
---|
1345 | FontStyle *styles; |
---|
1346 | gint style, prop; |
---|
1347 | gchar *text; |
---|
1348 | |
---|
1349 | #ifdef FONTSEL_DEBUG |
---|
1350 | g_message("In select_style\n"); |
---|
1351 | #endif |
---|
1352 | fontsel = GTK_FONT_SELECTION(data); |
---|
1353 | font_info = fontsel_info->font_info; |
---|
1354 | font = &font_info[fontsel->font_index]; |
---|
1355 | styles = &fontsel_info->font_styles[font->style_index]; |
---|
1356 | |
---|
1357 | if (bevent && !GTK_WIDGET_HAS_FOCUS (w)) |
---|
1358 | gtk_widget_grab_focus (w); |
---|
1359 | |
---|
1360 | /* The style index is stored in the row data, so we just need to copy |
---|
1361 | the style values into the fontsel and reload the font. */ |
---|
1362 | style = GPOINTER_TO_INT (gtk_clist_get_row_data(GTK_CLIST(fontsel->font_style_clist), row)); |
---|
1363 | |
---|
1364 | /* Don't allow selection of charset rows. */ |
---|
1365 | if (style == -1) |
---|
1366 | { |
---|
1367 | gtk_clist_unselect_row(GTK_CLIST(fontsel->font_style_clist), row, 0); |
---|
1368 | return; |
---|
1369 | } |
---|
1370 | |
---|
1371 | gtk_clist_get_text(GTK_CLIST(fontsel->font_style_clist), row, 0, &text); |
---|
1372 | gtk_entry_set_text(GTK_ENTRY(fontsel->font_style_entry), text); |
---|
1373 | |
---|
1374 | for (prop = 0; prop < GTK_NUM_STYLE_PROPERTIES; prop++) |
---|
1375 | fontsel->property_values[prop] = styles[style].properties[prop]; |
---|
1376 | |
---|
1377 | if (fontsel->style == style) |
---|
1378 | return; |
---|
1379 | |
---|
1380 | fontsel->style = style; |
---|
1381 | gtk_font_selection_show_available_sizes (fontsel); |
---|
1382 | gtk_font_selection_select_best_size (fontsel); |
---|
1383 | } |
---|
1384 | |
---|
1385 | |
---|
1386 | /* This shows all the available sizes in the size clist, according to the |
---|
1387 | current metric and the current font & style. */ |
---|
1388 | static void |
---|
1389 | gtk_font_selection_show_available_sizes (GtkFontSelection *fontsel) |
---|
1390 | { |
---|
1391 | FontInfo *font; |
---|
1392 | FontStyle *styles, *style; |
---|
1393 | const guint16 *standard_sizes; |
---|
1394 | guint16 *bitmapped_sizes; |
---|
1395 | gint nstandard_sizes, nbitmapped_sizes; |
---|
1396 | gchar buffer[16], *size; |
---|
1397 | gfloat bitmap_size_float = 0.; |
---|
1398 | guint16 bitmap_size = 0; |
---|
1399 | gboolean can_match; |
---|
1400 | gint type_filter; |
---|
1401 | |
---|
1402 | #ifdef FONTSEL_DEBUG |
---|
1403 | g_message("In show_available_sizes\n"); |
---|
1404 | #endif |
---|
1405 | font = &fontsel_info->font_info[fontsel->font_index]; |
---|
1406 | styles = &fontsel_info->font_styles[font->style_index]; |
---|
1407 | style = &styles[fontsel->style]; |
---|
1408 | |
---|
1409 | standard_sizes = font_sizes; |
---|
1410 | nstandard_sizes = sizeof(font_sizes) / sizeof(font_sizes[0]); |
---|
1411 | if (fontsel->metric == GTK_FONT_METRIC_POINTS) |
---|
1412 | { |
---|
1413 | bitmapped_sizes = &fontsel_info->point_sizes[style->point_sizes_index]; |
---|
1414 | nbitmapped_sizes = style->npoint_sizes; |
---|
1415 | } |
---|
1416 | else |
---|
1417 | { |
---|
1418 | bitmapped_sizes = &fontsel_info->pixel_sizes[style->pixel_sizes_index]; |
---|
1419 | nbitmapped_sizes = style->npixel_sizes; |
---|
1420 | } |
---|
1421 | |
---|
1422 | /* Only show the standard sizes if a scalable font is available. */ |
---|
1423 | type_filter = fontsel->filters[GTK_FONT_FILTER_BASE].font_type |
---|
1424 | & fontsel->filters[GTK_FONT_FILTER_USER].font_type; |
---|
1425 | |
---|
1426 | if (!((style->flags & GTK_FONT_SCALABLE_BITMAP |
---|
1427 | && type_filter & GTK_FONT_SCALABLE_BITMAP) |
---|
1428 | || (style->flags & GTK_FONT_SCALABLE |
---|
1429 | && type_filter & GTK_FONT_SCALABLE))) |
---|
1430 | nstandard_sizes = 0; |
---|
1431 | |
---|
1432 | gtk_clist_freeze (GTK_CLIST(fontsel->size_clist)); |
---|
1433 | gtk_clist_clear (GTK_CLIST(fontsel->size_clist)); |
---|
1434 | |
---|
1435 | /* Interleave the standard sizes with the bitmapped sizes so we get a list |
---|
1436 | of ascending sizes. If the metric is points, we have to convert the |
---|
1437 | decipoints to points. */ |
---|
1438 | while (nstandard_sizes || nbitmapped_sizes) |
---|
1439 | { |
---|
1440 | can_match = TRUE; |
---|
1441 | |
---|
1442 | if (nbitmapped_sizes) |
---|
1443 | { |
---|
1444 | if (fontsel->metric == GTK_FONT_METRIC_POINTS) |
---|
1445 | { |
---|
1446 | if (*bitmapped_sizes % 10 != 0) |
---|
1447 | can_match = FALSE; |
---|
1448 | bitmap_size = *bitmapped_sizes / 10; |
---|
1449 | bitmap_size_float = *bitmapped_sizes / 10; |
---|
1450 | } |
---|
1451 | else |
---|
1452 | { |
---|
1453 | bitmap_size = *bitmapped_sizes; |
---|
1454 | bitmap_size_float = *bitmapped_sizes; |
---|
1455 | } |
---|
1456 | } |
---|
1457 | |
---|
1458 | if (can_match && nstandard_sizes && nbitmapped_sizes |
---|
1459 | && *standard_sizes == bitmap_size) |
---|
1460 | { |
---|
1461 | sprintf(buffer, "%i *", *standard_sizes); |
---|
1462 | standard_sizes++; |
---|
1463 | nstandard_sizes--; |
---|
1464 | bitmapped_sizes++; |
---|
1465 | nbitmapped_sizes--; |
---|
1466 | } |
---|
1467 | else if (nstandard_sizes |
---|
1468 | && (!nbitmapped_sizes |
---|
1469 | || (gfloat)*standard_sizes < bitmap_size_float)) |
---|
1470 | { |
---|
1471 | sprintf(buffer, "%i", *standard_sizes); |
---|
1472 | standard_sizes++; |
---|
1473 | nstandard_sizes--; |
---|
1474 | } |
---|
1475 | else |
---|
1476 | { |
---|
1477 | if (fontsel->metric == GTK_FONT_METRIC_POINTS) |
---|
1478 | { |
---|
1479 | if (*bitmapped_sizes % 10 == 0) |
---|
1480 | sprintf(buffer, "%i *", *bitmapped_sizes / 10); |
---|
1481 | else |
---|
1482 | sprintf(buffer, "%i.%i *", *bitmapped_sizes / 10, |
---|
1483 | *bitmapped_sizes % 10); |
---|
1484 | } |
---|
1485 | else |
---|
1486 | { |
---|
1487 | sprintf(buffer, "%i *", *bitmapped_sizes); |
---|
1488 | } |
---|
1489 | bitmapped_sizes++; |
---|
1490 | nbitmapped_sizes--; |
---|
1491 | } |
---|
1492 | size = buffer; |
---|
1493 | gtk_clist_append(GTK_CLIST(fontsel->size_clist), &size); |
---|
1494 | } |
---|
1495 | gtk_clist_thaw (GTK_CLIST(fontsel->size_clist)); |
---|
1496 | } |
---|
1497 | |
---|
1498 | static void |
---|
1499 | gtk_font_selection_update_size (GtkFontSelection *fontsel) |
---|
1500 | { |
---|
1501 | gint new_size; |
---|
1502 | gfloat new_size_float; |
---|
1503 | gchar *text; |
---|
1504 | |
---|
1505 | #ifdef FONTSEL_DEBUG |
---|
1506 | g_message("In update_size\n"); |
---|
1507 | #endif |
---|
1508 | |
---|
1509 | text = gtk_entry_get_text (GTK_ENTRY (fontsel->size_entry)); |
---|
1510 | if (fontsel->metric == GTK_FONT_METRIC_PIXELS) |
---|
1511 | { |
---|
1512 | new_size = atoi (text); |
---|
1513 | if (new_size < 2) |
---|
1514 | new_size = 2; |
---|
1515 | } |
---|
1516 | else |
---|
1517 | { |
---|
1518 | new_size_float = atof (text) * 10; |
---|
1519 | new_size = (gint) new_size_float; |
---|
1520 | if (new_size < 20) |
---|
1521 | new_size = 20; |
---|
1522 | } |
---|
1523 | |
---|
1524 | /* Remember that this size was set explicitly. */ |
---|
1525 | fontsel->selected_size = new_size; |
---|
1526 | |
---|
1527 | /* Check if the font size has changed, and return if it hasn't. */ |
---|
1528 | if (fontsel->size == new_size) |
---|
1529 | return; |
---|
1530 | |
---|
1531 | fontsel->size = new_size; |
---|
1532 | gtk_font_selection_select_best_size (fontsel); |
---|
1533 | } |
---|
1534 | |
---|
1535 | /* If the user hits return in the font size entry, we change to the new font |
---|
1536 | size. */ |
---|
1537 | static void |
---|
1538 | gtk_font_selection_size_activate (GtkWidget *w, |
---|
1539 | gpointer data) |
---|
1540 | { |
---|
1541 | gtk_font_selection_update_size (data); |
---|
1542 | } |
---|
1543 | |
---|
1544 | /* This tries to select the closest size to the current size, though it |
---|
1545 | may have to change the size if only unscaled bitmaps are available. |
---|
1546 | Note: this will load a font. */ |
---|
1547 | static void |
---|
1548 | gtk_font_selection_select_best_size(GtkFontSelection *fontsel) |
---|
1549 | { |
---|
1550 | FontInfo *font; |
---|
1551 | FontStyle *styles, *style; |
---|
1552 | gchar *text; |
---|
1553 | gint row, best_row = 0, size, size_fraction, best_size = 0, nmatched; |
---|
1554 | gboolean found = FALSE; |
---|
1555 | gchar buffer[32]; |
---|
1556 | GList *selection; |
---|
1557 | gint type_filter; |
---|
1558 | |
---|
1559 | #ifdef FONTSEL_DEBUG |
---|
1560 | g_message("In select_best_size\n"); |
---|
1561 | #endif |
---|
1562 | |
---|
1563 | if (fontsel->font_index == -1) |
---|
1564 | return; |
---|
1565 | |
---|
1566 | font = &fontsel_info->font_info[fontsel->font_index]; |
---|
1567 | styles = &fontsel_info->font_styles[font->style_index]; |
---|
1568 | style = &styles[fontsel->style]; |
---|
1569 | |
---|
1570 | /* Find the closest size available in the size clist. If the exact size is |
---|
1571 | in the list set found to TRUE. */ |
---|
1572 | for (row = 0; row < GTK_CLIST(fontsel->size_clist)->rows; row++) |
---|
1573 | { |
---|
1574 | gtk_clist_get_text(GTK_CLIST(fontsel->size_clist), row, 0, &text); |
---|
1575 | nmatched = sscanf(text, "%i.%i", &size, &size_fraction); |
---|
1576 | if (fontsel->metric == GTK_FONT_METRIC_POINTS) |
---|
1577 | { |
---|
1578 | size *= 10; |
---|
1579 | if (nmatched == 2) |
---|
1580 | size += size_fraction; |
---|
1581 | } |
---|
1582 | |
---|
1583 | if (size == fontsel->selected_size) |
---|
1584 | { |
---|
1585 | found = TRUE; |
---|
1586 | best_size = size; |
---|
1587 | best_row = row; |
---|
1588 | break; |
---|
1589 | } |
---|
1590 | else if (best_size == 0 |
---|
1591 | || abs(size - fontsel->selected_size) |
---|
1592 | < (abs(best_size - fontsel->selected_size))) |
---|
1593 | { |
---|
1594 | best_size = size; |
---|
1595 | best_row = row; |
---|
1596 | } |
---|
1597 | } |
---|
1598 | |
---|
1599 | /* If we aren't scaling bitmapped fonts and this is a bitmapped font, we |
---|
1600 | need to use the closest size found. */ |
---|
1601 | type_filter = fontsel->filters[GTK_FONT_FILTER_BASE].font_type |
---|
1602 | & fontsel->filters[GTK_FONT_FILTER_USER].font_type; |
---|
1603 | |
---|
1604 | if (!((style->flags & GTK_FONT_SCALABLE_BITMAP |
---|
1605 | && type_filter & GTK_FONT_SCALABLE_BITMAP) |
---|
1606 | || (style->flags & GTK_FONT_SCALABLE |
---|
1607 | && type_filter & GTK_FONT_SCALABLE))) |
---|
1608 | found = TRUE; |
---|
1609 | |
---|
1610 | if (found) |
---|
1611 | { |
---|
1612 | fontsel->size = best_size; |
---|
1613 | gtk_clist_moveto(GTK_CLIST(fontsel->size_clist), best_row, -1, 0.5, 0); |
---|
1614 | gtk_clist_select_row(GTK_CLIST(fontsel->size_clist), best_row, 0); |
---|
1615 | } |
---|
1616 | else |
---|
1617 | { |
---|
1618 | fontsel->size = fontsel->selected_size; |
---|
1619 | selection = GTK_CLIST(fontsel->size_clist)->selection; |
---|
1620 | if (selection) |
---|
1621 | gtk_clist_unselect_row(GTK_CLIST(fontsel->size_clist), |
---|
1622 | GPOINTER_TO_INT (selection->data), 0); |
---|
1623 | gtk_clist_moveto(GTK_CLIST(fontsel->size_clist), best_row, -1, 0.5, 0); |
---|
1624 | |
---|
1625 | /* Show the size in the size entry. */ |
---|
1626 | if (fontsel->metric == GTK_FONT_METRIC_PIXELS) |
---|
1627 | sprintf(buffer, "%i", fontsel->size); |
---|
1628 | else |
---|
1629 | { |
---|
1630 | if (fontsel->size % 10 == 0) |
---|
1631 | sprintf(buffer, "%i", fontsel->size / 10); |
---|
1632 | else |
---|
1633 | sprintf(buffer, "%i.%i", fontsel->size / 10, fontsel->size % 10); |
---|
1634 | } |
---|
1635 | gtk_entry_set_text (GTK_ENTRY (fontsel->size_entry), buffer); |
---|
1636 | } |
---|
1637 | gtk_font_selection_load_font (fontsel); |
---|
1638 | } |
---|
1639 | |
---|
1640 | |
---|
1641 | /* This is called when a size is selected in the list. */ |
---|
1642 | static void |
---|
1643 | gtk_font_selection_select_size (GtkWidget *w, |
---|
1644 | gint row, |
---|
1645 | gint column, |
---|
1646 | GdkEventButton *bevent, |
---|
1647 | gpointer data) |
---|
1648 | { |
---|
1649 | GtkFontSelection *fontsel; |
---|
1650 | gint new_size; |
---|
1651 | gchar *text; |
---|
1652 | gchar buffer[16]; |
---|
1653 | gint i; |
---|
1654 | |
---|
1655 | #ifdef FONTSEL_DEBUG |
---|
1656 | g_message("In select_size\n"); |
---|
1657 | #endif |
---|
1658 | fontsel = GTK_FONT_SELECTION(data); |
---|
1659 | |
---|
1660 | if (bevent && !GTK_WIDGET_HAS_FOCUS (w)) |
---|
1661 | gtk_widget_grab_focus (w); |
---|
1662 | |
---|
1663 | /* Copy the size from the clist to the size entry, but without the bitmapped |
---|
1664 | marker ('*'). */ |
---|
1665 | gtk_clist_get_text(GTK_CLIST(fontsel->size_clist), row, 0, &text); |
---|
1666 | i = 0; |
---|
1667 | while (i < 15 && (text[i] == '.' || (text[i] >= '0' && text[i] <= '9'))) |
---|
1668 | { |
---|
1669 | buffer[i] = text[i]; |
---|
1670 | i++; |
---|
1671 | } |
---|
1672 | buffer[i] = '\0'; |
---|
1673 | gtk_entry_set_text(GTK_ENTRY(fontsel->size_entry), buffer); |
---|
1674 | |
---|
1675 | /* Check if the font size has changed, and return if it hasn't. */ |
---|
1676 | new_size = atoi(text); |
---|
1677 | if (fontsel->metric == GTK_FONT_METRIC_POINTS) |
---|
1678 | new_size *= 10; |
---|
1679 | |
---|
1680 | if (fontsel->size == new_size) |
---|
1681 | return; |
---|
1682 | |
---|
1683 | /* If the size was selected by the user we set the selected_size. */ |
---|
1684 | fontsel->selected_size = new_size; |
---|
1685 | |
---|
1686 | fontsel->size = new_size; |
---|
1687 | gtk_font_selection_load_font (fontsel); |
---|
1688 | } |
---|
1689 | |
---|
1690 | |
---|
1691 | /* This is called when the pixels or points radio buttons are pressed. */ |
---|
1692 | static void |
---|
1693 | gtk_font_selection_metric_callback (GtkWidget *w, |
---|
1694 | gpointer data) |
---|
1695 | { |
---|
1696 | GtkFontSelection *fontsel = GTK_FONT_SELECTION(data); |
---|
1697 | |
---|
1698 | #ifdef FONTSEL_DEBUG |
---|
1699 | g_message("In metric_callback\n"); |
---|
1700 | #endif |
---|
1701 | if (GTK_TOGGLE_BUTTON(fontsel->pixels_button)->active) |
---|
1702 | { |
---|
1703 | if (fontsel->metric == GTK_FONT_METRIC_PIXELS) |
---|
1704 | return; |
---|
1705 | fontsel->metric = GTK_FONT_METRIC_PIXELS; |
---|
1706 | fontsel->size = (fontsel->size + 5) / 10; |
---|
1707 | fontsel->selected_size = (fontsel->selected_size + 5) / 10; |
---|
1708 | } |
---|
1709 | else |
---|
1710 | { |
---|
1711 | if (fontsel->metric == GTK_FONT_METRIC_POINTS) |
---|
1712 | return; |
---|
1713 | fontsel->metric = GTK_FONT_METRIC_POINTS; |
---|
1714 | fontsel->size *= 10; |
---|
1715 | fontsel->selected_size *= 10; |
---|
1716 | } |
---|
1717 | if (fontsel->font_index != -1) |
---|
1718 | { |
---|
1719 | gtk_font_selection_show_available_sizes (fontsel); |
---|
1720 | gtk_font_selection_select_best_size (fontsel); |
---|
1721 | } |
---|
1722 | } |
---|
1723 | |
---|
1724 | |
---|
1725 | /* This searches the given property table and returns the index of the given |
---|
1726 | string, or 0, which is the wildcard '*' index, if it's not found. */ |
---|
1727 | static guint16 |
---|
1728 | gtk_font_selection_field_to_index (gchar **table, |
---|
1729 | gint ntable, |
---|
1730 | gchar *field) |
---|
1731 | { |
---|
1732 | gint i; |
---|
1733 | |
---|
1734 | for (i = 0; i < ntable; i++) |
---|
1735 | if (strcmp (field, table[i]) == 0) |
---|
1736 | return i; |
---|
1737 | |
---|
1738 | return 0; |
---|
1739 | } |
---|
1740 | |
---|
1741 | |
---|
1742 | |
---|
1743 | /* This attempts to load the current font, and returns TRUE if it succeeds. */ |
---|
1744 | static gboolean |
---|
1745 | gtk_font_selection_load_font (GtkFontSelection *fontsel) |
---|
1746 | { |
---|
1747 | GdkFont *font; |
---|
1748 | gchar *fontname, *label_text; |
---|
1749 | XFontStruct *xfs; |
---|
1750 | |
---|
1751 | if (fontsel->font) |
---|
1752 | gdk_font_unref (fontsel->font); |
---|
1753 | fontsel->font = NULL; |
---|
1754 | |
---|
1755 | /* If no family has been selected yet, just return FALSE. */ |
---|
1756 | if (fontsel->font_index == -1) |
---|
1757 | return FALSE; |
---|
1758 | |
---|
1759 | fontname = gtk_font_selection_get_font_name (fontsel); |
---|
1760 | if (fontname) |
---|
1761 | { |
---|
1762 | #ifdef FONTSEL_DEBUG |
---|
1763 | g_message("Loading: %s\n", fontname); |
---|
1764 | #endif |
---|
1765 | font = gdk_font_load (fontname); |
---|
1766 | xfs = font ? GDK_FONT_XFONT (font) : NULL; |
---|
1767 | if (xfs && (xfs->min_byte1 != 0 || xfs->max_byte1 != 0)) |
---|
1768 | { |
---|
1769 | gchar *tmp_name; |
---|
1770 | |
---|
1771 | gdk_font_unref (font); |
---|
1772 | tmp_name = g_strconcat (fontname, ",*", NULL); |
---|
1773 | font = gdk_fontset_load (tmp_name); |
---|
1774 | g_free (tmp_name); |
---|
1775 | } |
---|
1776 | g_free (fontname); |
---|
1777 | |
---|
1778 | if (font) |
---|
1779 | { |
---|
1780 | fontsel->font = font; |
---|
1781 | /* Make sure the message label is empty, but don't change it unless |
---|
1782 | it's necessary as it results in a resize of the whole window! */ |
---|
1783 | gtk_label_get(GTK_LABEL(fontsel->message_label), &label_text); |
---|
1784 | if (strcmp(label_text, "")) |
---|
1785 | gtk_label_set_text(GTK_LABEL(fontsel->message_label), ""); |
---|
1786 | gtk_font_selection_update_preview (fontsel); |
---|
1787 | return TRUE; |
---|
1788 | } |
---|
1789 | else |
---|
1790 | { |
---|
1791 | gtk_label_set_text(GTK_LABEL(fontsel->message_label), |
---|
1792 | _("The selected font is not available.")); |
---|
1793 | } |
---|
1794 | } |
---|
1795 | else |
---|
1796 | { |
---|
1797 | gtk_label_set_text(GTK_LABEL(fontsel->message_label), |
---|
1798 | _("The selected font is not a valid font.")); |
---|
1799 | } |
---|
1800 | |
---|
1801 | return FALSE; |
---|
1802 | } |
---|
1803 | |
---|
1804 | |
---|
1805 | /* This sets the font in the preview entry to the selected font, and tries to |
---|
1806 | make sure that the preview entry is a reasonable size, i.e. so that the |
---|
1807 | text can be seen with a bit of space to spare. But it tries to avoid |
---|
1808 | resizing the entry every time the font changes. |
---|
1809 | This also used to shrink the preview if the font size was decreased, but |
---|
1810 | that made it awkward if the user wanted to resize the window themself. */ |
---|
1811 | static void |
---|
1812 | gtk_font_selection_update_preview (GtkFontSelection *fontsel) |
---|
1813 | { |
---|
1814 | GtkWidget *preview_entry; |
---|
1815 | GtkStyle *style; |
---|
1816 | gint text_height, new_height; |
---|
1817 | gchar *text; |
---|
1818 | XFontStruct *xfs; |
---|
1819 | |
---|
1820 | #ifdef FONTSEL_DEBUG |
---|
1821 | g_message("In update_preview\n"); |
---|
1822 | #endif |
---|
1823 | style = gtk_style_new (); |
---|
1824 | gdk_font_unref (style->font); |
---|
1825 | style->font = fontsel->font; |
---|
1826 | gdk_font_ref (style->font); |
---|
1827 | |
---|
1828 | preview_entry = fontsel->preview_entry; |
---|
1829 | gtk_widget_set_style (preview_entry, style); |
---|
1830 | gtk_style_unref(style); |
---|
1831 | |
---|
1832 | text_height = preview_entry->style->font->ascent |
---|
1833 | + preview_entry->style->font->descent; |
---|
1834 | /* We don't ever want to be over MAX_PREVIEW_HEIGHT pixels high. */ |
---|
1835 | new_height = text_height + 20; |
---|
1836 | if (new_height < INITIAL_PREVIEW_HEIGHT) |
---|
1837 | new_height = INITIAL_PREVIEW_HEIGHT; |
---|
1838 | if (new_height > MAX_PREVIEW_HEIGHT) |
---|
1839 | new_height = MAX_PREVIEW_HEIGHT; |
---|
1840 | |
---|
1841 | if ((preview_entry->requisition.height < text_height + 10) |
---|
1842 | || (preview_entry->requisition.height > text_height + 40)) |
---|
1843 | gtk_widget_set_usize(preview_entry, -1, new_height); |
---|
1844 | |
---|
1845 | /* This sets the preview text, if it hasn't been set already. */ |
---|
1846 | text = gtk_entry_get_text(GTK_ENTRY(fontsel->preview_entry)); |
---|
1847 | if (strlen(text) == 0) |
---|
1848 | gtk_entry_set_text(GTK_ENTRY(fontsel->preview_entry), PREVIEW_TEXT); |
---|
1849 | gtk_entry_set_position(GTK_ENTRY(fontsel->preview_entry), 0); |
---|
1850 | |
---|
1851 | /* If this is a 2-byte font display a message to say it may not be |
---|
1852 | displayed properly. */ |
---|
1853 | xfs = GDK_FONT_XFONT(fontsel->font); |
---|
1854 | if (xfs->min_byte1 != 0 || xfs->max_byte1 != 0) |
---|
1855 | gtk_label_set_text(GTK_LABEL(fontsel->message_label), |
---|
1856 | _("This is a 2-byte font and may not be displayed correctly.")); |
---|
1857 | } |
---|
1858 | |
---|
1859 | |
---|
1860 | static void |
---|
1861 | gtk_font_selection_switch_page (GtkWidget *w, |
---|
1862 | GtkNotebookPage *page, |
---|
1863 | gint page_num, |
---|
1864 | gpointer data) |
---|
1865 | { |
---|
1866 | GtkFontSelection *fontsel = GTK_FONT_SELECTION(data); |
---|
1867 | |
---|
1868 | /* This function strangely gets called when the window is destroyed, |
---|
1869 | so we check here to see if the notebook is visible. */ |
---|
1870 | if (!GTK_WIDGET_VISIBLE(w)) |
---|
1871 | return; |
---|
1872 | |
---|
1873 | if (page_num == 0) |
---|
1874 | gtk_font_selection_update_filter(fontsel); |
---|
1875 | else if (page_num == 1) |
---|
1876 | gtk_font_selection_show_font_info(fontsel); |
---|
1877 | } |
---|
1878 | |
---|
1879 | |
---|
1880 | static void |
---|
1881 | gtk_font_selection_show_font_info (GtkFontSelection *fontsel) |
---|
1882 | { |
---|
1883 | Atom font_atom, atom; |
---|
1884 | Bool status; |
---|
1885 | char *name; |
---|
1886 | gchar *fontname; |
---|
1887 | gchar field_buffer[XLFD_MAX_FIELD_LEN]; |
---|
1888 | gchar *field; |
---|
1889 | gint i; |
---|
1890 | gboolean shown_actual_fields = FALSE; |
---|
1891 | |
---|
1892 | fontname = gtk_font_selection_get_font_name(fontsel); |
---|
1893 | gtk_entry_set_text(GTK_ENTRY(fontsel->requested_font_name), |
---|
1894 | fontname ? fontname : ""); |
---|
1895 | |
---|
1896 | gtk_clist_freeze (GTK_CLIST(fontsel->info_clist)); |
---|
1897 | for (i = 0; i < GTK_XLFD_NUM_FIELDS; i++) |
---|
1898 | { |
---|
1899 | if (fontname) |
---|
1900 | field = gtk_font_selection_get_xlfd_field (fontname, i, field_buffer); |
---|
1901 | else |
---|
1902 | field = NULL; |
---|
1903 | if (field) |
---|
1904 | { |
---|
1905 | if (i == XLFD_SLANT) |
---|
1906 | field = gtk_font_selection_expand_slant_code(field); |
---|
1907 | else if (i == XLFD_SPACING) |
---|
1908 | field = gtk_font_selection_expand_spacing_code(field); |
---|
1909 | } |
---|
1910 | gtk_clist_set_text(GTK_CLIST(fontsel->info_clist), i, 1, |
---|
1911 | field ? field : ""); |
---|
1912 | } |
---|
1913 | |
---|
1914 | if (fontsel->font) |
---|
1915 | { |
---|
1916 | font_atom = gdk_atom_intern ("FONT", FALSE); |
---|
1917 | |
---|
1918 | if (fontsel->font->type == GDK_FONT_FONTSET) |
---|
1919 | { |
---|
1920 | XFontStruct **font_structs; |
---|
1921 | gint num_fonts; |
---|
1922 | gchar **font_names; |
---|
1923 | |
---|
1924 | num_fonts = XFontsOfFontSet (GDK_FONT_XFONT(fontsel->font), |
---|
1925 | &font_structs, &font_names); |
---|
1926 | status = XGetFontProperty(font_structs[0], font_atom, &atom); |
---|
1927 | } |
---|
1928 | else |
---|
1929 | { |
---|
1930 | status = XGetFontProperty(GDK_FONT_XFONT(fontsel->font), font_atom, |
---|
1931 | &atom); |
---|
1932 | } |
---|
1933 | |
---|
1934 | if (status == True) |
---|
1935 | { |
---|
1936 | name = gdk_atom_name (atom); |
---|
1937 | gtk_entry_set_text(GTK_ENTRY(fontsel->actual_font_name), name); |
---|
1938 | |
---|
1939 | for (i = 0; i < GTK_XLFD_NUM_FIELDS; i++) |
---|
1940 | { |
---|
1941 | field = gtk_font_selection_get_xlfd_field (name, i, |
---|
1942 | field_buffer); |
---|
1943 | if (i == XLFD_SLANT) |
---|
1944 | field = gtk_font_selection_expand_slant_code(field); |
---|
1945 | else if (i == XLFD_SPACING) |
---|
1946 | field = gtk_font_selection_expand_spacing_code(field); |
---|
1947 | gtk_clist_set_text(GTK_CLIST(fontsel->info_clist), i, 2, |
---|
1948 | field ? field : ""); |
---|
1949 | } |
---|
1950 | shown_actual_fields = TRUE; |
---|
1951 | g_free (name); |
---|
1952 | } |
---|
1953 | } |
---|
1954 | if (!shown_actual_fields) |
---|
1955 | { |
---|
1956 | gtk_entry_set_text(GTK_ENTRY(fontsel->actual_font_name), ""); |
---|
1957 | for (i = 0; i < GTK_XLFD_NUM_FIELDS; i++) |
---|
1958 | { |
---|
1959 | gtk_clist_set_text(GTK_CLIST(fontsel->info_clist), i, 2, |
---|
1960 | fontname ? _("(unknown)") : ""); |
---|
1961 | } |
---|
1962 | } |
---|
1963 | gtk_clist_thaw (GTK_CLIST(fontsel->info_clist)); |
---|
1964 | g_free(fontname); |
---|
1965 | } |
---|
1966 | |
---|
1967 | |
---|
1968 | static gchar* |
---|
1969 | gtk_font_selection_expand_slant_code(gchar *slant) |
---|
1970 | { |
---|
1971 | if (!g_strcasecmp(slant, "r")) return(_("roman")); |
---|
1972 | else if (!g_strcasecmp(slant, "i")) return(_("italic")); |
---|
1973 | else if (!g_strcasecmp(slant, "o")) return(_("oblique")); |
---|
1974 | else if (!g_strcasecmp(slant, "ri")) return(_("reverse italic")); |
---|
1975 | else if (!g_strcasecmp(slant, "ro")) return(_("reverse oblique")); |
---|
1976 | else if (!g_strcasecmp(slant, "ot")) return(_("other")); |
---|
1977 | return slant; |
---|
1978 | } |
---|
1979 | |
---|
1980 | static gchar* |
---|
1981 | gtk_font_selection_expand_spacing_code(gchar *spacing) |
---|
1982 | { |
---|
1983 | if (!g_strcasecmp(spacing, "p")) return(_("proportional")); |
---|
1984 | else if (!g_strcasecmp(spacing, "m")) return(_("monospaced")); |
---|
1985 | else if (!g_strcasecmp(spacing, "c")) return(_("char cell")); |
---|
1986 | return spacing; |
---|
1987 | } |
---|
1988 | |
---|
1989 | |
---|
1990 | /***************************************************************************** |
---|
1991 | * These functions all deal with the Filter page and filtering the fonts. |
---|
1992 | *****************************************************************************/ |
---|
1993 | |
---|
1994 | /* This is called when an item is selected in one of the filter clists. |
---|
1995 | We make sure that the first row of the clist, i.e. the wildcard '*', is |
---|
1996 | selected if and only if none of the other items are selected. |
---|
1997 | Also doesn't allow selections of values filtered out by base filter. |
---|
1998 | We may need to be careful about triggering other signals. */ |
---|
1999 | static void |
---|
2000 | gtk_font_selection_select_filter (GtkWidget *w, |
---|
2001 | gint row, |
---|
2002 | gint column, |
---|
2003 | GdkEventButton *bevent, |
---|
2004 | GtkFontSelection *fontsel) |
---|
2005 | { |
---|
2006 | gint i, prop, index; |
---|
2007 | |
---|
2008 | if (row == 0) |
---|
2009 | { |
---|
2010 | for (i = 1; i < GTK_CLIST(w)->rows; i++) |
---|
2011 | gtk_clist_unselect_row(GTK_CLIST(w), i, 0); |
---|
2012 | } |
---|
2013 | else |
---|
2014 | { |
---|
2015 | /* Find out which property this is. */ |
---|
2016 | for (prop = 0; prop < GTK_NUM_FONT_PROPERTIES; prop++) |
---|
2017 | if (fontsel->filter_clists[prop] == w) |
---|
2018 | break; |
---|
2019 | index = GPOINTER_TO_INT (gtk_clist_get_row_data(GTK_CLIST(w), row)); |
---|
2020 | if (gtk_font_selection_filter_state (fontsel, GTK_FONT_FILTER_BASE, |
---|
2021 | prop, index) == NOT_FILTERED) |
---|
2022 | gtk_clist_unselect_row(GTK_CLIST(w), row, 0); |
---|
2023 | else |
---|
2024 | gtk_clist_unselect_row(GTK_CLIST(w), 0, 0); |
---|
2025 | } |
---|
2026 | } |
---|
2027 | |
---|
2028 | |
---|
2029 | /* Here a filter item is being deselected. If there are now no items selected |
---|
2030 | we select the first '*' item, unless that it is the item being deselected, |
---|
2031 | in which case we select all of the other items. This makes it easy to |
---|
2032 | select all items in the list except one or two. */ |
---|
2033 | static void |
---|
2034 | gtk_font_selection_unselect_filter (GtkWidget *w, |
---|
2035 | gint row, |
---|
2036 | gint column, |
---|
2037 | GdkEventButton *bevent, |
---|
2038 | GtkFontSelection *fontsel) |
---|
2039 | { |
---|
2040 | gint i, prop, index; |
---|
2041 | |
---|
2042 | if (!GTK_CLIST(w)->selection) |
---|
2043 | { |
---|
2044 | if (row == 0) |
---|
2045 | { |
---|
2046 | /* Find out which property this is. */ |
---|
2047 | for (prop = 0; prop < GTK_NUM_FONT_PROPERTIES; prop++) |
---|
2048 | if (fontsel->filter_clists[prop] == w) |
---|
2049 | break; |
---|
2050 | |
---|
2051 | for (i = 1; i < GTK_CLIST(w)->rows; i++) |
---|
2052 | { |
---|
2053 | index = GPOINTER_TO_INT (gtk_clist_get_row_data(GTK_CLIST(w), |
---|
2054 | i)); |
---|
2055 | if (gtk_font_selection_filter_state (fontsel, |
---|
2056 | GTK_FONT_FILTER_BASE, |
---|
2057 | prop, index) |
---|
2058 | != NOT_FILTERED) |
---|
2059 | gtk_clist_select_row(GTK_CLIST(w), i, 0); |
---|
2060 | } |
---|
2061 | } |
---|
2062 | else |
---|
2063 | { |
---|
2064 | gtk_clist_select_row(GTK_CLIST(w), 0, 0); |
---|
2065 | } |
---|
2066 | } |
---|
2067 | } |
---|
2068 | |
---|
2069 | |
---|
2070 | /* This is called when the main notebook page is selected. It checks if the |
---|
2071 | filter has changed, an if so it creates the filter settings, and filters the |
---|
2072 | fonts shown. If an empty filter (all '*'s) is applied, then filtering is |
---|
2073 | turned off. */ |
---|
2074 | static void |
---|
2075 | gtk_font_selection_update_filter (GtkFontSelection *fontsel) |
---|
2076 | { |
---|
2077 | GtkWidget *clist; |
---|
2078 | GList *selection; |
---|
2079 | gboolean default_filter = TRUE, filter_changed = FALSE; |
---|
2080 | gint prop, nselected, i, row, index; |
---|
2081 | GtkFontFilter *filter = &fontsel->filters[GTK_FONT_FILTER_USER]; |
---|
2082 | gint base_font_type, user_font_type, new_font_type; |
---|
2083 | |
---|
2084 | #ifdef FONTSEL_DEBUG |
---|
2085 | g_message("In update_filter\n"); |
---|
2086 | #endif |
---|
2087 | |
---|
2088 | /* Check if the user filter has changed, and also if it is the default |
---|
2089 | filter, i.e. bitmap & scalable fonts and all '*'s selected. |
---|
2090 | We only look at the bits which are not already filtered out by the base |
---|
2091 | filter, since that overrides the user filter. */ |
---|
2092 | base_font_type = fontsel->filters[GTK_FONT_FILTER_BASE].font_type |
---|
2093 | & GTK_FONT_ALL; |
---|
2094 | user_font_type = fontsel->filters[GTK_FONT_FILTER_USER].font_type |
---|
2095 | & GTK_FONT_ALL; |
---|
2096 | new_font_type = GTK_TOGGLE_BUTTON(fontsel->type_bitmaps_button)->active |
---|
2097 | ? GTK_FONT_BITMAP : 0; |
---|
2098 | new_font_type |= (GTK_TOGGLE_BUTTON(fontsel->type_scalable_button)->active |
---|
2099 | ? GTK_FONT_SCALABLE : 0); |
---|
2100 | new_font_type |= (GTK_TOGGLE_BUTTON(fontsel->type_scaled_bitmaps_button)->active ? GTK_FONT_SCALABLE_BITMAP : 0); |
---|
2101 | new_font_type &= base_font_type; |
---|
2102 | new_font_type |= (~base_font_type & user_font_type); |
---|
2103 | if (new_font_type != (GTK_FONT_BITMAP | GTK_FONT_SCALABLE)) |
---|
2104 | default_filter = FALSE; |
---|
2105 | |
---|
2106 | if (new_font_type != user_font_type) |
---|
2107 | filter_changed = TRUE; |
---|
2108 | fontsel->filters[GTK_FONT_FILTER_USER].font_type = new_font_type; |
---|
2109 | |
---|
2110 | for (prop = 0; prop < GTK_NUM_FONT_PROPERTIES; prop++) |
---|
2111 | { |
---|
2112 | clist = fontsel->filter_clists[prop]; |
---|
2113 | selection = GTK_CLIST(clist)->selection; |
---|
2114 | nselected = g_list_length(selection); |
---|
2115 | if (nselected != 1 || GPOINTER_TO_INT (selection->data) != 0) |
---|
2116 | { |
---|
2117 | default_filter = FALSE; |
---|
2118 | |
---|
2119 | if (filter->property_nfilters[prop] != nselected) |
---|
2120 | filter_changed = TRUE; |
---|
2121 | else |
---|
2122 | { |
---|
2123 | for (i = 0; i < nselected; i++) |
---|
2124 | { |
---|
2125 | row = GPOINTER_TO_INT (selection->data); |
---|
2126 | index = GPOINTER_TO_INT (gtk_clist_get_row_data (GTK_CLIST (clist), row)); |
---|
2127 | if (filter->property_filters[prop][i] != index) |
---|
2128 | filter_changed = TRUE; |
---|
2129 | selection = selection->next; |
---|
2130 | } |
---|
2131 | } |
---|
2132 | } |
---|
2133 | else |
---|
2134 | { |
---|
2135 | if (filter->property_nfilters[prop] != 0) |
---|
2136 | filter_changed = TRUE; |
---|
2137 | } |
---|
2138 | } |
---|
2139 | |
---|
2140 | /* If the filter hasn't changed we just return. */ |
---|
2141 | if (!filter_changed) |
---|
2142 | return; |
---|
2143 | |
---|
2144 | #ifdef FONTSEL_DEBUG |
---|
2145 | g_message(" update_fonts: filter has changed\n"); |
---|
2146 | #endif |
---|
2147 | |
---|
2148 | /* Free the old filter data and create the new arrays. */ |
---|
2149 | for (prop = 0; prop < GTK_NUM_FONT_PROPERTIES; prop++) |
---|
2150 | { |
---|
2151 | g_free(filter->property_filters[prop]); |
---|
2152 | |
---|
2153 | clist = fontsel->filter_clists[prop]; |
---|
2154 | selection = GTK_CLIST(clist)->selection; |
---|
2155 | nselected = g_list_length(selection); |
---|
2156 | if (nselected == 1 && GPOINTER_TO_INT (selection->data) == 0) |
---|
2157 | { |
---|
2158 | filter->property_filters[prop] = NULL; |
---|
2159 | filter->property_nfilters[prop] = 0; |
---|
2160 | } |
---|
2161 | else |
---|
2162 | { |
---|
2163 | filter->property_filters[prop] = g_new(guint16, nselected); |
---|
2164 | filter->property_nfilters[prop] = nselected; |
---|
2165 | for (i = 0; i < nselected; i++) |
---|
2166 | { |
---|
2167 | row = GPOINTER_TO_INT (selection->data); |
---|
2168 | index = GPOINTER_TO_INT (gtk_clist_get_row_data (GTK_CLIST (clist), row)); |
---|
2169 | filter->property_filters[prop][i] = index; |
---|
2170 | selection = selection->next; |
---|
2171 | } |
---|
2172 | } |
---|
2173 | } |
---|
2174 | |
---|
2175 | /* Set the 'Reset Filter' button sensitive if a filter is in effect, and |
---|
2176 | also set the label above the font list to show this as well. */ |
---|
2177 | if (default_filter) |
---|
2178 | { |
---|
2179 | gtk_widget_set_sensitive(fontsel->filter_button, FALSE); |
---|
2180 | gtk_label_set_text(GTK_LABEL(fontsel->font_label), _("Font:")); |
---|
2181 | } |
---|
2182 | else |
---|
2183 | { |
---|
2184 | gtk_widget_set_sensitive(fontsel->filter_button, TRUE); |
---|
2185 | gtk_label_set_text(GTK_LABEL(fontsel->font_label), _("Font: (Filter Applied)")); |
---|
2186 | } |
---|
2187 | gtk_font_selection_show_available_fonts(fontsel); |
---|
2188 | } |
---|
2189 | |
---|
2190 | |
---|
2191 | /* This shows all the available fonts in the font clist. */ |
---|
2192 | static void |
---|
2193 | gtk_font_selection_show_available_fonts (GtkFontSelection *fontsel) |
---|
2194 | { |
---|
2195 | FontInfo *font_info, *font; |
---|
2196 | GtkFontFilter *filter; |
---|
2197 | gint nfonts, i, j, k, row, style, font_row = -1; |
---|
2198 | gchar font_buffer[XLFD_MAX_FIELD_LEN * 2 + 4]; |
---|
2199 | gchar *font_item; |
---|
2200 | gboolean matched, matched_style; |
---|
2201 | |
---|
2202 | #ifdef FONTSEL_DEBUG |
---|
2203 | g_message("In show_available_fonts\n"); |
---|
2204 | #endif |
---|
2205 | font_info = fontsel_info->font_info; |
---|
2206 | nfonts = fontsel_info->nfonts; |
---|
2207 | |
---|
2208 | /* Filter the list of fonts. */ |
---|
2209 | gtk_clist_freeze (GTK_CLIST(fontsel->font_clist)); |
---|
2210 | gtk_clist_clear (GTK_CLIST(fontsel->font_clist)); |
---|
2211 | for (i = 0; i < nfonts; i++) |
---|
2212 | { |
---|
2213 | font = &font_info[i]; |
---|
2214 | |
---|
2215 | /* Check if the foundry passes through all filters. */ |
---|
2216 | matched = TRUE; |
---|
2217 | for (k = 0; k < GTK_NUM_FONT_FILTERS; k++) |
---|
2218 | { |
---|
2219 | filter = &fontsel->filters[k]; |
---|
2220 | |
---|
2221 | if (filter->property_nfilters[FOUNDRY] != 0) |
---|
2222 | { |
---|
2223 | matched = FALSE; |
---|
2224 | for (j = 0; j < filter->property_nfilters[FOUNDRY]; j++) |
---|
2225 | { |
---|
2226 | if (font->foundry == filter->property_filters[FOUNDRY][j]) |
---|
2227 | { |
---|
2228 | matched = TRUE; |
---|
2229 | break; |
---|
2230 | } |
---|
2231 | } |
---|
2232 | if (!matched) |
---|
2233 | break; |
---|
2234 | } |
---|
2235 | } |
---|
2236 | |
---|
2237 | if (!matched) |
---|
2238 | continue; |
---|
2239 | |
---|
2240 | |
---|
2241 | /* Now check if the other properties are matched in at least one style.*/ |
---|
2242 | matched_style = FALSE; |
---|
2243 | for (style = 0; style < font->nstyles; style++) |
---|
2244 | { |
---|
2245 | if (gtk_font_selection_style_visible(fontsel, font, style)) |
---|
2246 | { |
---|
2247 | matched_style = TRUE; |
---|
2248 | break; |
---|
2249 | } |
---|
2250 | } |
---|
2251 | if (!matched_style) |
---|
2252 | continue; |
---|
2253 | |
---|
2254 | /* Insert the font in the clist. */ |
---|
2255 | if ((i > 0 && font->family == font_info[i-1].family) |
---|
2256 | || (i < nfonts - 1 && font->family == font_info[i+1].family)) |
---|
2257 | { |
---|
2258 | sprintf(font_buffer, "%s (%s)", font->family, |
---|
2259 | fontsel_info->properties[FOUNDRY][font->foundry]); |
---|
2260 | font_item = font_buffer; |
---|
2261 | row = gtk_clist_append(GTK_CLIST(fontsel->font_clist), &font_item); |
---|
2262 | } |
---|
2263 | else |
---|
2264 | { |
---|
2265 | row = gtk_clist_append(GTK_CLIST(fontsel->font_clist), |
---|
2266 | &font->family); |
---|
2267 | } |
---|
2268 | gtk_clist_set_row_data(GTK_CLIST(fontsel->font_clist), row, |
---|
2269 | GINT_TO_POINTER (i)); |
---|
2270 | if (fontsel->font_index == i) |
---|
2271 | font_row = row; |
---|
2272 | } |
---|
2273 | gtk_clist_thaw (GTK_CLIST(fontsel->font_clist)); |
---|
2274 | |
---|
2275 | /* If the currently-selected font isn't in the new list, reset the |
---|
2276 | selection. */ |
---|
2277 | if (font_row == -1) |
---|
2278 | { |
---|
2279 | fontsel->font_index = -1; |
---|
2280 | if (fontsel->font) |
---|
2281 | gdk_font_unref(fontsel->font); |
---|
2282 | fontsel->font = NULL; |
---|
2283 | gtk_entry_set_text(GTK_ENTRY(fontsel->font_entry), ""); |
---|
2284 | gtk_clist_clear (GTK_CLIST(fontsel->font_style_clist)); |
---|
2285 | gtk_entry_set_text(GTK_ENTRY(fontsel->font_style_entry), ""); |
---|
2286 | return; |
---|
2287 | } |
---|
2288 | |
---|
2289 | gtk_clist_select_row(GTK_CLIST(fontsel->font_clist), font_row, 0); |
---|
2290 | if (gtk_clist_row_is_visible(GTK_CLIST(fontsel->font_clist), font_row) |
---|
2291 | != GTK_VISIBILITY_FULL) |
---|
2292 | gtk_clist_moveto(GTK_CLIST(fontsel->font_clist), font_row, -1, 0.5, 0); |
---|
2293 | |
---|
2294 | gtk_font_selection_show_available_styles (fontsel); |
---|
2295 | gtk_font_selection_select_best_style (fontsel, FALSE); |
---|
2296 | } |
---|
2297 | |
---|
2298 | |
---|
2299 | /* Returns TRUE if the style is not currently filtered out. */ |
---|
2300 | static gboolean |
---|
2301 | gtk_font_selection_style_visible(GtkFontSelection *fontsel, |
---|
2302 | FontInfo *font, |
---|
2303 | gint style_index) |
---|
2304 | { |
---|
2305 | FontStyle *styles, *style; |
---|
2306 | GtkFontFilter *filter; |
---|
2307 | guint16 value; |
---|
2308 | gint prop, i, j; |
---|
2309 | gboolean matched; |
---|
2310 | gint type_filter; |
---|
2311 | |
---|
2312 | styles = &fontsel_info->font_styles[font->style_index]; |
---|
2313 | style = &styles[style_index]; |
---|
2314 | |
---|
2315 | /* Check if font_type of style is filtered. */ |
---|
2316 | type_filter = fontsel->filters[GTK_FONT_FILTER_BASE].font_type |
---|
2317 | & fontsel->filters[GTK_FONT_FILTER_USER].font_type; |
---|
2318 | if (!(style->flags & type_filter)) |
---|
2319 | return FALSE; |
---|
2320 | |
---|
2321 | for (prop = 0; prop < GTK_NUM_STYLE_PROPERTIES; prop++) |
---|
2322 | { |
---|
2323 | value = style->properties[prop]; |
---|
2324 | |
---|
2325 | /* Check each filter. */ |
---|
2326 | for (i = 0; i < GTK_NUM_FONT_FILTERS; i++) |
---|
2327 | { |
---|
2328 | filter = &fontsel->filters[i]; |
---|
2329 | |
---|
2330 | if (filter->property_nfilters[prop] != 0) |
---|
2331 | { |
---|
2332 | matched = FALSE; |
---|
2333 | for (j = 0; j < filter->property_nfilters[prop]; j++) |
---|
2334 | { |
---|
2335 | if (value == filter->property_filters[prop][j]) |
---|
2336 | { |
---|
2337 | matched = TRUE; |
---|
2338 | break; |
---|
2339 | } |
---|
2340 | } |
---|
2341 | if (!matched) |
---|
2342 | return FALSE; |
---|
2343 | } |
---|
2344 | } |
---|
2345 | } |
---|
2346 | return TRUE; |
---|
2347 | } |
---|
2348 | |
---|
2349 | |
---|
2350 | /* This resets the font type to bitmap or scalable, and sets all the filter |
---|
2351 | clists to the wildcard '*' options. */ |
---|
2352 | static void |
---|
2353 | gtk_font_selection_reset_filter (GtkWidget *w, |
---|
2354 | GtkFontSelection *fontsel) |
---|
2355 | { |
---|
2356 | gint prop, base_font_type; |
---|
2357 | |
---|
2358 | fontsel->filters[GTK_FONT_FILTER_USER].font_type = GTK_FONT_BITMAP |
---|
2359 | | GTK_FONT_SCALABLE; |
---|
2360 | |
---|
2361 | base_font_type = fontsel->filters[GTK_FONT_FILTER_BASE].font_type; |
---|
2362 | if (base_font_type & GTK_FONT_BITMAP) |
---|
2363 | gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fontsel->type_bitmaps_button), TRUE); |
---|
2364 | if (base_font_type & GTK_FONT_SCALABLE) |
---|
2365 | gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fontsel->type_scalable_button), TRUE); |
---|
2366 | if (base_font_type & GTK_FONT_SCALABLE_BITMAP) |
---|
2367 | gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fontsel->type_scaled_bitmaps_button), FALSE); |
---|
2368 | |
---|
2369 | for (prop = 0; prop < GTK_NUM_FONT_PROPERTIES; prop++) |
---|
2370 | gtk_clist_select_row(GTK_CLIST(fontsel->filter_clists[prop]), 0, 0); |
---|
2371 | } |
---|
2372 | |
---|
2373 | |
---|
2374 | /* This clears the filter, showing all fonts and styles again. */ |
---|
2375 | static void |
---|
2376 | gtk_font_selection_on_clear_filter (GtkWidget *w, |
---|
2377 | GtkFontSelection *fontsel) |
---|
2378 | { |
---|
2379 | gtk_font_selection_clear_filter(fontsel); |
---|
2380 | } |
---|
2381 | |
---|
2382 | |
---|
2383 | /* This resets the user filter, showing all fonts and styles which pass the |
---|
2384 | base filter again. Note that the font type is set to bitmaps and scalable |
---|
2385 | fonts - scaled bitmaps are not shown. */ |
---|
2386 | static void |
---|
2387 | gtk_font_selection_clear_filter (GtkFontSelection *fontsel) |
---|
2388 | { |
---|
2389 | GtkFontFilter *filter; |
---|
2390 | gint prop; |
---|
2391 | |
---|
2392 | #ifdef FONTSEL_DEBUG |
---|
2393 | g_message("In clear_filter\n"); |
---|
2394 | #endif |
---|
2395 | /* Clear the filter data. */ |
---|
2396 | filter = &fontsel->filters[GTK_FONT_FILTER_USER]; |
---|
2397 | filter->font_type = GTK_FONT_BITMAP | GTK_FONT_SCALABLE; |
---|
2398 | for (prop = 0; prop < GTK_NUM_FONT_PROPERTIES; prop++) |
---|
2399 | { |
---|
2400 | g_free(filter->property_filters[prop]); |
---|
2401 | filter->property_filters[prop] = NULL; |
---|
2402 | filter->property_nfilters[prop] = 0; |
---|
2403 | } |
---|
2404 | |
---|
2405 | /* Select all the '*'s on the filter page. */ |
---|
2406 | gtk_font_selection_reset_filter(NULL, fontsel); |
---|
2407 | |
---|
2408 | /* Update the main notebook page. */ |
---|
2409 | gtk_widget_set_sensitive(fontsel->filter_button, FALSE); |
---|
2410 | gtk_label_set_text(GTK_LABEL(fontsel->font_label), _("Font:")); |
---|
2411 | |
---|
2412 | gtk_font_selection_show_available_fonts(fontsel); |
---|
2413 | } |
---|
2414 | |
---|
2415 | |
---|
2416 | void |
---|
2417 | gtk_font_selection_set_filter (GtkFontSelection *fontsel, |
---|
2418 | GtkFontFilterType filter_type, |
---|
2419 | GtkFontType font_type, |
---|
2420 | gchar **foundries, |
---|
2421 | gchar **weights, |
---|
2422 | gchar **slants, |
---|
2423 | gchar **setwidths, |
---|
2424 | gchar **spacings, |
---|
2425 | gchar **charsets) |
---|
2426 | { |
---|
2427 | GtkFontFilter *filter; |
---|
2428 | gchar **filter_strings [GTK_NUM_FONT_PROPERTIES]; |
---|
2429 | gchar *filter_string; |
---|
2430 | gchar *property, *property_alt; |
---|
2431 | gint prop, nfilters, i, j, num_found; |
---|
2432 | gint base_font_type, user_font_type; |
---|
2433 | gboolean filter_set; |
---|
2434 | |
---|
2435 | /* Put them into an array so we can use a simple loop. */ |
---|
2436 | filter_strings[FOUNDRY] = foundries; |
---|
2437 | filter_strings[WEIGHT] = weights; |
---|
2438 | filter_strings[SLANT] = slants; |
---|
2439 | filter_strings[SET_WIDTH] = setwidths; |
---|
2440 | filter_strings[SPACING] = spacings; |
---|
2441 | filter_strings[CHARSET] = charsets; |
---|
2442 | |
---|
2443 | filter = &fontsel->filters[filter_type]; |
---|
2444 | filter->font_type = font_type; |
---|
2445 | |
---|
2446 | /* Free the old filter data, and insert the new. */ |
---|
2447 | for (prop = 0; prop < GTK_NUM_FONT_PROPERTIES; prop++) |
---|
2448 | { |
---|
2449 | g_free(filter->property_filters[prop]); |
---|
2450 | filter->property_filters[prop] = NULL; |
---|
2451 | filter->property_nfilters[prop] = 0; |
---|
2452 | |
---|
2453 | if (filter_strings[prop]) |
---|
2454 | { |
---|
2455 | /* Count how many items in the new array. */ |
---|
2456 | nfilters = 0; |
---|
2457 | while (filter_strings[prop][nfilters]) |
---|
2458 | nfilters++; |
---|
2459 | |
---|
2460 | filter->property_filters[prop] = g_new(guint16, nfilters); |
---|
2461 | filter->property_nfilters[prop] = 0; |
---|
2462 | |
---|
2463 | /* Now convert the strings to property indices. */ |
---|
2464 | num_found = 0; |
---|
2465 | for (i = 0; i < nfilters; i++) |
---|
2466 | { |
---|
2467 | filter_string = filter_strings[prop][i]; |
---|
2468 | for (j = 0; j < fontsel_info->nproperties[prop]; j++) |
---|
2469 | { |
---|
2470 | property = _(fontsel_info->properties[prop][j]); |
---|
2471 | property_alt = NULL; |
---|
2472 | if (prop == SLANT) |
---|
2473 | property_alt = gtk_font_selection_expand_slant_code(property); |
---|
2474 | else if (prop == SPACING) |
---|
2475 | property_alt = gtk_font_selection_expand_spacing_code(property); |
---|
2476 | if (!strcmp (filter_string, property) |
---|
2477 | || (property_alt && !strcmp (filter_string, property_alt))) |
---|
2478 | { |
---|
2479 | filter->property_filters[prop][num_found] = j; |
---|
2480 | num_found++; |
---|
2481 | break; |
---|
2482 | } |
---|
2483 | } |
---|
2484 | } |
---|
2485 | filter->property_nfilters[prop] = num_found; |
---|
2486 | } |
---|
2487 | } |
---|
2488 | |
---|
2489 | /* Now set the clists on the filter page according to the new filter. */ |
---|
2490 | gtk_font_selection_update_filter_lists (fontsel); |
---|
2491 | |
---|
2492 | if (filter_type == GTK_FONT_FILTER_BASE) |
---|
2493 | { |
---|
2494 | user_font_type = fontsel->filters[GTK_FONT_FILTER_USER].font_type; |
---|
2495 | if (font_type & GTK_FONT_BITMAP) |
---|
2496 | { |
---|
2497 | gtk_widget_set_sensitive (fontsel->type_bitmaps_button, TRUE); |
---|
2498 | gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fontsel->type_bitmaps_button), user_font_type & GTK_FONT_BITMAP); |
---|
2499 | } |
---|
2500 | else |
---|
2501 | { |
---|
2502 | gtk_widget_set_sensitive (fontsel->type_bitmaps_button, FALSE); |
---|
2503 | gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fontsel->type_bitmaps_button), FALSE); |
---|
2504 | } |
---|
2505 | |
---|
2506 | if (font_type & GTK_FONT_SCALABLE) |
---|
2507 | { |
---|
2508 | gtk_widget_set_sensitive (fontsel->type_scalable_button, TRUE); |
---|
2509 | gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fontsel->type_scalable_button), user_font_type & GTK_FONT_SCALABLE); |
---|
2510 | } |
---|
2511 | else |
---|
2512 | { |
---|
2513 | gtk_widget_set_sensitive (fontsel->type_scalable_button, FALSE); |
---|
2514 | gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fontsel->type_scalable_button), FALSE); |
---|
2515 | } |
---|
2516 | |
---|
2517 | if (font_type & GTK_FONT_SCALABLE_BITMAP) |
---|
2518 | { |
---|
2519 | gtk_widget_set_sensitive (fontsel->type_scaled_bitmaps_button, TRUE); |
---|
2520 | gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fontsel->type_scaled_bitmaps_button), user_font_type & GTK_FONT_SCALABLE_BITMAP); |
---|
2521 | } |
---|
2522 | else |
---|
2523 | { |
---|
2524 | gtk_widget_set_sensitive (fontsel->type_scaled_bitmaps_button, FALSE); |
---|
2525 | gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fontsel->type_scaled_bitmaps_button), FALSE); |
---|
2526 | } |
---|
2527 | } |
---|
2528 | else |
---|
2529 | { |
---|
2530 | base_font_type = fontsel->filters[GTK_FONT_FILTER_BASE].font_type; |
---|
2531 | if (base_font_type & GTK_FONT_BITMAP) |
---|
2532 | gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fontsel->type_bitmaps_button), font_type & GTK_FONT_BITMAP); |
---|
2533 | |
---|
2534 | if (base_font_type & GTK_FONT_SCALABLE) |
---|
2535 | gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fontsel->type_scalable_button), font_type & GTK_FONT_SCALABLE); |
---|
2536 | |
---|
2537 | if (base_font_type & GTK_FONT_SCALABLE_BITMAP) |
---|
2538 | gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fontsel->type_scaled_bitmaps_button), font_type & GTK_FONT_SCALABLE_BITMAP); |
---|
2539 | |
---|
2540 | /* If the user filter is not the default, make the 'Reset Filter' button |
---|
2541 | sensitive. */ |
---|
2542 | filter_set = FALSE; |
---|
2543 | if (font_type != (GTK_FONT_BITMAP | GTK_FONT_SCALABLE)) |
---|
2544 | filter_set = TRUE; |
---|
2545 | for (prop = 0; prop < GTK_NUM_FONT_PROPERTIES; prop++) |
---|
2546 | { |
---|
2547 | if (filter->property_nfilters[prop] != 0) |
---|
2548 | filter_set = TRUE; |
---|
2549 | } |
---|
2550 | if (filter_set) |
---|
2551 | gtk_widget_set_sensitive (fontsel->filter_button, TRUE); |
---|
2552 | } |
---|
2553 | |
---|
2554 | gtk_font_selection_show_available_fonts (fontsel); |
---|
2555 | } |
---|
2556 | |
---|
2557 | |
---|
2558 | /* This sets the colour of each property in the filter clists according to |
---|
2559 | the base filter. i.e. Filtered properties are shown as insensitive. */ |
---|
2560 | static void |
---|
2561 | gtk_font_selection_update_filter_lists (GtkFontSelection *fontsel) |
---|
2562 | { |
---|
2563 | GtkWidget *clist; |
---|
2564 | GdkColor *inactive_fg, *inactive_bg, *fg, *bg; |
---|
2565 | gint prop, row, index; |
---|
2566 | |
---|
2567 | /* We have to make sure the clist is realized to use the colours. */ |
---|
2568 | for (prop = 0; prop < GTK_NUM_FONT_PROPERTIES; prop++) |
---|
2569 | { |
---|
2570 | clist = fontsel->filter_clists[prop]; |
---|
2571 | gtk_widget_realize (clist); |
---|
2572 | inactive_fg = &clist->style->fg[GTK_STATE_INSENSITIVE]; |
---|
2573 | inactive_bg = &clist->style->bg[GTK_STATE_INSENSITIVE]; |
---|
2574 | for (row = 1; row < GTK_CLIST(clist)->rows; row++) |
---|
2575 | { |
---|
2576 | index = GPOINTER_TO_INT (gtk_clist_get_row_data(GTK_CLIST(clist), |
---|
2577 | row)); |
---|
2578 | /* Set the colour according to the base filter. */ |
---|
2579 | if (gtk_font_selection_filter_state (fontsel, GTK_FONT_FILTER_BASE, |
---|
2580 | prop, index) == NOT_FILTERED) |
---|
2581 | { |
---|
2582 | fg = inactive_fg; |
---|
2583 | bg = inactive_bg; |
---|
2584 | } |
---|
2585 | else |
---|
2586 | { |
---|
2587 | fg = NULL; |
---|
2588 | bg = NULL; |
---|
2589 | } |
---|
2590 | gtk_clist_set_foreground(GTK_CLIST(clist), row, fg); |
---|
2591 | gtk_clist_set_background(GTK_CLIST(clist), row, bg); |
---|
2592 | |
---|
2593 | /* Set the selection state according to the user filter. */ |
---|
2594 | if (gtk_font_selection_filter_state (fontsel, GTK_FONT_FILTER_USER, |
---|
2595 | prop, index) == FILTERED |
---|
2596 | && fg == NULL) |
---|
2597 | gtk_clist_select_row (GTK_CLIST (clist), row, 0); |
---|
2598 | else |
---|
2599 | gtk_clist_unselect_row (GTK_CLIST (clist), row, 0); |
---|
2600 | } |
---|
2601 | } |
---|
2602 | } |
---|
2603 | |
---|
2604 | |
---|
2605 | /* Returns whether a property value is in the filter or not, or if the |
---|
2606 | property has no filter set. */ |
---|
2607 | static GtkFontPropertyFilterState |
---|
2608 | gtk_font_selection_filter_state (GtkFontSelection *fontsel, |
---|
2609 | GtkFontFilterType filter_type, |
---|
2610 | gint property, |
---|
2611 | gint index) |
---|
2612 | { |
---|
2613 | GtkFontFilter *filter; |
---|
2614 | gint i; |
---|
2615 | |
---|
2616 | filter = &fontsel->filters[filter_type]; |
---|
2617 | if (filter->property_nfilters[property] == 0) |
---|
2618 | return NOT_SET; |
---|
2619 | |
---|
2620 | for (i = 0; i < filter->property_nfilters[property]; i++) |
---|
2621 | { |
---|
2622 | if (filter->property_filters[property][i] == index) |
---|
2623 | return FILTERED; |
---|
2624 | } |
---|
2625 | return NOT_FILTERED; |
---|
2626 | } |
---|
2627 | |
---|
2628 | |
---|
2629 | /***************************************************************************** |
---|
2630 | * These functions all deal with creating the main class arrays containing |
---|
2631 | * the data about all available fonts. |
---|
2632 | *****************************************************************************/ |
---|
2633 | static void |
---|
2634 | gtk_font_selection_get_fonts (void) |
---|
2635 | { |
---|
2636 | gchar **xfontnames; |
---|
2637 | GSList **fontnames; |
---|
2638 | gchar *fontname; |
---|
2639 | GSList * temp_list; |
---|
2640 | gint num_fonts; |
---|
2641 | gint i, prop, style, size; |
---|
2642 | gint npixel_sizes = 0, npoint_sizes = 0; |
---|
2643 | FontInfo *font; |
---|
2644 | FontStyle *current_style, *prev_style, *tmp_style; |
---|
2645 | gboolean matched_style, found_size; |
---|
2646 | gint pixels, points, res_x, res_y; |
---|
2647 | gchar field_buffer[XLFD_MAX_FIELD_LEN]; |
---|
2648 | gchar *field; |
---|
2649 | guint8 flags; |
---|
2650 | guint16 *pixel_sizes, *point_sizes, *tmp_sizes; |
---|
2651 | |
---|
2652 | fontsel_info = g_new (GtkFontSelInfo, 1); |
---|
2653 | |
---|
2654 | /* Get a maximum of MAX_FONTS fontnames from the X server. |
---|
2655 | Use "-*" as the pattern rather than "-*-*-*-*-*-*-*-*-*-*-*-*-*-*" since |
---|
2656 | the latter may result in fonts being returned which don't actually exist. |
---|
2657 | xlsfonts also uses "*" so I think it's OK. "-*" gets rid of aliases. */ |
---|
2658 | xfontnames = XListFonts (GDK_DISPLAY(), "-*", MAX_FONTS, &num_fonts); |
---|
2659 | /* Output a warning if we actually get MAX_FONTS fonts. */ |
---|
2660 | if (num_fonts == MAX_FONTS) |
---|
2661 | g_warning(_("MAX_FONTS exceeded. Some fonts may be missing.")); |
---|
2662 | |
---|
2663 | /* The maximum size of all these tables is the number of font names |
---|
2664 | returned. We realloc them later when we know exactly how many |
---|
2665 | unique entries there are. */ |
---|
2666 | fontsel_info->font_info = g_new (FontInfo, num_fonts); |
---|
2667 | fontsel_info->font_styles = g_new (FontStyle, num_fonts); |
---|
2668 | fontsel_info->pixel_sizes = g_new (guint16, num_fonts); |
---|
2669 | fontsel_info->point_sizes = g_new (guint16, num_fonts); |
---|
2670 | |
---|
2671 | fontnames = g_new (GSList*, num_fonts); |
---|
2672 | |
---|
2673 | /* Create the initial arrays for the property value strings, though they |
---|
2674 | may be realloc'ed later. Put the wildcard '*' in the first elements. */ |
---|
2675 | for (prop = 0; prop < GTK_NUM_FONT_PROPERTIES; prop++) |
---|
2676 | { |
---|
2677 | fontsel_info->properties[prop] = g_new(gchar*, PROPERTY_ARRAY_INCREMENT); |
---|
2678 | fontsel_info->space_allocated[prop] = PROPERTY_ARRAY_INCREMENT; |
---|
2679 | fontsel_info->nproperties[prop] = 1; |
---|
2680 | fontsel_info->properties[prop][0] = "*"; |
---|
2681 | } |
---|
2682 | |
---|
2683 | |
---|
2684 | /* Insert the font families into the main table, sorted by family and |
---|
2685 | foundry (fonts with different foundries are placed in seaparate FontInfos. |
---|
2686 | All fontnames in each family + foundry are placed into the fontnames |
---|
2687 | array of lists. */ |
---|
2688 | fontsel_info->nfonts = 0; |
---|
2689 | for (i = 0; i < num_fonts; i++) |
---|
2690 | { |
---|
2691 | #ifdef FONTSEL_DEBUG |
---|
2692 | g_message("%s\n", xfontnames[i]); |
---|
2693 | #endif |
---|
2694 | if (gtk_font_selection_is_xlfd_font_name (xfontnames[i])) |
---|
2695 | gtk_font_selection_insert_font (fontnames, &fontsel_info->nfonts, xfontnames[i]); |
---|
2696 | else |
---|
2697 | { |
---|
2698 | #ifdef FONTSEL_DEBUG |
---|
2699 | g_warning("Skipping invalid font: %s", xfontnames[i]); |
---|
2700 | #endif |
---|
2701 | } |
---|
2702 | } |
---|
2703 | |
---|
2704 | |
---|
2705 | /* Since many font names will be in the same FontInfo not all of the |
---|
2706 | allocated FontInfo table will be used, so we will now reallocate it |
---|
2707 | with the real size. */ |
---|
2708 | fontsel_info->font_info = g_realloc(fontsel_info->font_info, |
---|
2709 | sizeof(FontInfo) * fontsel_info->nfonts); |
---|
2710 | |
---|
2711 | |
---|
2712 | /* Now we work out which choices of weight/slant etc. are valid for each |
---|
2713 | font. */ |
---|
2714 | fontsel_info->nstyles = 0; |
---|
2715 | current_style = fontsel_info->font_styles; |
---|
2716 | for (i = 0; i < fontsel_info->nfonts; i++) |
---|
2717 | { |
---|
2718 | font = &fontsel_info->font_info[i]; |
---|
2719 | |
---|
2720 | /* Use the next free position in the styles array. */ |
---|
2721 | font->style_index = fontsel_info->nstyles; |
---|
2722 | |
---|
2723 | /* Now step through each of the fontnames with this family, and create |
---|
2724 | a style for each fontname. Each style contains the index into the |
---|
2725 | weights/slants etc. arrays, and a number of pixel/point sizes. */ |
---|
2726 | style = 0; |
---|
2727 | temp_list = fontnames[i]; |
---|
2728 | while (temp_list) |
---|
2729 | { |
---|
2730 | fontname = temp_list->data; |
---|
2731 | temp_list = temp_list->next; |
---|
2732 | |
---|
2733 | for (prop = 0; prop < GTK_NUM_STYLE_PROPERTIES; prop++) |
---|
2734 | { |
---|
2735 | current_style->properties[prop] |
---|
2736 | = gtk_font_selection_insert_field (fontname, prop); |
---|
2737 | } |
---|
2738 | current_style->pixel_sizes_index = npixel_sizes; |
---|
2739 | current_style->npixel_sizes = 0; |
---|
2740 | current_style->point_sizes_index = npoint_sizes; |
---|
2741 | current_style->npoint_sizes = 0; |
---|
2742 | current_style->flags = 0; |
---|
2743 | |
---|
2744 | |
---|
2745 | field = gtk_font_selection_get_xlfd_field (fontname, XLFD_PIXELS, |
---|
2746 | field_buffer); |
---|
2747 | pixels = atoi(field); |
---|
2748 | |
---|
2749 | field = gtk_font_selection_get_xlfd_field (fontname, XLFD_POINTS, |
---|
2750 | field_buffer); |
---|
2751 | points = atoi(field); |
---|
2752 | |
---|
2753 | field = gtk_font_selection_get_xlfd_field (fontname, |
---|
2754 | XLFD_RESOLUTION_X, |
---|
2755 | field_buffer); |
---|
2756 | res_x = atoi(field); |
---|
2757 | |
---|
2758 | field = gtk_font_selection_get_xlfd_field (fontname, |
---|
2759 | XLFD_RESOLUTION_Y, |
---|
2760 | field_buffer); |
---|
2761 | res_y = atoi(field); |
---|
2762 | |
---|
2763 | if (pixels == 0 && points == 0) |
---|
2764 | { |
---|
2765 | if (res_x == 0 && res_y == 0) |
---|
2766 | flags = GTK_FONT_SCALABLE; |
---|
2767 | else |
---|
2768 | flags = GTK_FONT_SCALABLE_BITMAP; |
---|
2769 | } |
---|
2770 | else |
---|
2771 | flags = GTK_FONT_BITMAP; |
---|
2772 | |
---|
2773 | /* Now we check to make sure that the style is unique. If it isn't |
---|
2774 | we forget it. */ |
---|
2775 | prev_style = fontsel_info->font_styles + font->style_index; |
---|
2776 | matched_style = FALSE; |
---|
2777 | while (prev_style < current_style) |
---|
2778 | { |
---|
2779 | matched_style = TRUE; |
---|
2780 | for (prop = 0; prop < GTK_NUM_STYLE_PROPERTIES; prop++) |
---|
2781 | { |
---|
2782 | if (prev_style->properties[prop] |
---|
2783 | != current_style->properties[prop]) |
---|
2784 | { |
---|
2785 | matched_style = FALSE; |
---|
2786 | break; |
---|
2787 | } |
---|
2788 | } |
---|
2789 | if (matched_style) |
---|
2790 | break; |
---|
2791 | prev_style++; |
---|
2792 | } |
---|
2793 | |
---|
2794 | /* If we matched an existing style, we need to add the pixels & |
---|
2795 | point sizes to the style. If not, we insert the pixel & point |
---|
2796 | sizes into our new style. Note that we don't add sizes for |
---|
2797 | scalable fonts. */ |
---|
2798 | if (matched_style) |
---|
2799 | { |
---|
2800 | prev_style->flags |= flags; |
---|
2801 | if (flags == GTK_FONT_BITMAP) |
---|
2802 | { |
---|
2803 | pixel_sizes = fontsel_info->pixel_sizes |
---|
2804 | + prev_style->pixel_sizes_index; |
---|
2805 | found_size = FALSE; |
---|
2806 | for (size = 0; size < prev_style->npixel_sizes; size++) |
---|
2807 | { |
---|
2808 | if (pixels == *pixel_sizes) |
---|
2809 | { |
---|
2810 | found_size = TRUE; |
---|
2811 | break; |
---|
2812 | } |
---|
2813 | else if (pixels < *pixel_sizes) |
---|
2814 | break; |
---|
2815 | pixel_sizes++; |
---|
2816 | } |
---|
2817 | /* We need to move all the following pixel sizes up, and also |
---|
2818 | update the indexes of any following styles. */ |
---|
2819 | if (!found_size) |
---|
2820 | { |
---|
2821 | for (tmp_sizes = fontsel_info->pixel_sizes + npixel_sizes; |
---|
2822 | tmp_sizes > pixel_sizes; tmp_sizes--) |
---|
2823 | *tmp_sizes = *(tmp_sizes - 1); |
---|
2824 | |
---|
2825 | *pixel_sizes = pixels; |
---|
2826 | npixel_sizes++; |
---|
2827 | prev_style->npixel_sizes++; |
---|
2828 | |
---|
2829 | tmp_style = prev_style + 1; |
---|
2830 | while (tmp_style < current_style) |
---|
2831 | { |
---|
2832 | tmp_style->pixel_sizes_index++; |
---|
2833 | tmp_style++; |
---|
2834 | } |
---|
2835 | } |
---|
2836 | |
---|
2837 | point_sizes = fontsel_info->point_sizes |
---|
2838 | + prev_style->point_sizes_index; |
---|
2839 | found_size = FALSE; |
---|
2840 | for (size = 0; size < prev_style->npoint_sizes; size++) |
---|
2841 | { |
---|
2842 | if (points == *point_sizes) |
---|
2843 | { |
---|
2844 | found_size = TRUE; |
---|
2845 | break; |
---|
2846 | } |
---|
2847 | else if (points < *point_sizes) |
---|
2848 | break; |
---|
2849 | point_sizes++; |
---|
2850 | } |
---|
2851 | /* We need to move all the following point sizes up, and also |
---|
2852 | update the indexes of any following styles. */ |
---|
2853 | if (!found_size) |
---|
2854 | { |
---|
2855 | for (tmp_sizes = fontsel_info->point_sizes + npoint_sizes; |
---|
2856 | tmp_sizes > point_sizes; tmp_sizes--) |
---|
2857 | *tmp_sizes = *(tmp_sizes - 1); |
---|
2858 | |
---|
2859 | *point_sizes = points; |
---|
2860 | npoint_sizes++; |
---|
2861 | prev_style->npoint_sizes++; |
---|
2862 | |
---|
2863 | tmp_style = prev_style + 1; |
---|
2864 | while (tmp_style < current_style) |
---|
2865 | { |
---|
2866 | tmp_style->point_sizes_index++; |
---|
2867 | tmp_style++; |
---|
2868 | } |
---|
2869 | } |
---|
2870 | } |
---|
2871 | } |
---|
2872 | else |
---|
2873 | { |
---|
2874 | current_style->flags = flags; |
---|
2875 | if (flags == GTK_FONT_BITMAP) |
---|
2876 | { |
---|
2877 | fontsel_info->pixel_sizes[npixel_sizes++] = pixels; |
---|
2878 | current_style->npixel_sizes = 1; |
---|
2879 | fontsel_info->point_sizes[npoint_sizes++] = points; |
---|
2880 | current_style->npoint_sizes = 1; |
---|
2881 | } |
---|
2882 | style++; |
---|
2883 | fontsel_info->nstyles++; |
---|
2884 | current_style++; |
---|
2885 | } |
---|
2886 | } |
---|
2887 | g_slist_free(fontnames[i]); |
---|
2888 | |
---|
2889 | /* Set nstyles to the real value, minus duplicated fontnames. |
---|
2890 | Note that we aren't using all the allocated memory if fontnames are |
---|
2891 | duplicated. */ |
---|
2892 | font->nstyles = style; |
---|
2893 | } |
---|
2894 | |
---|
2895 | /* Since some repeated styles may be skipped we won't have used all the |
---|
2896 | allocated space, so we will now reallocate it with the real size. */ |
---|
2897 | fontsel_info->font_styles = g_realloc(fontsel_info->font_styles, |
---|
2898 | sizeof(FontStyle) * fontsel_info->nstyles); |
---|
2899 | fontsel_info->pixel_sizes = g_realloc(fontsel_info->pixel_sizes, |
---|
2900 | sizeof(guint16) * npixel_sizes); |
---|
2901 | fontsel_info->point_sizes = g_realloc(fontsel_info->point_sizes, |
---|
2902 | sizeof(guint16) * npoint_sizes); |
---|
2903 | g_free(fontnames); |
---|
2904 | XFreeFontNames (xfontnames); |
---|
2905 | |
---|
2906 | |
---|
2907 | /* Debugging Output */ |
---|
2908 | /* This outputs all FontInfos. */ |
---|
2909 | #ifdef FONTSEL_DEBUG |
---|
2910 | g_message("\n\n Font Family Weight Slant Set Width Spacing Charset\n\n"); |
---|
2911 | for (i = 0; i < fontsel_info->nfonts; i++) |
---|
2912 | { |
---|
2913 | FontInfo *font = &fontsel_info->font_info[i]; |
---|
2914 | FontStyle *styles = fontsel_info->font_styles + font->style_index; |
---|
2915 | for (style = 0; style < font->nstyles; style++) |
---|
2916 | { |
---|
2917 | g_message("%5i %-16.16s ", i, font->family); |
---|
2918 | for (prop = 0; prop < GTK_NUM_STYLE_PROPERTIES; prop++) |
---|
2919 | g_message("%-9.9s ", |
---|
2920 | fontsel_info->properties[prop][styles->properties[prop]]); |
---|
2921 | g_message("\n "); |
---|
2922 | |
---|
2923 | if (styles->flags & GTK_FONT_BITMAP) |
---|
2924 | g_message("Bitmapped font "); |
---|
2925 | if (styles->flags & GTK_FONT_SCALABLE) |
---|
2926 | g_message("Scalable font "); |
---|
2927 | if (styles->flags & GTK_FONT_SCALABLE_BITMAP) |
---|
2928 | g_message("Scalable-Bitmapped font "); |
---|
2929 | g_message("\n"); |
---|
2930 | |
---|
2931 | if (styles->npixel_sizes) |
---|
2932 | { |
---|
2933 | g_message(" Pixel sizes: "); |
---|
2934 | tmp_sizes = fontsel_info->pixel_sizes + styles->pixel_sizes_index; |
---|
2935 | for (size = 0; size < styles->npixel_sizes; size++) |
---|
2936 | g_message("%i ", *tmp_sizes++); |
---|
2937 | g_message("\n"); |
---|
2938 | } |
---|
2939 | |
---|
2940 | if (styles->npoint_sizes) |
---|
2941 | { |
---|
2942 | g_message(" Point sizes: "); |
---|
2943 | tmp_sizes = fontsel_info->point_sizes + styles->point_sizes_index; |
---|
2944 | for (size = 0; size < styles->npoint_sizes; size++) |
---|
2945 | g_message("%i ", *tmp_sizes++); |
---|
2946 | g_message("\n"); |
---|
2947 | } |
---|
2948 | |
---|
2949 | g_message("\n"); |
---|
2950 | styles++; |
---|
2951 | } |
---|
2952 | } |
---|
2953 | /* This outputs all available properties. */ |
---|
2954 | for (prop = 0; prop < GTK_NUM_FONT_PROPERTIES; prop++) |
---|
2955 | { |
---|
2956 | g_message("Property: %s\n", xlfd_field_names[xlfd_index[prop]]); |
---|
2957 | for (i = 0; i < fontsel_info->nproperties[prop]; i++) |
---|
2958 | g_message(" %s\n", fontsel_info->properties[prop][i]); |
---|
2959 | } |
---|
2960 | #endif |
---|
2961 | } |
---|
2962 | |
---|
2963 | /* This inserts the given fontname into the FontInfo table. |
---|
2964 | If a FontInfo already exists with the same family and foundry, then the |
---|
2965 | fontname is added to the FontInfos list of fontnames, else a new FontInfo |
---|
2966 | is created and inserted in alphabetical order in the table. */ |
---|
2967 | static void |
---|
2968 | gtk_font_selection_insert_font (GSList *fontnames[], |
---|
2969 | gint *ntable, |
---|
2970 | gchar *fontname) |
---|
2971 | { |
---|
2972 | FontInfo *table; |
---|
2973 | FontInfo temp_info; |
---|
2974 | GSList *temp_fontname; |
---|
2975 | gchar *family; |
---|
2976 | gboolean family_exists = FALSE; |
---|
2977 | gint foundry; |
---|
2978 | gint lower, upper; |
---|
2979 | gint middle, cmp; |
---|
2980 | gchar family_buffer[XLFD_MAX_FIELD_LEN]; |
---|
2981 | |
---|
2982 | table = fontsel_info->font_info; |
---|
2983 | |
---|
2984 | /* insert a fontname into a table */ |
---|
2985 | family = gtk_font_selection_get_xlfd_field (fontname, XLFD_FAMILY, |
---|
2986 | family_buffer); |
---|
2987 | if (!family) |
---|
2988 | return; |
---|
2989 | |
---|
2990 | foundry = gtk_font_selection_insert_field (fontname, FOUNDRY); |
---|
2991 | |
---|
2992 | lower = 0; |
---|
2993 | if (*ntable > 0) |
---|
2994 | { |
---|
2995 | /* Do a binary search to determine if we have already encountered |
---|
2996 | * a font with this family & foundry. */ |
---|
2997 | upper = *ntable; |
---|
2998 | while (lower < upper) |
---|
2999 | { |
---|
3000 | middle = (lower + upper) >> 1; |
---|
3001 | |
---|
3002 | cmp = strcmp (family, table[middle].family); |
---|
3003 | /* If the family matches we sort by the foundry. */ |
---|
3004 | if (cmp == 0) |
---|
3005 | { |
---|
3006 | family_exists = TRUE; |
---|
3007 | family = table[middle].family; |
---|
3008 | cmp = strcmp(fontsel_info->properties[FOUNDRY][foundry], |
---|
3009 | fontsel_info->properties[FOUNDRY][table[middle].foundry]); |
---|
3010 | } |
---|
3011 | |
---|
3012 | if (cmp == 0) |
---|
3013 | { |
---|
3014 | fontnames[middle] = g_slist_prepend (fontnames[middle], |
---|
3015 | fontname); |
---|
3016 | return; |
---|
3017 | } |
---|
3018 | else if (cmp < 0) |
---|
3019 | upper = middle; |
---|
3020 | else |
---|
3021 | lower = middle+1; |
---|
3022 | } |
---|
3023 | } |
---|
3024 | |
---|
3025 | /* Add another entry to the table for this new font family */ |
---|
3026 | temp_info.family = family_exists ? family : g_strdup(family); |
---|
3027 | temp_info.foundry = foundry; |
---|
3028 | temp_fontname = g_slist_prepend (NULL, fontname); |
---|
3029 | |
---|
3030 | (*ntable)++; |
---|
3031 | |
---|
3032 | /* Quickly insert the entry into the table in sorted order |
---|
3033 | * using a modification of insertion sort and the knowledge |
---|
3034 | * that the entries proper position in the table was determined |
---|
3035 | * above in the binary search and is contained in the "lower" |
---|
3036 | * variable. */ |
---|
3037 | if (*ntable > 1) |
---|
3038 | { |
---|
3039 | upper = *ntable - 1; |
---|
3040 | while (lower != upper) |
---|
3041 | { |
---|
3042 | table[upper] = table[upper-1]; |
---|
3043 | fontnames[upper] = fontnames[upper-1]; |
---|
3044 | upper--; |
---|
3045 | } |
---|
3046 | } |
---|
3047 | table[lower] = temp_info; |
---|
3048 | fontnames[lower] = temp_fontname; |
---|
3049 | } |
---|
3050 | |
---|
3051 | |
---|
3052 | /* This checks that the specified field of the given fontname is in the |
---|
3053 | appropriate properties array. If not it is added. Thus eventually we get |
---|
3054 | arrays of all possible weights/slants etc. It returns the array index. */ |
---|
3055 | static gint |
---|
3056 | gtk_font_selection_insert_field (gchar *fontname, |
---|
3057 | gint prop) |
---|
3058 | { |
---|
3059 | gchar field_buffer[XLFD_MAX_FIELD_LEN]; |
---|
3060 | gchar *field; |
---|
3061 | guint16 index; |
---|
3062 | |
---|
3063 | field = gtk_font_selection_get_xlfd_field (fontname, xlfd_index[prop], |
---|
3064 | field_buffer); |
---|
3065 | if (!field) |
---|
3066 | return 0; |
---|
3067 | |
---|
3068 | /* If the field is already in the array just return its index. */ |
---|
3069 | for (index = 0; index < fontsel_info->nproperties[prop]; index++) |
---|
3070 | if (!strcmp(field, fontsel_info->properties[prop][index])) |
---|
3071 | return index; |
---|
3072 | |
---|
3073 | /* Make sure we have enough space to add the field. */ |
---|
3074 | if (fontsel_info->nproperties[prop] == fontsel_info->space_allocated[prop]) |
---|
3075 | { |
---|
3076 | fontsel_info->space_allocated[prop] += PROPERTY_ARRAY_INCREMENT; |
---|
3077 | fontsel_info->properties[prop] = g_realloc(fontsel_info->properties[prop], |
---|
3078 | sizeof(gchar*) |
---|
3079 | * fontsel_info->space_allocated[prop]); |
---|
3080 | } |
---|
3081 | |
---|
3082 | /* Add the new field. */ |
---|
3083 | index = fontsel_info->nproperties[prop]; |
---|
3084 | fontsel_info->properties[prop][index] = g_strdup(field); |
---|
3085 | fontsel_info->nproperties[prop]++; |
---|
3086 | return index; |
---|
3087 | } |
---|
3088 | |
---|
3089 | |
---|
3090 | /***************************************************************************** |
---|
3091 | * These functions are the main public interface for getting/setting the font. |
---|
3092 | *****************************************************************************/ |
---|
3093 | |
---|
3094 | GdkFont* |
---|
3095 | gtk_font_selection_get_font (GtkFontSelection *fontsel) |
---|
3096 | { |
---|
3097 | g_return_val_if_fail (GTK_IS_FONT_SELECTION (fontsel), NULL); |
---|
3098 | |
---|
3099 | gtk_font_selection_update_size (fontsel); |
---|
3100 | |
---|
3101 | return fontsel->font; |
---|
3102 | } |
---|
3103 | |
---|
3104 | |
---|
3105 | gchar * |
---|
3106 | gtk_font_selection_get_font_name (GtkFontSelection *fontsel) |
---|
3107 | { |
---|
3108 | FontInfo *font; |
---|
3109 | gchar *family_str, *foundry_str; |
---|
3110 | gchar *property_str[GTK_NUM_STYLE_PROPERTIES]; |
---|
3111 | gint prop; |
---|
3112 | |
---|
3113 | g_return_val_if_fail (fontsel != NULL, NULL); |
---|
3114 | g_return_val_if_fail (GTK_IS_FONT_SELECTION (fontsel), NULL); |
---|
3115 | |
---|
3116 | gtk_font_selection_update_size (fontsel); |
---|
3117 | |
---|
3118 | /* If no family has been selected return NULL. */ |
---|
3119 | if (fontsel->font_index == -1) |
---|
3120 | return NULL; |
---|
3121 | |
---|
3122 | font = &fontsel_info->font_info[fontsel->font_index]; |
---|
3123 | family_str = font->family; |
---|
3124 | foundry_str = fontsel_info->properties[FOUNDRY][font->foundry]; |
---|
3125 | /* some fonts have a (nil) foundry */ |
---|
3126 | if (strcmp (foundry_str, "(nil)") == 0) |
---|
3127 | foundry_str = ""; |
---|
3128 | |
---|
3129 | for (prop = 0; prop < GTK_NUM_STYLE_PROPERTIES; prop++) |
---|
3130 | { |
---|
3131 | property_str[prop] = fontsel_info->properties[prop][fontsel->property_values[prop]]; |
---|
3132 | if (strcmp (property_str[prop], "(nil)") == 0) |
---|
3133 | property_str[prop] = ""; |
---|
3134 | } |
---|
3135 | |
---|
3136 | return gtk_font_selection_create_xlfd (fontsel->size, |
---|
3137 | fontsel->metric, |
---|
3138 | foundry_str, |
---|
3139 | family_str, |
---|
3140 | property_str[WEIGHT], |
---|
3141 | property_str[SLANT], |
---|
3142 | property_str[SET_WIDTH], |
---|
3143 | property_str[SPACING], |
---|
3144 | property_str[CHARSET]); |
---|
3145 | } |
---|
3146 | |
---|
3147 | |
---|
3148 | /* This sets the current font, selecting the appropriate clist rows. |
---|
3149 | First we check the fontname is valid and try to find the font family |
---|
3150 | - i.e. the name in the main list. If we can't find that, then just return. |
---|
3151 | Next we try to set each of the properties according to the fontname. |
---|
3152 | Finally we select the font family & style in the clists. */ |
---|
3153 | gboolean |
---|
3154 | gtk_font_selection_set_font_name (GtkFontSelection *fontsel, |
---|
3155 | const gchar *fontname) |
---|
3156 | { |
---|
3157 | gchar *family, *field; |
---|
3158 | gint index, prop, size, row; |
---|
3159 | guint16 foundry, value; |
---|
3160 | gchar family_buffer[XLFD_MAX_FIELD_LEN]; |
---|
3161 | gchar field_buffer[XLFD_MAX_FIELD_LEN]; |
---|
3162 | gchar buffer[16]; |
---|
3163 | |
---|
3164 | g_return_val_if_fail (fontsel != NULL, FALSE); |
---|
3165 | g_return_val_if_fail (GTK_IS_FONT_SELECTION (fontsel), FALSE); |
---|
3166 | g_return_val_if_fail (fontname != NULL, FALSE); |
---|
3167 | |
---|
3168 | /* Check it is a valid fontname. */ |
---|
3169 | if (!gtk_font_selection_is_xlfd_font_name(fontname)) |
---|
3170 | return FALSE; |
---|
3171 | |
---|
3172 | family = gtk_font_selection_get_xlfd_field (fontname, XLFD_FAMILY, |
---|
3173 | family_buffer); |
---|
3174 | if (!family) |
---|
3175 | return FALSE; |
---|
3176 | |
---|
3177 | field = gtk_font_selection_get_xlfd_field (fontname, XLFD_FOUNDRY, |
---|
3178 | field_buffer); |
---|
3179 | foundry = gtk_font_selection_field_to_index (fontsel_info->properties[FOUNDRY], |
---|
3180 | fontsel_info->nproperties[FOUNDRY], |
---|
3181 | field); |
---|
3182 | |
---|
3183 | index = gtk_font_selection_find_font(fontsel, family, foundry); |
---|
3184 | if (index == -1) |
---|
3185 | return FALSE; |
---|
3186 | |
---|
3187 | /* Convert the property fields into indices and set them. */ |
---|
3188 | for (prop = 0; prop < GTK_NUM_STYLE_PROPERTIES; prop++) |
---|
3189 | { |
---|
3190 | field = gtk_font_selection_get_xlfd_field (fontname, xlfd_index[prop], |
---|
3191 | field_buffer); |
---|
3192 | value = gtk_font_selection_field_to_index (fontsel_info->properties[prop], |
---|
3193 | fontsel_info->nproperties[prop], |
---|
3194 | field); |
---|
3195 | fontsel->property_values[prop] = value; |
---|
3196 | } |
---|
3197 | |
---|
3198 | field = gtk_font_selection_get_xlfd_field (fontname, XLFD_POINTS, |
---|
3199 | field_buffer); |
---|
3200 | size = atoi(field); |
---|
3201 | if (size > 0) |
---|
3202 | { |
---|
3203 | if (size < 20) |
---|
3204 | size = 20; |
---|
3205 | fontsel->size = fontsel->selected_size = size; |
---|
3206 | fontsel->metric = GTK_FONT_METRIC_POINTS; |
---|
3207 | gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(fontsel->points_button), |
---|
3208 | TRUE); |
---|
3209 | if (size % 10 == 0) |
---|
3210 | sprintf (buffer, "%i", size / 10); |
---|
3211 | else |
---|
3212 | sprintf (buffer, "%i.%i", size / 10, size % 10); |
---|
3213 | } |
---|
3214 | else |
---|
3215 | { |
---|
3216 | field = gtk_font_selection_get_xlfd_field (fontname, XLFD_PIXELS, |
---|
3217 | field_buffer); |
---|
3218 | size = atoi(field); |
---|
3219 | if (size < 2) |
---|
3220 | size = 2; |
---|
3221 | fontsel->size = fontsel->selected_size = size; |
---|
3222 | fontsel->metric = GTK_FONT_METRIC_PIXELS; |
---|
3223 | gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(fontsel->pixels_button), |
---|
3224 | TRUE); |
---|
3225 | sprintf (buffer, "%i", size); |
---|
3226 | } |
---|
3227 | gtk_entry_set_text (GTK_ENTRY (fontsel->size_entry), buffer); |
---|
3228 | |
---|
3229 | /* Clear any current filter. */ |
---|
3230 | gtk_font_selection_clear_filter(fontsel); |
---|
3231 | |
---|
3232 | /* Now find the best style match. */ |
---|
3233 | fontsel->font_index = index; |
---|
3234 | row = gtk_clist_find_row_from_data (GTK_CLIST (fontsel->font_clist), |
---|
3235 | GINT_TO_POINTER (index)); |
---|
3236 | if (row != -1) |
---|
3237 | { |
---|
3238 | gtk_clist_select_row (GTK_CLIST (fontsel->font_clist), row, 0); |
---|
3239 | if (GTK_WIDGET_MAPPED (fontsel->font_clist)) |
---|
3240 | gtk_clist_moveto (GTK_CLIST (fontsel->font_clist), row, -1, 0.5, 0); |
---|
3241 | } |
---|
3242 | |
---|
3243 | gtk_font_selection_show_available_styles (fontsel); |
---|
3244 | /* This will load the font. */ |
---|
3245 | gtk_font_selection_select_best_style (fontsel, FALSE); |
---|
3246 | |
---|
3247 | return TRUE; |
---|
3248 | } |
---|
3249 | |
---|
3250 | |
---|
3251 | /* Returns the index of the given family, or -1 if not found */ |
---|
3252 | static gint |
---|
3253 | gtk_font_selection_find_font (GtkFontSelection *fontsel, |
---|
3254 | gchar *family, |
---|
3255 | guint16 foundry) |
---|
3256 | { |
---|
3257 | FontInfo *font_info; |
---|
3258 | gint lower, upper, middle = -1, cmp, nfonts; |
---|
3259 | gint found_family = -1; |
---|
3260 | |
---|
3261 | font_info = fontsel_info->font_info; |
---|
3262 | nfonts = fontsel_info->nfonts; |
---|
3263 | if (nfonts == 0) |
---|
3264 | return -1; |
---|
3265 | |
---|
3266 | /* Do a binary search to find the font family. */ |
---|
3267 | lower = 0; |
---|
3268 | upper = nfonts; |
---|
3269 | while (lower < upper) |
---|
3270 | { |
---|
3271 | middle = (lower + upper) >> 1; |
---|
3272 | |
---|
3273 | cmp = strcmp (family, font_info[middle].family); |
---|
3274 | if (cmp == 0) |
---|
3275 | { |
---|
3276 | found_family = middle; |
---|
3277 | cmp = strcmp(fontsel_info->properties[FOUNDRY][foundry], |
---|
3278 | fontsel_info->properties[FOUNDRY][font_info[middle].foundry]); |
---|
3279 | } |
---|
3280 | |
---|
3281 | if (cmp == 0) |
---|
3282 | return middle; |
---|
3283 | else if (cmp < 0) |
---|
3284 | upper = middle; |
---|
3285 | else if (cmp > 0) |
---|
3286 | lower = middle+1; |
---|
3287 | } |
---|
3288 | |
---|
3289 | /* We couldn't find the family and foundry, but we may have just found the |
---|
3290 | family, so we return that. */ |
---|
3291 | return found_family; |
---|
3292 | } |
---|
3293 | |
---|
3294 | |
---|
3295 | /* This returns the text in the preview entry. You should copy the returned |
---|
3296 | text if you need it. */ |
---|
3297 | gchar* |
---|
3298 | gtk_font_selection_get_preview_text (GtkFontSelection *fontsel) |
---|
3299 | { |
---|
3300 | return gtk_entry_get_text(GTK_ENTRY(fontsel->preview_entry)); |
---|
3301 | } |
---|
3302 | |
---|
3303 | |
---|
3304 | /* This sets the text in the preview entry. */ |
---|
3305 | void |
---|
3306 | gtk_font_selection_set_preview_text (GtkFontSelection *fontsel, |
---|
3307 | const gchar *text) |
---|
3308 | { |
---|
3309 | gtk_entry_set_text(GTK_ENTRY(fontsel->preview_entry), text); |
---|
3310 | } |
---|
3311 | |
---|
3312 | |
---|
3313 | /***************************************************************************** |
---|
3314 | * These functions all deal with X Logical Font Description (XLFD) fontnames. |
---|
3315 | * See the freely available documentation about this. |
---|
3316 | *****************************************************************************/ |
---|
3317 | |
---|
3318 | /* |
---|
3319 | * Returns TRUE if the fontname is a valid XLFD. |
---|
3320 | * (It just checks if the number of dashes is 14, and that each |
---|
3321 | * field < XLFD_MAX_FIELD_LEN characters long - that's not in the XLFD but it |
---|
3322 | * makes it easier for me). |
---|
3323 | */ |
---|
3324 | static gboolean |
---|
3325 | gtk_font_selection_is_xlfd_font_name (const gchar *fontname) |
---|
3326 | { |
---|
3327 | gint i = 0; |
---|
3328 | gint field_len = 0; |
---|
3329 | |
---|
3330 | while (*fontname) |
---|
3331 | { |
---|
3332 | if (*fontname++ == '-') |
---|
3333 | { |
---|
3334 | if (field_len > XLFD_MAX_FIELD_LEN) return FALSE; |
---|
3335 | field_len = 0; |
---|
3336 | i++; |
---|
3337 | } |
---|
3338 | else |
---|
3339 | field_len++; |
---|
3340 | } |
---|
3341 | |
---|
3342 | return (i == 14) ? TRUE : FALSE; |
---|
3343 | } |
---|
3344 | |
---|
3345 | /* |
---|
3346 | * This fills the buffer with the specified field from the X Logical Font |
---|
3347 | * Description name, and returns it. If fontname is NULL or the field is |
---|
3348 | * longer than XFLD_MAX_FIELD_LEN it returns NULL. |
---|
3349 | * Note: For the charset field, we also return the encoding, e.g. 'iso8859-1'. |
---|
3350 | */ |
---|
3351 | static gchar* |
---|
3352 | gtk_font_selection_get_xlfd_field (const gchar *fontname, |
---|
3353 | FontField field_num, |
---|
3354 | gchar *buffer) |
---|
3355 | { |
---|
3356 | const gchar *t1, *t2; |
---|
3357 | gint countdown, len, num_dashes; |
---|
3358 | |
---|
3359 | if (!fontname) |
---|
3360 | return NULL; |
---|
3361 | |
---|
3362 | /* we assume this is a valid fontname...that is, it has 14 fields */ |
---|
3363 | |
---|
3364 | countdown = field_num; |
---|
3365 | t1 = fontname; |
---|
3366 | while (*t1 && (countdown >= 0)) |
---|
3367 | if (*t1++ == '-') |
---|
3368 | countdown--; |
---|
3369 | |
---|
3370 | num_dashes = (field_num == XLFD_CHARSET) ? 2 : 1; |
---|
3371 | for (t2 = t1; *t2; t2++) |
---|
3372 | { |
---|
3373 | if (*t2 == '-' && --num_dashes == 0) |
---|
3374 | break; |
---|
3375 | } |
---|
3376 | |
---|
3377 | if (t1 != t2) |
---|
3378 | { |
---|
3379 | /* Check we don't overflow the buffer */ |
---|
3380 | len = (long) t2 - (long) t1; |
---|
3381 | if (len > XLFD_MAX_FIELD_LEN - 1) |
---|
3382 | return NULL; |
---|
3383 | strncpy (buffer, t1, len); |
---|
3384 | buffer[len] = 0; |
---|
3385 | |
---|
3386 | /* Convert to lower case. */ |
---|
3387 | g_strdown (buffer); |
---|
3388 | } |
---|
3389 | else |
---|
3390 | strcpy(buffer, "(nil)"); |
---|
3391 | |
---|
3392 | return buffer; |
---|
3393 | } |
---|
3394 | |
---|
3395 | /* |
---|
3396 | * This returns a X Logical Font Description font name, given all the pieces. |
---|
3397 | * Note: this retval must be freed by the caller. |
---|
3398 | */ |
---|
3399 | static gchar * |
---|
3400 | gtk_font_selection_create_xlfd (gint size, |
---|
3401 | GtkFontMetricType metric, |
---|
3402 | gchar *foundry, |
---|
3403 | gchar *family, |
---|
3404 | gchar *weight, |
---|
3405 | gchar *slant, |
---|
3406 | gchar *set_width, |
---|
3407 | gchar *spacing, |
---|
3408 | gchar *charset) |
---|
3409 | { |
---|
3410 | gchar buffer[16]; |
---|
3411 | gchar *pixel_size = "*", *point_size = "*", *fontname; |
---|
3412 | |
---|
3413 | if (size <= 0) |
---|
3414 | return NULL; |
---|
3415 | |
---|
3416 | sprintf (buffer, "%d", (int) size); |
---|
3417 | if (metric == GTK_FONT_METRIC_PIXELS) |
---|
3418 | pixel_size = buffer; |
---|
3419 | else |
---|
3420 | point_size = buffer; |
---|
3421 | |
---|
3422 | fontname = g_strdup_printf("-%s-%s-%s-%s-%s-*-%s-%s-*-*-%s-*-%s", |
---|
3423 | foundry, family, weight, slant, set_width, |
---|
3424 | pixel_size, point_size, spacing, charset); |
---|
3425 | return fontname; |
---|
3426 | } |
---|
3427 | |
---|
3428 | |
---|
3429 | |
---|
3430 | /***************************************************************************** |
---|
3431 | * GtkFontSelectionDialog |
---|
3432 | *****************************************************************************/ |
---|
3433 | |
---|
3434 | guint |
---|
3435 | gtk_font_selection_dialog_get_type (void) |
---|
3436 | { |
---|
3437 | static guint font_selection_dialog_type = 0; |
---|
3438 | |
---|
3439 | if (!font_selection_dialog_type) |
---|
3440 | { |
---|
3441 | GtkTypeInfo fontsel_diag_info = |
---|
3442 | { |
---|
3443 | "GtkFontSelectionDialog", |
---|
3444 | sizeof (GtkFontSelectionDialog), |
---|
3445 | sizeof (GtkFontSelectionDialogClass), |
---|
3446 | (GtkClassInitFunc) gtk_font_selection_dialog_class_init, |
---|
3447 | (GtkObjectInitFunc) gtk_font_selection_dialog_init, |
---|
3448 | /* reserved_1 */ NULL, |
---|
3449 | /* reserved_2 */ NULL, |
---|
3450 | (GtkClassInitFunc) NULL, |
---|
3451 | }; |
---|
3452 | |
---|
3453 | font_selection_dialog_type = gtk_type_unique (GTK_TYPE_WINDOW, &fontsel_diag_info); |
---|
3454 | } |
---|
3455 | |
---|
3456 | return font_selection_dialog_type; |
---|
3457 | } |
---|
3458 | |
---|
3459 | static void |
---|
3460 | gtk_font_selection_dialog_class_init (GtkFontSelectionDialogClass *klass) |
---|
3461 | { |
---|
3462 | GtkObjectClass *object_class; |
---|
3463 | |
---|
3464 | object_class = (GtkObjectClass*) klass; |
---|
3465 | |
---|
3466 | font_selection_dialog_parent_class = gtk_type_class (GTK_TYPE_WINDOW); |
---|
3467 | } |
---|
3468 | |
---|
3469 | static void |
---|
3470 | gtk_font_selection_dialog_init (GtkFontSelectionDialog *fontseldiag) |
---|
3471 | { |
---|
3472 | fontseldiag->dialog_width = -1; |
---|
3473 | fontseldiag->auto_resize = TRUE; |
---|
3474 | |
---|
3475 | gtk_widget_set_events(GTK_WIDGET(fontseldiag), GDK_STRUCTURE_MASK); |
---|
3476 | gtk_signal_connect (GTK_OBJECT (fontseldiag), "configure_event", |
---|
3477 | (GtkSignalFunc) gtk_font_selection_dialog_on_configure, |
---|
3478 | fontseldiag); |
---|
3479 | |
---|
3480 | gtk_container_set_border_width (GTK_CONTAINER (fontseldiag), 4); |
---|
3481 | gtk_window_set_policy(GTK_WINDOW(fontseldiag), FALSE, TRUE, TRUE); |
---|
3482 | |
---|
3483 | fontseldiag->main_vbox = gtk_vbox_new (FALSE, 4); |
---|
3484 | gtk_widget_show (fontseldiag->main_vbox); |
---|
3485 | gtk_container_add (GTK_CONTAINER (fontseldiag), fontseldiag->main_vbox); |
---|
3486 | |
---|
3487 | fontseldiag->fontsel = gtk_font_selection_new(); |
---|
3488 | gtk_widget_show (fontseldiag->fontsel); |
---|
3489 | gtk_box_pack_start (GTK_BOX (fontseldiag->main_vbox), |
---|
3490 | fontseldiag->fontsel, TRUE, TRUE, 0); |
---|
3491 | |
---|
3492 | /* Create the action area */ |
---|
3493 | fontseldiag->action_area = gtk_hbutton_box_new (); |
---|
3494 | gtk_button_box_set_layout(GTK_BUTTON_BOX(fontseldiag->action_area), |
---|
3495 | GTK_BUTTONBOX_END); |
---|
3496 | gtk_button_box_set_spacing(GTK_BUTTON_BOX(fontseldiag->action_area), 5); |
---|
3497 | gtk_box_pack_start (GTK_BOX (fontseldiag->main_vbox), |
---|
3498 | fontseldiag->action_area, FALSE, FALSE, 0); |
---|
3499 | gtk_widget_show (fontseldiag->action_area); |
---|
3500 | |
---|
3501 | fontseldiag->ok_button = gtk_button_new_with_label(_("OK")); |
---|
3502 | GTK_WIDGET_SET_FLAGS (fontseldiag->ok_button, GTK_CAN_DEFAULT); |
---|
3503 | gtk_widget_show(fontseldiag->ok_button); |
---|
3504 | gtk_box_pack_start (GTK_BOX (fontseldiag->action_area), |
---|
3505 | fontseldiag->ok_button, TRUE, TRUE, 0); |
---|
3506 | gtk_widget_grab_default (fontseldiag->ok_button); |
---|
3507 | |
---|
3508 | fontseldiag->apply_button = gtk_button_new_with_label(_("Apply")); |
---|
3509 | GTK_WIDGET_SET_FLAGS (fontseldiag->apply_button, GTK_CAN_DEFAULT); |
---|
3510 | /*gtk_widget_show(fontseldiag->apply_button);*/ |
---|
3511 | gtk_box_pack_start (GTK_BOX(fontseldiag->action_area), |
---|
3512 | fontseldiag->apply_button, TRUE, TRUE, 0); |
---|
3513 | |
---|
3514 | fontseldiag->cancel_button = gtk_button_new_with_label(_("Cancel")); |
---|
3515 | GTK_WIDGET_SET_FLAGS (fontseldiag->cancel_button, GTK_CAN_DEFAULT); |
---|
3516 | gtk_widget_show(fontseldiag->cancel_button); |
---|
3517 | gtk_box_pack_start (GTK_BOX(fontseldiag->action_area), |
---|
3518 | fontseldiag->cancel_button, TRUE, TRUE, 0); |
---|
3519 | |
---|
3520 | |
---|
3521 | } |
---|
3522 | |
---|
3523 | GtkWidget* |
---|
3524 | gtk_font_selection_dialog_new (const gchar *title) |
---|
3525 | { |
---|
3526 | GtkFontSelectionDialog *fontseldiag; |
---|
3527 | |
---|
3528 | fontseldiag = gtk_type_new (GTK_TYPE_FONT_SELECTION_DIALOG); |
---|
3529 | gtk_window_set_title (GTK_WINDOW (fontseldiag), |
---|
3530 | title ? title : _("Font Selection")); |
---|
3531 | |
---|
3532 | return GTK_WIDGET (fontseldiag); |
---|
3533 | } |
---|
3534 | |
---|
3535 | gchar* |
---|
3536 | gtk_font_selection_dialog_get_font_name (GtkFontSelectionDialog *fsd) |
---|
3537 | { |
---|
3538 | return gtk_font_selection_get_font_name(GTK_FONT_SELECTION(fsd->fontsel)); |
---|
3539 | } |
---|
3540 | |
---|
3541 | GdkFont* |
---|
3542 | gtk_font_selection_dialog_get_font (GtkFontSelectionDialog *fsd) |
---|
3543 | { |
---|
3544 | return gtk_font_selection_get_font(GTK_FONT_SELECTION(fsd->fontsel)); |
---|
3545 | } |
---|
3546 | |
---|
3547 | gboolean |
---|
3548 | gtk_font_selection_dialog_set_font_name (GtkFontSelectionDialog *fsd, |
---|
3549 | const gchar *fontname) |
---|
3550 | { |
---|
3551 | return gtk_font_selection_set_font_name(GTK_FONT_SELECTION(fsd->fontsel), |
---|
3552 | fontname); |
---|
3553 | } |
---|
3554 | |
---|
3555 | void |
---|
3556 | gtk_font_selection_dialog_set_filter (GtkFontSelectionDialog *fsd, |
---|
3557 | GtkFontFilterType filter_type, |
---|
3558 | GtkFontType font_type, |
---|
3559 | gchar **foundries, |
---|
3560 | gchar **weights, |
---|
3561 | gchar **slants, |
---|
3562 | gchar **setwidths, |
---|
3563 | gchar **spacings, |
---|
3564 | gchar **charsets) |
---|
3565 | { |
---|
3566 | gtk_font_selection_set_filter (GTK_FONT_SELECTION (fsd->fontsel), |
---|
3567 | filter_type, font_type, |
---|
3568 | foundries, weights, slants, setwidths, |
---|
3569 | spacings, charsets); |
---|
3570 | } |
---|
3571 | |
---|
3572 | gchar* |
---|
3573 | gtk_font_selection_dialog_get_preview_text (GtkFontSelectionDialog *fsd) |
---|
3574 | { |
---|
3575 | return gtk_font_selection_get_preview_text(GTK_FONT_SELECTION(fsd->fontsel)); |
---|
3576 | } |
---|
3577 | |
---|
3578 | void |
---|
3579 | gtk_font_selection_dialog_set_preview_text (GtkFontSelectionDialog *fsd, |
---|
3580 | const gchar *text) |
---|
3581 | { |
---|
3582 | gtk_font_selection_set_preview_text(GTK_FONT_SELECTION(fsd->fontsel), text); |
---|
3583 | } |
---|
3584 | |
---|
3585 | |
---|
3586 | /* This turns auto-shrink off if the user resizes the width of the dialog. |
---|
3587 | It also turns it back on again if the user resizes it back to its normal |
---|
3588 | width. */ |
---|
3589 | static gint |
---|
3590 | gtk_font_selection_dialog_on_configure (GtkWidget *widget, |
---|
3591 | GdkEventConfigure *event, |
---|
3592 | GtkFontSelectionDialog *fsd) |
---|
3593 | { |
---|
3594 | /* This sets the initial width. */ |
---|
3595 | if (fsd->dialog_width == -1) |
---|
3596 | fsd->dialog_width = event->width; |
---|
3597 | else if (fsd->auto_resize && fsd->dialog_width != event->width) |
---|
3598 | { |
---|
3599 | fsd->auto_resize = FALSE; |
---|
3600 | gtk_window_set_policy(GTK_WINDOW(fsd), FALSE, TRUE, FALSE); |
---|
3601 | } |
---|
3602 | else if (!fsd->auto_resize && fsd->dialog_width == event->width) |
---|
3603 | { |
---|
3604 | fsd->auto_resize = TRUE; |
---|
3605 | gtk_window_set_policy(GTK_WINDOW(fsd), FALSE, TRUE, TRUE); |
---|
3606 | } |
---|
3607 | |
---|
3608 | return FALSE; |
---|
3609 | } |
---|