mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-01-25 01:02:24 +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:
parent
f0b78b8869
commit
bb80007da4
209
unix/gtkfont.c
209
unix/gtkfont.c
@ -27,25 +27,30 @@
|
|||||||
* TODO on fontsel
|
* TODO on fontsel
|
||||||
* ---------------
|
* ---------------
|
||||||
*
|
*
|
||||||
* - implement the preview pane
|
* - preview pane fixes:
|
||||||
*
|
* + better centring of text? (Garuda is a particularly oddly
|
||||||
* - extend the font style language for X11 fonts so that we
|
* behaved font in this respect; are its metrics going weird
|
||||||
* never get unexplained double size elements? Or, at least, so
|
* for some reason?)
|
||||||
* that _my_ font collection never produces them; that'd be a
|
* + pick a better few lines of preview text. Should take care
|
||||||
* decent start.
|
* to use wide letters (MWmw) and narrow ones (ij).
|
||||||
*
|
* + resize to fit?
|
||||||
* - 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?
|
|
||||||
*
|
*
|
||||||
* - think about points versus pixels, harder than I already have
|
* - 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
|
* - work out why the list boxes don't go all the way to the RHS
|
||||||
* of the dialog box
|
* 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!
|
* - big testing and shakedown!
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -103,7 +108,8 @@ struct unifont_vtable {
|
|||||||
int bold, int cellwidth);
|
int bold, int cellwidth);
|
||||||
void (*enum_fonts)(GtkWidget *widget,
|
void (*enum_fonts)(GtkWidget *widget,
|
||||||
fontsel_add_entry callback, void *callback_ctx);
|
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);
|
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,
|
static void x11font_enum_fonts(GtkWidget *widget,
|
||||||
fontsel_add_entry callback, void *callback_ctx);
|
fontsel_add_entry callback, void *callback_ctx);
|
||||||
static char *x11font_canonify_fontname(GtkWidget *widget, const char *name,
|
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,
|
static char *x11font_scale_fontname(GtkWidget *widget, const char *name,
|
||||||
int size);
|
int size);
|
||||||
|
|
||||||
@ -593,14 +599,18 @@ static void x11font_enum_fonts(GtkWidget *widget,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static char *x11font_canonify_fontname(GtkWidget *widget, const char *name,
|
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
|
* 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
|
* font selector, we must attempt to load it (to see if it
|
||||||
* exists), and then canonify it by extracting its FONT
|
* exists), and then canonify it by extracting its FONT
|
||||||
* property, which should give its full XLFD even if what we
|
* 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);
|
GdkFont *font = gdk_font_load(name);
|
||||||
XFontStruct *xfs;
|
XFontStruct *xfs;
|
||||||
@ -618,15 +628,16 @@ static char *x11font_canonify_fontname(GtkWidget *widget, const char *name,
|
|||||||
fontprop = XInternAtom(disp, "FONT", False);
|
fontprop = XInternAtom(disp, "FONT", False);
|
||||||
|
|
||||||
if (XGetFontProperty(xfs, fontprop, &ret)) {
|
if (XGetFontProperty(xfs, fontprop, &ret)) {
|
||||||
char *name = XGetAtomName(disp, (Atom)ret);
|
char *newname = XGetAtomName(disp, (Atom)ret);
|
||||||
if (name) {
|
if (newname) {
|
||||||
unsigned long fsize = 12;
|
unsigned long fsize = 12;
|
||||||
|
|
||||||
fontprop2 = XInternAtom(disp, "PIXEL_SIZE", False);
|
fontprop2 = XInternAtom(disp, "PIXEL_SIZE", False);
|
||||||
if (XGetFontProperty(xfs, fontprop2, &fsize)) {
|
if (XGetFontProperty(xfs, fontprop2, &fsize) && fsize > 0) {
|
||||||
*size = fsize;
|
*size = fsize;
|
||||||
gdk_font_unref(font);
|
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,
|
static void pangofont_enum_fonts(GtkWidget *widget, fontsel_add_entry callback,
|
||||||
void *callback_ctx);
|
void *callback_ctx);
|
||||||
static char *pangofont_canonify_fontname(GtkWidget *widget, const char *name,
|
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,
|
static char *pangofont_scale_fontname(GtkWidget *widget, const char *name,
|
||||||
int size);
|
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,
|
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
|
* 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;
|
GtkListStore *family_model, *style_model, *size_model;
|
||||||
GtkWidget *family_list, *style_list, *size_entry, *size_list;
|
GtkWidget *family_list, *style_list, *size_entry, *size_list;
|
||||||
GtkWidget *filter_buttons[4];
|
GtkWidget *filter_buttons[4];
|
||||||
|
GtkWidget *preview_area;
|
||||||
|
GdkPixmap *preview_pixmap;
|
||||||
|
int preview_width, preview_height;
|
||||||
|
GdkColor preview_fg, preview_bg;
|
||||||
int filter_flags;
|
int filter_flags;
|
||||||
tree234 *fonts_by_realname, *fonts_by_selorder;
|
tree234 *fonts_by_realname, *fonts_by_selorder;
|
||||||
fontinfo *selected;
|
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_entry_set_editable(GTK_ENTRY(fs->size_entry), fs->selected->size == 0);
|
||||||
gtk_widget_set_sensitive(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;
|
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 *unifontsel_new(const char *wintitle)
|
||||||
{
|
{
|
||||||
unifontsel_internal *fs = snew(unifontsel_internal);
|
unifontsel_internal *fs = snew(unifontsel_internal);
|
||||||
GtkWidget *table, *label, *w, *scroll;
|
GtkWidget *table, *label, *w, *scroll;
|
||||||
GtkListStore *model;
|
GtkListStore *model;
|
||||||
GtkTreeViewColumn *column;
|
GtkTreeViewColumn *column;
|
||||||
int lists_height, font_width, style_width, size_width;
|
int lists_height, preview_height, font_width, style_width, size_width;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
fs->inhibit_response = FALSE;
|
fs->inhibit_response = FALSE;
|
||||||
@ -1735,6 +1868,7 @@ unifontsel *unifontsel_new(const char *wintitle)
|
|||||||
gtk_widget_size_request(label, &req);
|
gtk_widget_size_request(label, &req);
|
||||||
font_width = req.width;
|
font_width = req.width;
|
||||||
lists_height = 14 * req.height;
|
lists_height = 14 * req.height;
|
||||||
|
preview_height = 5 * req.height;
|
||||||
gtk_label_set_text(GTK_LABEL(label), "Italic Extra Condensed");
|
gtk_label_set_text(GTK_LABEL(label), "Italic Extra Condensed");
|
||||||
gtk_widget_size_request(label, &req);
|
gtk_widget_size_request(label, &req);
|
||||||
style_width = req.width;
|
style_width = req.width;
|
||||||
@ -1794,6 +1928,8 @@ unifontsel *unifontsel_new(const char *wintitle)
|
|||||||
gtk_tree_view_append_column(GTK_TREE_VIEW(w), column);
|
gtk_tree_view_append_column(GTK_TREE_VIEW(w), column);
|
||||||
g_signal_connect(G_OBJECT(gtk_tree_view_get_selection(GTK_TREE_VIEW(w))),
|
g_signal_connect(G_OBJECT(gtk_tree_view_get_selection(GTK_TREE_VIEW(w))),
|
||||||
"changed", G_CALLBACK(family_changed), fs);
|
"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);
|
scroll = gtk_scrolled_window_new(NULL, NULL);
|
||||||
gtk_container_add(GTK_CONTAINER(scroll), w);
|
gtk_container_add(GTK_CONTAINER(scroll), w);
|
||||||
@ -1879,6 +2015,26 @@ unifontsel *unifontsel_new(const char *wintitle)
|
|||||||
fs->size_model = model;
|
fs->size_model = model;
|
||||||
fs->size_list = w;
|
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
|
* FIXME: preview widget
|
||||||
*/
|
*/
|
||||||
@ -1945,6 +2101,9 @@ void unifontsel_destroy(unifontsel *fontsel)
|
|||||||
unifontsel_internal *fs = (unifontsel_internal *)fontsel;
|
unifontsel_internal *fs = (unifontsel_internal *)fontsel;
|
||||||
fontinfo *info;
|
fontinfo *info;
|
||||||
|
|
||||||
|
if (fs->preview_pixmap)
|
||||||
|
gdk_pixmap_unref(fs->preview_pixmap);
|
||||||
|
|
||||||
freetree234(fs->fonts_by_selorder);
|
freetree234(fs->fonts_by_selorder);
|
||||||
while ((info = delpos234(fs->fonts_by_realname, 0)) != NULL)
|
while ((info = delpos234(fs->fonts_by_realname, 0)) != NULL)
|
||||||
sfree(info);
|
sfree(info);
|
||||||
@ -1973,7 +2132,7 @@ void unifontsel_set_name(unifontsel *fontsel, const char *fontname)
|
|||||||
fontname = unifont_do_prefix(fontname, &start, &end);
|
fontname = unifont_do_prefix(fontname, &start, &end);
|
||||||
for (i = start; i < end; i++) {
|
for (i = start; i < end; i++) {
|
||||||
fontname2 = unifont_types[i]->canonify_fontname
|
fontname2 = unifont_types[i]->canonify_fontname
|
||||||
(GTK_WIDGET(fs->u.window), fontname, &size);
|
(GTK_WIDGET(fs->u.window), fontname, &size, FALSE);
|
||||||
if (fontname2)
|
if (fontname2)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user