1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-01-10 01:48:00 +00:00

More consistent handling of X11 font aliases: we now don't resolve

them automatically. If the user selects an alias in the font
selector, they get that alias copied literally into the output font
name string; when they return to the font selector, the alias is
still selected. We still _can_ resolve aliases, but we only do it on
demand: double-clicking one in the list box will do the job.

[originally from svn r7944]
This commit is contained in:
Simon Tatham 2008-03-27 19:41:08 +00:00
parent f0b78b8869
commit bb80007da4

View File

@ -27,25 +27,30 @@
* TODO on fontsel
* ---------------
*
* - implement the preview pane
*
* - extend the font style language for X11 fonts so that we
* never get unexplained double size elements? Or, at least, so
* that _my_ font collection never produces them; that'd be a
* decent start.
*
* - decide what _should_ happen about font aliases. Should we
* resolve them as soon as they're clicked? Or be able to
* resolve them on demand, er, somehow? Or resolve them on exit
* from the function? Or what? If we resolve on demand, should
* we stop canonifying them on input, on the basis that we'd
* prefer to let the user _tell_ us when to canonify them?
* - preview pane fixes:
* + better centring of text? (Garuda is a particularly oddly
* behaved font in this respect; are its metrics going weird
* for some reason?)
* + pick a better few lines of preview text. Should take care
* to use wide letters (MWmw) and narrow ones (ij).
* + resize to fit?
*
* - 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:
* + the preview pane is empty when the dialog comes up
* + 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
*
* - big testing and shakedown!
*/
@ -103,7 +108,8 @@ struct unifont_vtable {
int bold, int cellwidth);
void (*enum_fonts)(GtkWidget *widget,
fontsel_add_entry callback, void *callback_ctx);
char *(*canonify_fontname)(GtkWidget *widget, const char *name, int *size);
char *(*canonify_fontname)(GtkWidget *widget, const char *name, int *size,
int resolve_aliases);
char *(*scale_fontname)(GtkWidget *widget, const char *name, int size);
/*
@ -126,7 +132,7 @@ static void x11font_destroy(unifont *font);
static void x11font_enum_fonts(GtkWidget *widget,
fontsel_add_entry callback, void *callback_ctx);
static char *x11font_canonify_fontname(GtkWidget *widget, const char *name,
int *size);
int *size, int resolve_aliases);
static char *x11font_scale_fontname(GtkWidget *widget, const char *name,
int size);
@ -593,14 +599,18 @@ static void x11font_enum_fonts(GtkWidget *widget,
}
static char *x11font_canonify_fontname(GtkWidget *widget, const char *name,
int *size)
int *size, int resolve_aliases)
{
/*
* When given an X11 font name to try to make sense of for a
* font selector, we must attempt to load it (to see if it
* exists), and then canonify it by extracting its FONT
* property, which should give its full XLFD even if what we
* originally had was an alias.
* originally had was a wildcard.
*
* However, we must carefully avoid canonifying font
* _aliases_, unless specifically asked to, because the font
* selector treats them as worthwhile in their own right.
*/
GdkFont *font = gdk_font_load(name);
XFontStruct *xfs;
@ -618,15 +628,16 @@ static char *x11font_canonify_fontname(GtkWidget *widget, const char *name,
fontprop = XInternAtom(disp, "FONT", False);
if (XGetFontProperty(xfs, fontprop, &ret)) {
char *name = XGetAtomName(disp, (Atom)ret);
if (name) {
char *newname = XGetAtomName(disp, (Atom)ret);
if (newname) {
unsigned long fsize = 12;
fontprop2 = XInternAtom(disp, "PIXEL_SIZE", False);
if (XGetFontProperty(xfs, fontprop2, &fsize)) {
if (XGetFontProperty(xfs, fontprop2, &fsize) && fsize > 0) {
*size = fsize;
gdk_font_unref(font);
return dupstr(name);
return dupstr(name[0] == '-' || resolve_aliases ?
newname : name);
}
}
}
@ -655,7 +666,7 @@ static void pangofont_destroy(unifont *font);
static void pangofont_enum_fonts(GtkWidget *widget, fontsel_add_entry callback,
void *callback_ctx);
static char *pangofont_canonify_fontname(GtkWidget *widget, const char *name,
int *size);
int *size, int resolve_aliases);
static char *pangofont_scale_fontname(GtkWidget *widget, const char *name,
int size);
@ -978,7 +989,7 @@ static void pangofont_enum_fonts(GtkWidget *widget, fontsel_add_entry callback,
}
static char *pangofont_canonify_fontname(GtkWidget *widget, const char *name,
int *size)
int *size, int resolve_aliases)
{
/*
* When given a Pango font name to try to make sense of for a
@ -1160,6 +1171,10 @@ typedef struct unifontsel_internal {
GtkListStore *family_model, *style_model, *size_model;
GtkWidget *family_list, *style_list, *size_entry, *size_list;
GtkWidget *filter_buttons[4];
GtkWidget *preview_area;
GdkPixmap *preview_pixmap;
int preview_width, preview_height;
GdkColor preview_fg, preview_bg;
int filter_flags;
tree234 *fonts_by_realname, *fonts_by_selorder;
fontinfo *selected;
@ -1550,6 +1565,38 @@ static void unifontsel_select_font(unifontsel_internal *fs,
gtk_entry_set_editable(GTK_ENTRY(fs->size_entry), fs->selected->size == 0);
gtk_widget_set_sensitive(fs->size_entry, fs->selected->size == 0);
/*
* Instantiate the font and draw some preview text.
*/
{
unifont *font;
char *sizename;
sizename = info->fontclass->scale_fontname
(GTK_WIDGET(fs->u.window), info->realname, fs->selsize);
font = info->fontclass->create(GTK_WIDGET(fs->u.window),
sizename ? sizename : info->realname,
FALSE, FALSE, 0, 0);
if (font && 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,
fs->preview_width, fs->preview_height);
gdk_gc_set_foreground(gc, &fs->preview_fg);
info->fontclass->draw_text(fs->preview_pixmap, gc, font,
font->width, font->height,
"hello, world", 12,
FALSE, FALSE, font->width);
gdk_gc_unref(gc);
gdk_window_invalidate_rect(fs->preview_area->window, NULL, FALSE);
}
info->fontclass->destroy(font);
sfree(sizename);
}
fs->inhibit_response = FALSE;
}
@ -1715,13 +1762,99 @@ static void size_entry_changed(GtkEditable *ed, gpointer data)
}
}
static void alias_resolve(GtkTreeView *treeview, GtkTreePath *path,
GtkTreeViewColumn *column, gpointer data)
{
unifontsel_internal *fs = (unifontsel_internal *)data;
GtkTreeIter iter;
int minval, newsize;
fontinfo *info, *newinfo;
char *newname;
if (fs->inhibit_response) /* we made this change ourselves */
return;
gtk_tree_model_get_iter(GTK_TREE_MODEL(fs->family_model), &iter, path);
gtk_tree_model_get(GTK_TREE_MODEL(fs->family_model), &iter, 1,&minval, -1);
info = (fontinfo *)index234(fs->fonts_by_selorder, minval);
if (info) {
newname = info->fontclass->canonify_fontname
(GTK_WIDGET(fs->u.window), info->realname, &newsize, TRUE);
newinfo = find234(fs->fonts_by_realname, (char *)newname,
fontinfo_realname_find);
sfree(newname);
if (!newinfo)
return; /* font name not in our index */
if (newinfo == info)
return; /* didn't change under canonification => not an alias */
unifontsel_select_font(fs, newinfo,
newinfo->size ? newinfo->size : newsize, 1);
}
}
static gint unifontsel_expose_area(GtkWidget *widget, GdkEventExpose *event,
gpointer data)
{
unifontsel_internal *fs = (unifontsel_internal *)data;
if (fs->preview_pixmap) {
gdk_draw_pixmap(widget->window,
widget->style->fg_gc[GTK_WIDGET_STATE(widget)],
fs->preview_pixmap,
event->area.x, event->area.y,
event->area.x, event->area.y,
event->area.width, event->area.height);
}
return TRUE;
}
static gint unifontsel_configure_area(GtkWidget *widget,
GdkEventConfigure *event, gpointer data)
{
unifontsel_internal *fs = (unifontsel_internal *)data;
GdkGC *gc;
int ox, oy, nx, ny, x, y;
/*
* Enlarge the pixmap, but never shrink it.
*/
ox = fs->preview_width;
oy = fs->preview_height;
x = event->width;
y = event->height;
if (x > ox || y > oy) {
GdkPixmap *newpm;
nx = (x > ox ? x : ox);
ny = (y > oy ? y : oy);
newpm = gdk_pixmap_new(widget->window, nx, ny, -1);
gc = gdk_gc_new(newpm);
gdk_gc_set_foreground(gc, &fs->preview_bg);
gdk_draw_rectangle(newpm, gc, 1, 0, 0, nx, ny);
if (fs->preview_pixmap) {
gdk_draw_pixmap(newpm, gc, fs->preview_pixmap, 0, 0, 0, 0, ox, oy);
gdk_pixmap_unref(fs->preview_pixmap);
}
gdk_gc_unref(gc);
fs->preview_pixmap = newpm;
fs->preview_width = nx;
fs->preview_height = ny;
}
gdk_window_invalidate_rect(widget->window, NULL, FALSE);
return TRUE;
}
unifontsel *unifontsel_new(const char *wintitle)
{
unifontsel_internal *fs = snew(unifontsel_internal);
GtkWidget *table, *label, *w, *scroll;
GtkListStore *model;
GtkTreeViewColumn *column;
int lists_height, font_width, style_width, size_width;
int lists_height, preview_height, font_width, style_width, size_width;
int i;
fs->inhibit_response = FALSE;
@ -1735,6 +1868,7 @@ unifontsel *unifontsel_new(const char *wintitle)
gtk_widget_size_request(label, &req);
font_width = req.width;
lists_height = 14 * req.height;
preview_height = 5 * req.height;
gtk_label_set_text(GTK_LABEL(label), "Italic Extra Condensed");
gtk_widget_size_request(label, &req);
style_width = req.width;
@ -1794,6 +1928,8 @@ unifontsel *unifontsel_new(const char *wintitle)
gtk_tree_view_append_column(GTK_TREE_VIEW(w), column);
g_signal_connect(G_OBJECT(gtk_tree_view_get_selection(GTK_TREE_VIEW(w))),
"changed", G_CALLBACK(family_changed), fs);
g_signal_connect(G_OBJECT(w), "row-activated",
G_CALLBACK(alias_resolve), fs);
scroll = gtk_scrolled_window_new(NULL, NULL);
gtk_container_add(GTK_CONTAINER(scroll), w);
@ -1879,6 +2015,26 @@ unifontsel *unifontsel_new(const char *wintitle)
fs->size_model = model;
fs->size_list = w;
fs->preview_area = gtk_drawing_area_new();
fs->preview_pixmap = NULL;
fs->preview_width = 0;
fs->preview_height = 0;
fs->preview_fg.pixel = fs->preview_bg.pixel = 0;
fs->preview_fg.red = fs->preview_fg.green = fs->preview_fg.blue = 0x0000;
fs->preview_bg.red = fs->preview_bg.green = fs->preview_bg.blue = 0xFFFF;
gdk_colormap_alloc_color(gdk_colormap_get_system(), &fs->preview_fg,
FALSE, FALSE);
gdk_colormap_alloc_color(gdk_colormap_get_system(), &fs->preview_bg,
FALSE, FALSE);
gtk_signal_connect(GTK_OBJECT(fs->preview_area), "expose_event",
GTK_SIGNAL_FUNC(unifontsel_expose_area), fs);
gtk_signal_connect(GTK_OBJECT(fs->preview_area), "configure_event",
GTK_SIGNAL_FUNC(unifontsel_configure_area), fs);
gtk_widget_set_size_request(fs->preview_area, 1, preview_height);
gtk_widget_show(fs->preview_area);
gtk_table_attach(GTK_TABLE(table), fs->preview_area, 0, 3, 3, 4,
GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
/*
* FIXME: preview widget
*/
@ -1945,6 +2101,9 @@ void unifontsel_destroy(unifontsel *fontsel)
unifontsel_internal *fs = (unifontsel_internal *)fontsel;
fontinfo *info;
if (fs->preview_pixmap)
gdk_pixmap_unref(fs->preview_pixmap);
freetree234(fs->fonts_by_selorder);
while ((info = delpos234(fs->fonts_by_realname, 0)) != NULL)
sfree(info);
@ -1973,7 +2132,7 @@ void unifontsel_set_name(unifontsel *fontsel, const char *fontname)
fontname = unifont_do_prefix(fontname, &start, &end);
for (i = start; i < end; i++) {
fontname2 = unifont_types[i]->canonify_fontname
(GTK_WIDGET(fs->u.window), fontname, &size);
(GTK_WIDGET(fs->u.window), fontname, &size, FALSE);
if (fontname2)
break;
}