* TODO on fontsel
* ---------------
*
- * - think about points versus pixels, harder than I already have
+ * - add a third line of sample text containing digits and punct
*
- * - work out why the list boxes don't go all the way to the RHS
- * of the dialog box
+ * - start drawing X fonts one character at a time, at least if
+ * they're not fixed-width? Now we have that helpful pangram,
+ * we should make it work for everyone.
*
- * - consistency and updating issues:
- * + we should attempt to preserve font size when switching
- * font family and style (it's currently OK as long as we're
- * moving between scalable fonts but falls down badly
- * otherwise)
+ * - think about points versus pixels, harder than I already have
*
* - generalised style and padding polish
* + gtk_scrolled_window_set_shadow_type(foo, GTK_SHADOW_IN);
* might be worth considering
+ * + work out why the list boxes don't go all the way to the
+ * RHS of the dialog box
*
* - big testing and shakedown!
*/
int filter_flags;
tree234 *fonts_by_realname, *fonts_by_selorder;
fontinfo *selected;
- int selsize;
+ int selsize, intendedsize;
int inhibit_response; /* inhibit callbacks when we change GUI controls */
} unifontsel_internal;
font = info->fontclass->create(GTK_WIDGET(fs->u.window),
sizename ? sizename : info->realname,
FALSE, FALSE, 0, 0);
- if (font && fs->preview_pixmap) {
+ if (fs->preview_pixmap) {
GdkGC *gc = gdk_gc_new(fs->preview_pixmap);
gdk_gc_set_foreground(gc, &fs->preview_bg);
gdk_draw_rectangle(fs->preview_pixmap, gc, 1, 0, 0,
* effort of selecting their font and _then_ realise it
* was a mistake.
*/
- info->fontclass->draw_text(fs->preview_pixmap, gc, font,
- 0, font->ascent,
- "bankrupt jilted showmen quiz convex fogey",
- 41, FALSE, FALSE, font->width);
- info->fontclass->draw_text(fs->preview_pixmap, gc, font,
- 0, font->ascent + font->height,
- "BANKRUPT JILTED SHOWMEN QUIZ CONVEX FOGEY",
- 41, FALSE, FALSE, font->width);
+ if (font) {
+ info->fontclass->draw_text(fs->preview_pixmap, gc, font,
+ 0, font->ascent,
+ "bankrupt jilted showmen quiz convex fogey",
+ 41, FALSE, FALSE, font->width);
+ info->fontclass->draw_text(fs->preview_pixmap, gc, font,
+ 0, font->ascent + font->height,
+ "BANKRUPT JILTED SHOWMEN QUIZ CONVEX FOGEY",
+ 41, FALSE, FALSE, font->width);
+ }
gdk_gc_unref(gc);
gdk_window_invalidate_rect(fs->preview_area->window, NULL, FALSE);
}
-
- info->fontclass->destroy(font);
+ if (font)
+ info->fontclass->destroy(font);
sfree(sizename);
}
static void unifontsel_select_font(unifontsel_internal *fs,
- fontinfo *info, int size, int leftlist)
+ fontinfo *info, int size, int leftlist,
+ int size_is_explicit)
{
int index;
int minval, maxval;
fs->selected = info;
fs->selsize = size;
+ if (size_is_explicit)
+ fs->intendedsize = size;
/*
* Find the index of this fontinfo in the selorder list.
add234(fs->fonts_by_selorder, info);
}
+static fontinfo *update_for_intended_size(unifontsel_internal *fs,
+ fontinfo *info)
+{
+ fontinfo info2, *below, *above;
+ int pos;
+
+ /*
+ * Copy the info structure. This doesn't copy its dynamic
+ * string fields, but that's unimportant because all we're
+ * going to do is to adjust the size field and use it in one
+ * tree search.
+ */
+ info2 = *info;
+ info2.size = fs->intendedsize;
+
+ /*
+ * Search in the tree to find the fontinfo structure which
+ * best approximates the size the user last requested.
+ */
+ below = findrelpos234(fs->fonts_by_selorder, &info2, NULL,
+ REL234_LE, &pos);
+ above = index234(fs->fonts_by_selorder, pos+1);
+
+ /*
+ * See if we've found it exactly, which is an easy special
+ * case. If we have, it'll be in `below' and not `above',
+ * because we did a REL234_LE rather than REL234_LT search.
+ */
+ if (!fontinfo_selorder_compare(&info2, below))
+ return below;
+
+ /*
+ * Now we've either found two suitable fonts, one smaller and
+ * one larger, or we're at one or other extreme end of the
+ * scale. Find out which, by NULLing out either of below and
+ * above if it differs from this one in any respect but size
+ * (and the disambiguating index field). Bear in mind, also,
+ * that either one might _already_ be NULL if we're at the
+ * extreme ends of the font list.
+ */
+ if (below) {
+ info2.size = below->size;
+ info2.index = below->index;
+ if (fontinfo_selorder_compare(&info2, below))
+ below = NULL;
+ }
+ if (above) {
+ info2.size = above->size;
+ info2.index = above->index;
+ if (fontinfo_selorder_compare(&info2, above))
+ above = NULL;
+ }
+
+ /*
+ * Now return whichever of above and below is non-NULL, if
+ * that's unambiguous.
+ */
+ if (!above)
+ return below;
+ if (!below)
+ return above;
+
+ /*
+ * And now we really do have to make a choice about whether to
+ * round up or down. We'll do it by rounding to nearest,
+ * breaking ties by rounding up.
+ */
+ if (above->size - fs->intendedsize <= fs->intendedsize - below->size)
+ return above;
+ else
+ return below;
+}
+
static void family_changed(GtkTreeSelection *treeselection, gpointer data)
{
unifontsel_internal *fs = (unifontsel_internal *)data;
gtk_tree_model_get(treemodel, &treeiter, 1, &minval, -1);
info = (fontinfo *)index234(fs->fonts_by_selorder, minval);
- unifontsel_select_font(fs, info, info->size ? info->size : fs->selsize, 1);
+ info = update_for_intended_size(fs, info);
+ if (!info)
+ return; /* _shouldn't_ happen unless font list is completely funted */
+ if (!info->size)
+ fs->selsize = fs->intendedsize; /* font is scalable */
+ unifontsel_select_font(fs, info, info->size ? info->size : fs->selsize,
+ 1, FALSE);
}
static void style_changed(GtkTreeSelection *treeselection, gpointer data)
if (minval < 0)
return; /* somehow a charset heading got clicked */
info = (fontinfo *)index234(fs->fonts_by_selorder, minval);
- unifontsel_select_font(fs, info, info->size ? info->size : fs->selsize, 2);
+ info = update_for_intended_size(fs, info);
+ if (!info)
+ return; /* _shouldn't_ happen unless font list is completely funted */
+ if (!info->size)
+ fs->selsize = fs->intendedsize; /* font is scalable */
+ unifontsel_select_font(fs, info, info->size ? info->size : fs->selsize,
+ 2, FALSE);
}
static void size_changed(GtkTreeSelection *treeselection, gpointer data)
gtk_tree_model_get(treemodel, &treeiter, 1, &minval, 2, &size, -1);
info = (fontinfo *)index234(fs->fonts_by_selorder, minval);
- unifontsel_select_font(fs, info, info->size ? info->size : size, 3);
+ unifontsel_select_font(fs, info, info->size ? info->size : size, 3, TRUE);
}
static void size_entry_changed(GtkEditable *ed, gpointer data)
if (size > 0) {
assert(fs->selected->size == 0);
- unifontsel_select_font(fs, fs->selected, size, 3);
+ unifontsel_select_font(fs, fs->selected, size, 3, TRUE);
}
}
if (newinfo == info)
return; /* didn't change under canonification => not an alias */
unifontsel_select_font(fs, newinfo,
- newinfo->size ? newinfo->size : newsize, 1);
+ newinfo->size ? newinfo->size : newsize,
+ 1, TRUE);
}
}
* know everything we need to fill in all the fields in the
* dialog.
*/
- unifontsel_select_font(fs, info, size, 0);
+ unifontsel_select_font(fs, info, size, 0, TRUE);
}
char *unifontsel_get_name(unifontsel *fontsel)