1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-04-09 15:18:06 -05:00

When the user switches between fonts using the font family or style

selectors, preserve their most recent size selection as faithfully
as possible. We do this by having a secondary size variable
indicating what they _intend_, so we can come back to their intended
size even after going through a font which doesn't include it.

[originally from svn r7947]
This commit is contained in:
Simon Tatham 2008-03-29 10:16:48 +00:00
parent d173eb52ea
commit 6e6eae2506

View File

@ -27,20 +27,19 @@
* TODO on fontsel
* ---------------
*
* - add a third line of sample text containing digits and punct
*
* - 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.
*
* - think about points versus pixels, harder than I already have
*
* - work out why the list boxes don't go all the way to the RHS
* of the dialog box
*
* - 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)
*
* - 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!
*/
@ -1169,7 +1168,7 @@ typedef struct unifontsel_internal {
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;
@ -1445,7 +1444,7 @@ static void unifontsel_draw_preview_text(unifontsel_internal *fs)
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,
@ -1471,25 +1470,28 @@ static void unifontsel_draw_preview_text(unifontsel_internal *fs)
* 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;
@ -1500,6 +1502,8 @@ static void unifontsel_select_font(unifontsel_internal *fs,
fs->selected = info;
fs->selsize = size;
if (size_is_explicit)
fs->intendedsize = size;
/*
* Find the index of this fontinfo in the selorder list.
@ -1701,6 +1705,79 @@ static void unifontsel_add_entry(void *ctx, const char *realfontname,
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;
@ -1717,7 +1794,13 @@ static void family_changed(GtkTreeSelection *treeselection, gpointer 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)
@ -1738,7 +1821,13 @@ 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)
@ -1757,7 +1846,7 @@ 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)
@ -1774,7 +1863,7 @@ 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);
}
}
@ -1804,7 +1893,8 @@ static void alias_resolve(GtkTreeView *treeview, GtkTreePath *path,
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);
}
}
@ -2170,7 +2260,7 @@ void unifontsel_set_name(unifontsel *fontsel, const char *fontname)
* 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)