1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-01-09 09:27:59 +00:00

At last, merge the putty-gtk2 branch back into the trunk!

[originally from svn r8037]
This commit is contained in:
Simon Tatham 2008-06-04 23:05:48 +00:00
commit 865b6b404d
24 changed files with 3981 additions and 558 deletions

View File

@ -3,7 +3,7 @@ PuTTY is copyright 1997-2008 Simon Tatham.
Portions copyright Robert de Bath, Joris van Rantwijk, Delian
Delchev, Andreas Schultz, Jeroen Massar, Wez Furlong, Nicolas Barry,
Justin Bradford, Ben Harris, Malcolm Smith, Ahmad Khalifa, Markus
Kuhn, and CORE SDI S.A.
Kuhn, Colin Watson, and CORE SDI S.A.
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation files

2
Recipe
View File

@ -245,7 +245,7 @@ GUITERM = TERMINAL window windlg winctrls sizetip winucs winprint
# Same thing on Unix.
UXTERM = TERMINAL uxcfg sercfg uxucs uxprint timing
GTKTERM = UXTERM gtkwin gtkcfg gtkdlg gtkcols xkeysym
GTKTERM = UXTERM gtkwin gtkcfg gtkdlg gtkfont gtkcols xkeysym
OSXTERM = UXTERM osxwin osxdlg osxctrls
# Non-SSH back ends (putty, puttytel, plink).

View File

@ -1,4 +1,4 @@
/* $Id: macenc.c,v 1.2 2003/01/25 19:21:56 ben Exp $ */
/* $Id$ */
/*
* Copyright (c) 2003 Ben Harris
* All rights reserved.

View File

@ -209,6 +209,10 @@ union control {
* has a drop-down list built in. (Note that a _non_-
* editable drop-down list is done as a special case of a
* list box.)
*
* Don't try setting has_list and password on the same
* control; front ends are not required to support that
* combination.
*/
int has_list;
/*
@ -333,6 +337,11 @@ union control {
* the respective widths of `ncols' columns, which together
* will exactly fit the width of the list box. Otherwise
* `percentages' must be NULL.
*
* There should never be more than one column in a
* drop-down list (one with height==0), because front ends
* may have to implement it as a special case of an
* editable combo box.
*/
int ncols; /* number of columns */
int *percentages; /* % width of each column */

View File

@ -6,8 +6,8 @@ PuTTY is \i{copyright} 1997-2008 Simon Tatham.
Portions copyright Robert de Bath, Joris van Rantwijk, Delian
Delchev, Andreas Schultz, Jeroen Massar, Wez Furlong, Nicolas Barry,
Justin Bradford, Ben Harris, Malcolm Smith, Ahmad Khalifa, Markus Kuhn,
and CORE SDI S.A.
Justin Bradford, Ben Harris, Malcolm Smith, Ahmad Khalifa, Markus
Kuhn, Colin Watson, and CORE SDI S.A.
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation files

View File

@ -1247,7 +1247,7 @@ resource 'TEXT' (wLicence, "licence", purgeable) {
"Portions copyright Robert de Bath, Joris van Rantwijk, Delian "
"Delchev, Andreas Schultz, Jeroen Massar, Wez Furlong, Nicolas Barry, "
"Justin Bradford, Ben Harris, Malcolm Smith, Ahmad Khalifa, Markus "
"Kuhn, and CORE SDI S.A.\n"
"Kuhn, Colin Watson, and CORE SDI S.A.\n"
"\n"
"Permission is hereby granted, free of charge, to any person "
"obtaining a copy of this software and associated documentation "

View File

@ -1,4 +1,4 @@
/* $Id: macabout.c,v 1.3 2003/03/29 23:07:55 ben Exp $ */
/* $Id$ */
/*
* Copyright (c) 1999, 2002, 2003 Ben Harris
* All rights reserved.

View File

@ -1,4 +1,4 @@
/* $Id: macpgen.c,v 1.5 2003/02/23 13:31:12 ben Exp $ */
/* $Id$ */
/*
* Copyright (c) 1999, 2003 Ben Harris
* All rights reserved.

View File

@ -448,7 +448,7 @@ resource 'TEXT' (wLicence, "licence", purgeable) {
"Portions copyright Robert de Bath, Joris van Rantwijk, Delian "
"Delchev, Andreas Schultz, Jeroen Massar, Wez Furlong, Nicolas Barry, "
"Justin Bradford, Ben Harris, Malcolm Smith, Ahmad Khalifa, Markus "
"Kuhn, and CORE SDI S.A.\n"
"Kuhn, Colin Watson, and CORE SDI S.A.\n"
"\n"
"Permission is hereby granted, free of charge, to any person "
"obtaining a copy of this software and associated documentation "

View File

@ -1,4 +1,4 @@
/* $Id: macpgkey.c,v 1.5 2003/03/29 23:57:55 ben Exp $ */
/* $Id$ */
/*
* Copyright (c) 2003 Ben Harris
* Copyright (c) 1997-2003 Simon Tatham

View File

@ -1,4 +1,4 @@
/* $Id: macpgrid.h,v 1.4 2003/02/20 22:55:09 ben Exp $ */
/* $Id$ */
/*
* macpgrid.h -- Mac resource IDs for PuTTYgen

View File

@ -3,6 +3,10 @@
# It's separate from mkfiles.pl because it won't work (and isn't needed)
# on a non-Unix system.
# It's nice to be able to run this from inside the unix subdir as
# well as from outside.
test -f unix.h && cd ..
# Persuade automake to give us a copy of its install-sh. This is a
# pain because I don't actually want to have to _use_ automake.
# Instead, I construct a trivial unrelated automake project in a

View File

@ -924,12 +924,18 @@ if (defined $makefiles{'gtk'}) {
"# You can define this path to point at your tools if you need to\n".
"# TOOLPATH = /opt/gcc/bin\n".
"CC = \$(TOOLPATH)cc\n".
"# You can manually set this to `gtk-config' or `pkg-config gtk+-1.2'\n".
"# (depending on what works on your system) if you want to enforce\n".
"# building with GTK 1.2, or you can set it to `pkg-config gtk+-2.0'\n".
"# if you want to enforce 2.0. The default is to try 2.0 and fall back\n".
"# to 1.2 if it isn't found.\n".
"GTK_CONFIG = sh -c 'pkg-config gtk+-2.0 \$\$0 2>/dev/null || gtk-config \$\$0'\n".
"\n".
&splitline("CFLAGS = -O2 -Wall -Werror -g " .
(join " ", map {"-I$dirpfx$_"} @srcdirs) .
" `gtk-config --cflags`").
" `\$(GTK_CONFIG) --cflags`").
" -D _FILE_OFFSET_BITS=64\n".
"XLDFLAGS = \$(LDFLAGS) `gtk-config --libs`\n".
"XLDFLAGS = \$(LDFLAGS) `\$(GTK_CONFIG) --libs`\n".
"ULDFLAGS = \$(LDFLAGS)\n".
"INSTALL=install\n",
"INSTALL_PROGRAM=\$(INSTALL)\n",

View File

@ -18,7 +18,23 @@ AC_CHECK_HEADERS([utmpx.h sys/select.h],,,[
#include <sys/types.h>
#include <utmp.h>])
AM_PATH_GTK([1.2.0], [all_targets="all-cli all-gtk"], [all_targets="all-cli"])
# Look for both GTK 1 and GTK 2.
AM_PATH_GTK([1.2.0], [gtk=1], [gtk=none])
AM_PATH_GTK_2_0([2.0.0], [gtk=2], [])
if test "$gtk" = "none"; then
all_targets="all-cli"
else
all_targets="all-cli all-gtk"
fi
if test "$gtk" = "2"; then
ac_save_CFLAGS="$CFLAGS"
ac_save_LIBS="$LIBS"
CFLAGS="$CFLAGS $GTK_CFLAGS"
LIBS="$GTK_LIBS $LIBS"
AC_CHECK_FUNCS([pango_font_family_is_monospace pango_font_map_list_families])
CFLAGS="$ac_save_CFLAGS"
LIBS="$ac_save_LIBS"
fi
AC_SUBST([all_targets])
AC_SEARCH_LIBS([socket], [xnet])
@ -48,4 +64,10 @@ AH_BOTTOM([
#ifndef HAVE_SYS_SELECT_H
# define HAVE_NO_SYS_SELECT_H
#endif
#ifndef HAVE_PANGO_FONT_FAMILY_IS_MONOSPACE
# define PANGO_PRE_1POINT4
#endif
#ifndef HAVE_PANGO_FONT_MAP_LIST_FAMILIES
# define PANGO_PRE_1POINT6
#endif
])

View File

@ -3,24 +3,30 @@
*/
#include "gtkcols.h"
#include <gtk/gtk.h>
static void columns_init(Columns *cols);
static void columns_class_init(ColumnsClass *klass);
static void columns_map(GtkWidget *widget);
static void columns_unmap(GtkWidget *widget);
#if !GTK_CHECK_VERSION(2,0,0)
static void columns_draw(GtkWidget *widget, GdkRectangle *area);
static gint columns_expose(GtkWidget *widget, GdkEventExpose *event);
#endif
static void columns_base_add(GtkContainer *container, GtkWidget *widget);
static void columns_remove(GtkContainer *container, GtkWidget *widget);
static void columns_forall(GtkContainer *container, gboolean include_internals,
GtkCallback callback, gpointer callback_data);
#if !GTK_CHECK_VERSION(2,0,0)
static gint columns_focus(GtkContainer *container, GtkDirectionType dir);
#endif
static GtkType columns_child_type(GtkContainer *container);
static void columns_size_request(GtkWidget *widget, GtkRequisition *req);
static void columns_size_allocate(GtkWidget *widget, GtkAllocation *alloc);
static GtkContainerClass *parent_class = NULL;
#if !GTK_CHECK_VERSION(2,0,0)
GtkType columns_get_type(void)
{
static GtkType columns_type = 0;
@ -42,31 +48,61 @@ GtkType columns_get_type(void)
return columns_type;
}
#else
GType columns_get_type(void)
{
static GType columns_type = 0;
if (!columns_type) {
static const GTypeInfo columns_info = {
sizeof(ColumnsClass),
NULL,
NULL,
(GClassInitFunc) columns_class_init,
NULL,
NULL,
sizeof(Columns),
0,
(GInstanceInitFunc)columns_init,
};
columns_type = g_type_register_static(GTK_TYPE_CONTAINER, "Columns",
&columns_info, 0);
}
return columns_type;
}
#endif
#if !GTK_CHECK_VERSION(2,0,0)
static gint (*columns_inherited_focus)(GtkContainer *container,
GtkDirectionType direction);
#endif
static void columns_class_init(ColumnsClass *klass)
{
GtkObjectClass *object_class;
GtkWidgetClass *widget_class;
GtkContainerClass *container_class;
object_class = (GtkObjectClass *)klass;
widget_class = (GtkWidgetClass *)klass;
container_class = (GtkContainerClass *)klass;
#if !GTK_CHECK_VERSION(2,0,0)
/* GtkObjectClass *object_class = (GtkObjectClass *)klass; */
GtkWidgetClass *widget_class = (GtkWidgetClass *)klass;
GtkContainerClass *container_class = (GtkContainerClass *)klass;
#else
/* GObjectClass *object_class = G_OBJECT_CLASS(klass); */
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(klass);
GtkContainerClass *container_class = GTK_CONTAINER_CLASS(klass);
#endif
#if !GTK_CHECK_VERSION(2,0,0)
parent_class = gtk_type_class(GTK_TYPE_CONTAINER);
/*
* FIXME: do we have to do all this faffing with set_arg,
* get_arg and child_arg_type? Ick.
*/
#else
parent_class = g_type_class_peek_parent(klass);
#endif
widget_class->map = columns_map;
widget_class->unmap = columns_unmap;
#if !GTK_CHECK_VERSION(2,0,0)
widget_class->draw = columns_draw;
widget_class->expose_event = columns_expose;
#endif
widget_class->size_request = columns_size_request;
widget_class->size_allocate = columns_size_allocate;
@ -74,10 +110,12 @@ static void columns_class_init(ColumnsClass *klass)
container_class->remove = columns_remove;
container_class->forall = columns_forall;
container_class->child_type = columns_child_type;
#if !GTK_CHECK_VERSION(2,0,0)
/* Save the previous value of this method. */
if (!columns_inherited_focus)
columns_inherited_focus = container_class->focus;
container_class->focus = columns_focus;
#endif
}
static void columns_init(Columns *cols)
@ -135,6 +173,7 @@ static void columns_unmap(GtkWidget *widget)
gtk_widget_unmap(child->widget);
}
}
#if !GTK_CHECK_VERSION(2,0,0)
static void columns_draw(GtkWidget *widget, GdkRectangle *area)
{
Columns *cols;
@ -186,6 +225,7 @@ static gint columns_expose(GtkWidget *widget, GdkEventExpose *event)
}
return FALSE;
}
#endif
static void columns_base_add(GtkContainer *container, GtkWidget *widget)
{
@ -241,6 +281,9 @@ static void columns_remove(GtkContainer *container, GtkWidget *widget)
cols->taborder = g_list_remove_link(cols->taborder, children);
g_list_free(children);
#if GTK_CHECK_VERSION(2,0,0)
gtk_container_set_focus_chain(container, cols->taborder);
#endif
break;
}
}
@ -284,7 +327,12 @@ GtkWidget *columns_new(gint spacing)
{
Columns *cols;
#if !GTK_CHECK_VERSION(2,0,0)
cols = gtk_type_new(columns_get_type());
#else
cols = g_object_new(TYPE_COLUMNS, NULL);
#endif
cols->spacing = spacing;
return GTK_WIDGET(cols);
@ -332,6 +380,10 @@ void columns_add(Columns *cols, GtkWidget *child,
gtk_widget_set_parent(child, GTK_WIDGET(cols));
#if GTK_CHECK_VERSION(2,0,0)
gtk_container_set_focus_chain(GTK_CONTAINER(cols), cols->taborder);
#endif
if (GTK_WIDGET_REALIZED(cols))
gtk_widget_realize(child);
@ -382,10 +434,14 @@ void columns_taborder_last(Columns *cols, GtkWidget *widget)
cols->taborder = g_list_remove_link(cols->taborder, children);
g_list_free(children);
cols->taborder = g_list_append(cols->taborder, widget);
#if GTK_CHECK_VERSION(2,0,0)
gtk_container_set_focus_chain(GTK_CONTAINER(cols), cols->taborder);
#endif
break;
}
}
#if !GTK_CHECK_VERSION(2,0,0)
/*
* Override GtkContainer's focus movement so the user can
* explicitly specify the tab order.
@ -449,6 +505,7 @@ static gint columns_focus(GtkContainer *container, GtkDirectionType dir)
} else
return columns_inherited_focus(container, dir);
}
#endif
/*
* Now here comes the interesting bit. The actual layout part is

File diff suppressed because it is too large Load Diff

2520
unix/gtkfont.c Normal file

File diff suppressed because it is too large Load Diff

67
unix/gtkfont.h Normal file
View File

@ -0,0 +1,67 @@
/*
* Header file for gtkfont.c. Has to be separate from unix.h
* because it depends on GTK data types, hence can't be included
* from cross-platform code (which doesn't go near GTK).
*/
#ifndef PUTTY_GTKFONT_H
#define PUTTY_GTKFONT_H
/*
* Exports from gtkfont.c.
*/
struct unifont_vtable; /* contents internal to gtkfont.c */
typedef struct unifont {
const struct unifont_vtable *vt;
/*
* `Non-static data members' of the `class', accessible to
* external code.
*/
/*
* public_charset is the charset used when the user asks for
* `Use font encoding'.
*
* real_charset is the charset used when translating text into
* a form suitable for sending to unifont_draw_text().
*
* They can differ. For example, public_charset might be
* CS_ISO8859_1 while real_charset is CS_ISO8859_1_X11.
*/
int public_charset, real_charset;
/*
* Font dimensions needed by clients.
*/
int width, height, ascent, descent;
} unifont;
unifont *unifont_create(GtkWidget *widget, const char *name,
int wide, int bold,
int shadowoffset, int shadowalways);
void unifont_destroy(unifont *font);
void unifont_draw_text(GdkDrawable *target, GdkGC *gc, unifont *font,
int x, int y, const char *string, int len,
int wide, int bold, int cellwidth);
/*
* Unified font selector dialog. I can't be bothered to do a
* proper GTK subclassing today, so this will just be an ordinary
* data structure with some useful members.
*
* (Of course, these aren't the only members; this structure is
* contained within a bigger one which holds data visible only to
* the implementation.)
*/
typedef struct unifontsel {
void *user_data; /* settable by the user */
GtkWindow *window;
GtkWidget *ok_button, *cancel_button;
} unifontsel;
unifontsel *unifontsel_new(const char *wintitle);
void unifontsel_destroy(unifontsel *fontsel);
void unifontsel_set_name(unifontsel *fontsel, const char *fontname);
char *unifontsel_get_name(unifontsel *fontsel);
#endif /* PUTTY_GTKFONT_H */

View File

@ -28,6 +28,7 @@
#include "putty.h"
#include "terminal.h"
#include "gtkfont.h"
#define CAT2(x,y) x ## y
#define CAT(x,y) CAT2(x,y)
@ -58,11 +59,7 @@ struct gui_data {
*restartitem;
GtkWidget *sessionsmenu;
GdkPixmap *pixmap;
GdkFont *fonts[4]; /* normal, bold, wide, widebold */
struct {
int charset;
int is_wide;
} fontinfo[4];
unifont *fonts[4]; /* normal, bold, wide, widebold */
int xpos, ypos, gotpos, gravity;
GdkCursor *rawcursor, *textcursor, *blankcursor, *waitcursor, *currcursor;
GdkColor cols[NALLCOLOURS];
@ -137,7 +134,7 @@ FontSpec platform_default_fontspec(const char *name)
{
FontSpec ret;
if (!strcmp(name, "Font"))
strcpy(ret.name, "fixed");
strcpy(ret.name, "server:fixed");
else
*ret.name = '\0';
return ret;
@ -327,7 +324,7 @@ void set_zoomed(void *frontend, int zoomed)
*/
#if GTK_CHECK_VERSION(2,0,0)
struct gui_data *inst = (struct gui_data *)frontend;
if (iconic)
if (zoomed)
gtk_window_maximize(GTK_WINDOW(inst->window));
else
gtk_window_unmaximize(GTK_WINDOW(inst->window));
@ -1353,17 +1350,29 @@ void request_resize(void *frontend, int w, int h)
*/
#if GTK_CHECK_VERSION(2,0,0)
gtk_widget_set_size_request(inst->area, area_x, area_y);
#else
gtk_widget_set_usize(inst->area, area_x, area_y);
gtk_drawing_area_size(GTK_DRAWING_AREA(inst->area), area_x, area_y);
#endif
gtk_container_dequeue_resize_handler(GTK_CONTAINER(inst->window));
#if GTK_CHECK_VERSION(2,0,0)
gtk_window_resize(GTK_WINDOW(inst->window),
area_x + offset_x, area_y + offset_y);
#else
gtk_widget_set_usize(inst->area, area_x, area_y);
gtk_drawing_area_size(GTK_DRAWING_AREA(inst->area), area_x, area_y);
/*
* I can no longer remember what this call to
* gtk_container_dequeue_resize_handler is for. It was
* introduced in r3092 with no comment, and the commit log
* message was uninformative. I'm _guessing_ its purpose is to
* prevent gratuitous resize processing on the window given
* that we're about to resize it anyway, but I have no idea
* why that's so incredibly vital.
*
* I've tried removing the call, and nothing seems to go
* wrong. I've backtracked to r3092 and tried removing the
* call there, and still nothing goes wrong. So I'm going to
* adopt the working hypothesis that it's superfluous; I won't
* actually remove it from the GTK 1.2 code, but I won't
* attempt to replicate its functionality in the GTK 2 code
* above.
*/
gtk_container_dequeue_resize_handler(GTK_CONTAINER(inst->window));
gdk_window_resize(inst->window->window,
area_x + offset_x, area_y + offset_y);
#endif
@ -1462,7 +1471,7 @@ void palette_reset(void *frontend)
/* Since Default Background may have changed, ensure that space
* between text area and window border is refreshed. */
set_window_background(inst);
if (inst->area) {
if (inst->area && inst->area->window) {
draw_backing_rect(inst);
gtk_widget_queue_draw(inst->area);
}
@ -1884,6 +1893,8 @@ int char_width(Context ctx, int uc)
* Under X, any fixed-width font really _is_ fixed-width.
* Double-width characters will be dealt with using a separate
* font. For the moment we can simply return 1.
*
* FIXME: but is that also true of Pango?
*/
return 1;
}
@ -1924,7 +1935,7 @@ void do_text_internal(Context ctx, int x, int y, wchar_t *text, int len,
struct gui_data *inst = dctx->inst;
GdkGC *gc = dctx->gc;
int ncombining, combining;
int nfg, nbg, t, fontid, shadow, rlen, widefactor;
int nfg, nbg, t, fontid, shadow, rlen, widefactor, bold;
int monochrome = gtk_widget_get_visual(inst->area)->depth == 1;
if (attr & TATTR_COMBINING) {
@ -1963,10 +1974,27 @@ void do_text_internal(Context ctx, int x, int y, wchar_t *text, int len,
}
if ((attr & ATTR_BOLD) && !inst->cfg.bold_colour) {
if (inst->fonts[fontid | 1])
fontid |= 1;
else
shadow = 1;
bold = 1;
fontid |= 1;
} else {
bold = 0;
}
if (!inst->fonts[fontid]) {
int i;
/*
* Fall back through font ids with subsets of this one's
* set bits, in order.
*/
for (i = fontid; i-- > 0 ;) {
if (i & ~fontid)
continue; /* some other bit is set */
if (inst->fonts[i]) {
fontid = i;
break;
}
}
assert(inst->fonts[fontid]); /* we should at least have hit zero */
}
if ((lattr & LATTR_MODE) != LATTR_NORM) {
@ -1997,82 +2025,27 @@ void do_text_internal(Context ctx, int x, int y, wchar_t *text, int len,
gdk_gc_set_foreground(gc, &inst->cols[nfg]);
{
GdkWChar *gwcs;
gchar *gcs;
wchar_t *wcs;
int i;
wcs = snewn(len*ncombining+1, wchar_t);
for (i = 0; i < len*ncombining; i++) {
wcs[i] = text[i];
}
/*
* FIXME: this length is hardwired on the assumption that
* conversions from wide to multibyte characters will
* never generate more than 10 bytes for a single wide
* character.
*/
gcs = snewn(len*10+1, gchar);
if (inst->fonts[fontid] == NULL && (fontid & 2)) {
/*
* We've been given ATTR_WIDE, but have no wide font.
* Fall back to the non-wide font.
*/
fontid &= ~2;
}
if (inst->fonts[fontid] == NULL) {
/*
* The font for this contingency does not exist. So we
* display nothing at all; such is life.
*/
} else if (inst->fontinfo[fontid].is_wide) {
/*
* At least one version of gdk_draw_text_wc() has a
* weird bug whereby it reads `len' elements of the
* input string, but only draws `len/2'. Hence I'm
* going to make its input array twice as long as it
* theoretically needs to be, and pass in twice the
* actual number of characters. If a fixed gdk actually
* takes the doubled length seriously, then (a) the
* array will stand scrutiny up to the full length, (b)
* the spare elements of the array are full of zeroes
* which will probably be an empty glyph in the font,
* and (c) the clip rectangle should prevent it causing
* trouble anyway.
*/
gwcs = snewn(len*2+1, GdkWChar);
memset(gwcs, 0, sizeof(GdkWChar) * (len*2+1));
/*
* FIXME: when we have a wide-char equivalent of
* from_unicode, use it instead of this.
*/
for (combining = 0; combining < ncombining; combining++) {
for (i = 0; i <= len; i++)
gwcs[i] = wcs[i + combining];
gdk_draw_text_wc(inst->pixmap, inst->fonts[fontid], gc,
x*inst->font_width+inst->cfg.window_border,
y*inst->font_height+inst->cfg.window_border+inst->fonts[0]->ascent,
gwcs, len*2);
if (shadow)
gdk_draw_text_wc(inst->pixmap, inst->fonts[fontid], gc,
x*inst->font_width+inst->cfg.window_border+inst->cfg.shadowboldoffset,
y*inst->font_height+inst->cfg.window_border+inst->fonts[0]->ascent,
gwcs, len*2);
}
sfree(gwcs);
} else {
gcs = snewn(len+1, gchar);
for (combining = 0; combining < ncombining; combining++) {
wc_to_mb(inst->fontinfo[fontid].charset, 0,
wcs + combining, len, gcs, len, ".", NULL, NULL);
gdk_draw_text(inst->pixmap, inst->fonts[fontid], gc,
for (combining = 0; combining < ncombining; combining++) {
int mblen = wc_to_mb(inst->fonts[fontid]->real_charset, 0,
text + combining, len, gcs, len*10+1, ".",
NULL, NULL);
unifont_draw_text(inst->pixmap, gc, inst->fonts[fontid],
x*inst->font_width+inst->cfg.window_border,
y*inst->font_height+inst->cfg.window_border+inst->fonts[0]->ascent,
gcs, len);
if (shadow)
gdk_draw_text(inst->pixmap, inst->fonts[fontid], gc,
x*inst->font_width+inst->cfg.window_border+inst->cfg.shadowboldoffset,
y*inst->font_height+inst->cfg.window_border+inst->fonts[0]->ascent,
gcs, len);
}
sfree(gcs);
gcs, mblen, widefactor > 1, bold, inst->font_width);
}
sfree(wcs);
sfree(gcs);
}
if (attr & ATTR_UNDER) {
@ -2292,8 +2265,11 @@ GdkCursor *make_mouse_ptr(struct gui_data *inst, int cursor_val)
return NULL;
}
if (cursor_val >= 0 && !cursor_font)
if (cursor_val >= 0 && !cursor_font) {
cursor_font = gdk_font_load("cursor");
if (cursor_font)
gdk_font_ref(cursor_font);
}
/*
* Get the text extent of the cursor in question. We use the
@ -2634,75 +2610,12 @@ int do_cmdline(int argc, char **argv, int do_everything, int *allow_launch,
return err;
}
/*
* This function retrieves the character set encoding of a font. It
* returns the character set without the X11 hack (in case the user
* asks to use the font's own encoding).
*/
static int set_font_info(struct gui_data *inst, int fontid)
{
GdkFont *font = inst->fonts[fontid];
XFontStruct *xfs = GDK_FONT_XFONT(font);
Display *disp = GDK_FONT_XDISPLAY(font);
Atom charset_registry, charset_encoding;
unsigned long registry_ret, encoding_ret;
int retval = CS_NONE;
charset_registry = XInternAtom(disp, "CHARSET_REGISTRY", False);
charset_encoding = XInternAtom(disp, "CHARSET_ENCODING", False);
inst->fontinfo[fontid].charset = CS_NONE;
inst->fontinfo[fontid].is_wide = 0;
if (XGetFontProperty(xfs, charset_registry, &registry_ret) &&
XGetFontProperty(xfs, charset_encoding, &encoding_ret)) {
char *reg, *enc;
reg = XGetAtomName(disp, (Atom)registry_ret);
enc = XGetAtomName(disp, (Atom)encoding_ret);
if (reg && enc) {
char *encoding = dupcat(reg, "-", enc, NULL);
retval = inst->fontinfo[fontid].charset =
charset_from_xenc(encoding);
/* FIXME: when libcharset supports wide encodings fix this. */
if (!strcasecmp(encoding, "iso10646-1")) {
inst->fontinfo[fontid].is_wide = 1;
retval = CS_UTF8;
}
/*
* Hack for X line-drawing characters: if the primary
* font is encoded as ISO-8859-anything, and has valid
* glyphs in the first 32 char positions, it is assumed
* that those glyphs are the VT100 line-drawing
* character set.
*
* Actually, we'll hack even harder by only checking
* position 0x19 (vertical line, VT100 linedrawing
* `x'). Then we can check it easily by seeing if the
* ascent and descent differ.
*/
if (inst->fontinfo[fontid].charset == CS_ISO8859_1) {
int lb, rb, wid, asc, desc;
gchar text[2];
text[1] = '\0';
text[0] = '\x12';
gdk_string_extents(inst->fonts[fontid], text,
&lb, &rb, &wid, &asc, &desc);
if (asc != desc)
inst->fontinfo[fontid].charset = CS_ISO8859_1_X11;
}
sfree(encoding);
}
}
return retval;
}
int uxsel_input_add(int fd, int rwx) {
int flags = 0;
if (rwx & 1) flags |= GDK_INPUT_READ;
if (rwx & 2) flags |= GDK_INPUT_WRITE;
if (rwx & 4) flags |= GDK_INPUT_EXCEPTION;
assert(flags);
return gdk_input_add(fd, flags, fd_input_func, NULL);
}
@ -2710,158 +2623,75 @@ void uxsel_input_remove(int id) {
gdk_input_remove(id);
}
char *guess_derived_font_name(GdkFont *font, int bold, int wide)
{
XFontStruct *xfs = GDK_FONT_XFONT(font);
Display *disp = GDK_FONT_XDISPLAY(font);
Atom fontprop = XInternAtom(disp, "FONT", False);
unsigned long ret;
if (XGetFontProperty(xfs, fontprop, &ret)) {
char *name = XGetAtomName(disp, (Atom)ret);
if (name && name[0] == '-') {
char *strings[13];
char *dupname, *extrafree = NULL, *ret;
char *p, *q;
int nstr;
p = q = dupname = dupstr(name); /* skip initial minus */
nstr = 0;
while (*p && nstr < lenof(strings)) {
if (*p == '-') {
*p = '\0';
strings[nstr++] = p+1;
}
p++;
}
if (nstr < lenof(strings))
return NULL; /* XLFD was malformed */
if (bold)
strings[2] = "bold";
if (wide) {
/* 4 is `wideness', which obviously may have changed. */
/* 5 is additional style, which may be e.g. `ja' or `ko'. */
strings[4] = strings[5] = "*";
strings[11] = extrafree = dupprintf("%d", 2*atoi(strings[11]));
}
ret = dupcat("-", strings[ 0], "-", strings[ 1], "-", strings[ 2],
"-", strings[ 3], "-", strings[ 4], "-", strings[ 5],
"-", strings[ 6], "-", strings[ 7], "-", strings[ 8],
"-", strings[ 9], "-", strings[10], "-", strings[11],
"-", strings[12], NULL);
sfree(extrafree);
sfree(dupname);
return ret;
}
}
return NULL;
}
void setup_fonts_ucs(struct gui_data *inst)
{
int font_charset;
char *name;
int guessed;
if (inst->fonts[0])
gdk_font_unref(inst->fonts[0]);
unifont_destroy(inst->fonts[0]);
if (inst->fonts[1])
gdk_font_unref(inst->fonts[1]);
unifont_destroy(inst->fonts[1]);
if (inst->fonts[2])
gdk_font_unref(inst->fonts[2]);
unifont_destroy(inst->fonts[2]);
if (inst->fonts[3])
gdk_font_unref(inst->fonts[3]);
unifont_destroy(inst->fonts[3]);
inst->fonts[0] = gdk_font_load(inst->cfg.font.name);
inst->fonts[0] = unifont_create(inst->area, inst->cfg.font.name,
FALSE, FALSE,
inst->cfg.shadowboldoffset,
inst->cfg.shadowbold);
if (!inst->fonts[0]) {
fprintf(stderr, "%s: unable to load font \"%s\"\n", appname,
inst->cfg.font.name);
exit(1);
}
font_charset = set_font_info(inst, 0);
if (inst->cfg.shadowbold) {
if (inst->cfg.shadowbold || !inst->cfg.boldfont.name[0]) {
inst->fonts[1] = NULL;
} else {
if (inst->cfg.boldfont.name[0]) {
name = inst->cfg.boldfont.name;
guessed = FALSE;
} else {
name = guess_derived_font_name(inst->fonts[0], TRUE, FALSE);
guessed = TRUE;
}
inst->fonts[1] = name ? gdk_font_load(name) : NULL;
if (inst->fonts[1]) {
set_font_info(inst, 1);
} else if (!guessed) {
inst->fonts[1] = unifont_create(inst->area, inst->cfg.boldfont.name,
FALSE, TRUE,
inst->cfg.shadowboldoffset,
inst->cfg.shadowbold);
if (!inst->fonts[1]) {
fprintf(stderr, "%s: unable to load bold font \"%s\"\n", appname,
inst->cfg.boldfont.name);
exit(1);
}
if (guessed)
sfree(name);
}
if (inst->cfg.widefont.name[0]) {
name = inst->cfg.widefont.name;
guessed = FALSE;
} else {
name = guess_derived_font_name(inst->fonts[0], FALSE, TRUE);
guessed = TRUE;
}
inst->fonts[2] = name ? gdk_font_load(name) : NULL;
if (inst->fonts[2]) {
set_font_info(inst, 2);
} else if (!guessed) {
fprintf(stderr, "%s: unable to load wide font \"%s\"\n", appname,
inst->cfg.widefont.name);
exit(1);
}
if (guessed)
sfree(name);
if (inst->cfg.shadowbold) {
inst->fonts[3] = NULL;
} else {
if (inst->cfg.wideboldfont.name[0]) {
name = inst->cfg.wideboldfont.name;
guessed = FALSE;
} else {
/*
* Here we have some choices. We can widen the bold font,
* bolden the wide font, or widen and bolden the standard
* font. Try them all, in that order!
*/
if (inst->cfg.widefont.name[0])
name = guess_derived_font_name(inst->fonts[2], TRUE, FALSE);
else if (inst->cfg.boldfont.name[0])
name = guess_derived_font_name(inst->fonts[1], FALSE, TRUE);
else
name = guess_derived_font_name(inst->fonts[0], TRUE, TRUE);
guessed = TRUE;
}
inst->fonts[3] = name ? gdk_font_load(name) : NULL;
if (inst->fonts[3]) {
set_font_info(inst, 3);
} else if (!guessed) {
fprintf(stderr, "%s: unable to load wide/bold font \"%s\"\n", appname,
inst->cfg.wideboldfont.name);
inst->fonts[2] = unifont_create(inst->area, inst->cfg.widefont.name,
TRUE, FALSE,
inst->cfg.shadowboldoffset,
inst->cfg.shadowbold);
if (!inst->fonts[2]) {
fprintf(stderr, "%s: unable to load wide font \"%s\"\n", appname,
inst->cfg.widefont.name);
exit(1);
}
if (guessed)
sfree(name);
} else {
inst->fonts[2] = NULL;
}
inst->font_width = gdk_char_width(inst->fonts[0], ' ');
inst->font_height = inst->fonts[0]->ascent + inst->fonts[0]->descent;
if (inst->cfg.shadowbold || !inst->cfg.wideboldfont.name[0]) {
inst->fonts[3] = NULL;
} else {
inst->fonts[3] = unifont_create(inst->area,
inst->cfg.wideboldfont.name, TRUE,
TRUE, inst->cfg.shadowboldoffset,
inst->cfg.shadowbold);
if (!inst->fonts[3]) {
fprintf(stderr, "%s: unable to load wide bold font \"%s\"\n", appname,
inst->cfg.boldfont.name);
exit(1);
}
}
inst->font_width = inst->fonts[0]->width;
inst->font_height = inst->fonts[0]->height;
inst->direct_to_font = init_ucs(&inst->ucsdata, inst->cfg.line_codepage,
inst->cfg.utf8_override, font_charset,
inst->cfg.utf8_override,
inst->fonts[0]->public_charset,
inst->cfg.vtmode);
}
@ -3510,6 +3340,8 @@ int pt_main(int argc, char **argv)
if (!utf8_string_atom)
utf8_string_atom = gdk_atom_intern("UTF8_STRING", FALSE);
inst->area = gtk_drawing_area_new();
setup_fonts_ucs(inst);
init_cutbuffers();
@ -3523,7 +3355,6 @@ int pt_main(int argc, char **argv)
inst->width = inst->cfg.width;
inst->height = inst->cfg.height;
inst->area = gtk_drawing_area_new();
gtk_drawing_area_size(GTK_DRAWING_AREA(inst->area),
inst->font_width * inst->cfg.width + 2*inst->cfg.window_border,
inst->font_height * inst->cfg.height + 2*inst->cfg.window_border);

View File

@ -62,22 +62,18 @@ void uxsel_init(void)
void uxsel_set(int fd, int rwx, uxsel_callback_fn callback)
{
struct fd *newfd = snew(struct fd);
struct fd *oldfd;
struct fd *newfd;
newfd->fd = fd;
newfd->rwx = rwx;
newfd->callback = callback;
uxsel_del(fd);
oldfd = find234(fds, newfd, NULL);
if (oldfd) {
uxsel_input_remove(oldfd->id);
del234(fds, oldfd);
sfree(oldfd);
if (rwx) {
newfd = snew(struct fd);
newfd->fd = fd;
newfd->rwx = rwx;
newfd->callback = callback;
newfd->id = uxsel_input_add(fd, rwx);
add234(fds, newfd);
}
add234(fds, newfd);
newfd->id = uxsel_input_add(fd, rwx);
}
void uxsel_del(int fd)

View File

@ -362,7 +362,35 @@ int read_setting_i(void *handle, const char *key, int defvalue)
int read_setting_fontspec(void *handle, const char *name, FontSpec *result)
{
return !!read_setting_s(handle, name, result->name, sizeof(result->name));
/*
* In GTK1-only PuTTY, we used to store font names simply as a
* valid X font description string (logical or alias), under a
* bare key such as "Font".
*
* In GTK2 PuTTY, we have a prefix system where "client:"
* indicates a Pango font and "server:" an X one; existing
* configuration needs to be reinterpreted as having the
* "server:" prefix, so we change the storage key from the
* provided name string (e.g. "Font") to a suffixed one
* ("FontName").
*/
char *suffname = dupcat(name, "Name", NULL);
if (read_setting_s(handle, suffname, result->name, sizeof(result->name))) {
sfree(suffname);
return TRUE; /* got new-style name */
}
sfree(suffname);
/* Fall back to old-style name. */
memcpy(result->name, "server:", 7);
if (!read_setting_s(handle, name,
result->name + 7, sizeof(result->name) - 7) ||
!result->name[7]) {
result->name[0] = '\0';
return FALSE;
} else {
return TRUE;
}
}
int read_setting_filename(void *handle, const char *name, Filename *result)
{
@ -371,7 +399,14 @@ int read_setting_filename(void *handle, const char *name, Filename *result)
void write_setting_fontspec(void *handle, const char *name, FontSpec result)
{
write_setting_s(handle, name, result.name);
/*
* read_setting_fontspec had to handle two cases, but when
* writing our settings back out we simply always generate the
* new-style name.
*/
char *suffname = dupcat(name, "Name", NULL);
write_setting_s(handle, suffname, result.name);
sfree(suffname);
}
void write_setting_filename(void *handle, const char *name, Filename result)
{

View File

@ -62,7 +62,7 @@ BEGIN
LTEXT "Portions copyright Robert de Bath, Joris van Rantwijk, Delian", 1001, 10, 26, 206, 8
LTEXT "Delchev, Andreas Schultz, Jeroen Massar, Wez Furlong, Nicolas", 1002, 10, 34, 206, 8
LTEXT "Barry, Justin Bradford, Ben Harris, Malcolm Smith, Ahmad Khalifa,", 1003, 10, 42, 206, 8
LTEXT "Markus Kuhn, and CORE SDI S.A.", 1004, 10, 50, 206, 8
LTEXT "Markus Kuhn, Colin Watson, and CORE SDI S.A.", 1004, 10, 50, 206, 8
LTEXT "Permission is hereby granted, free of charge, to any person", 1005, 10, 66, 206, 8
LTEXT "obtaining a copy of this software and associated documentation", 1006, 10, 74, 206, 8

View File

@ -55,7 +55,7 @@ BEGIN
LTEXT "Portions copyright Robert de Bath, Joris van Rantwijk, Delian", 1001, 10, 26, 206, 8
LTEXT "Delchev, Andreas Schultz, Jeroen Massar, Wez Furlong, Nicolas", 1002, 10, 34, 206, 8
LTEXT "Barry, Justin Bradford, Ben Harris, Malcolm Smith, Ahmad Khalifa,", 1003, 10, 42, 206, 8
LTEXT "Markus Kuhn, and CORE SDI S.A.", 1004, 10, 50, 206, 8
LTEXT "Markus Kuhn, Colin Watson, and CORE SDI S.A.", 1004, 10, 50, 206, 8
LTEXT "Permission is hereby granted, free of charge, to any person", 1005, 10, 66, 206, 8
LTEXT "obtaining a copy of this software and associated documentation", 1006, 10, 74, 206, 8

View File

@ -63,7 +63,7 @@ BEGIN
LTEXT "Portions copyright Robert de Bath, Joris van Rantwijk, Delian", 1001, 10, 26, 206, 8
LTEXT "Delchev, Andreas Schultz, Jeroen Massar, Wez Furlong, Nicolas", 1002, 10, 34, 206, 8
LTEXT "Barry, Justin Bradford, Ben Harris, Malcolm Smith, Ahmad Khalifa,", 1003, 10, 42, 206, 8
LTEXT "Markus Kuhn, and CORE SDI S.A.", 1004, 10, 50, 206, 8
LTEXT "Markus Kuhn, Colin Watson, and CORE SDI S.A.", 1004, 10, 50, 206, 8
LTEXT "Permission is hereby granted, free of charge, to any person", 1005, 10, 66, 206, 8
LTEXT "obtaining a copy of this software and associated documentation", 1006, 10, 74, 206, 8