mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-01-10 09:58:01 +00:00
Support for double-width (CJK) characters, using the xterm-like
options -fw and -fwb to specify wide and wide-bold fonts. [originally from svn r2412]
This commit is contained in:
parent
7bdd57f300
commit
d97ac46223
4
putty.h
4
putty.h
@ -349,7 +349,9 @@ struct config_tag {
|
|||||||
int stamp_utmp;
|
int stamp_utmp;
|
||||||
int login_shell;
|
int login_shell;
|
||||||
int scrollbar_on_left;
|
int scrollbar_on_left;
|
||||||
char boldfont[64];
|
char boldfont[256];
|
||||||
|
char widefont[256];
|
||||||
|
char wideboldfont[256];
|
||||||
int shadowboldoffset;
|
int shadowboldoffset;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
17
unix/pterm.1
17
unix/pterm.1
@ -36,6 +36,13 @@ will be displayed in different colours instead of a different font,
|
|||||||
so this option will be ignored. If \fIBoldAsColour\fP is set to 0
|
so this option will be ignored. If \fIBoldAsColour\fP is set to 0
|
||||||
and you do not specify a bold font, \fIpterm\fP will overprint the
|
and you do not specify a bold font, \fIpterm\fP will overprint the
|
||||||
normal font to make it look bolder.
|
normal font to make it look bolder.
|
||||||
|
.IP "\fB\-fw\fP \fIfont-name\fP"
|
||||||
|
Specify the font to use for double-width characters (typically
|
||||||
|
Chinese, Japanese and Korean text) displayed in the terminal.
|
||||||
|
.IP "\fB\-fwb\fP \fIfont-name\fP"
|
||||||
|
Specify the font to use for bold double-width characters (typically
|
||||||
|
Chinese, Japanese and Korean text) Like \fI-fb\fP, this will be
|
||||||
|
ignored unless the \fIBoldAsColour\fP resource is set to 0.
|
||||||
.IP "\fB\-geometry\fP \fIwidth\fPx\fIheight\fP"
|
.IP "\fB\-geometry\fP \fIwidth\fPx\fIheight\fP"
|
||||||
Specify the size of the terminal, in rows and columns of text.
|
Specify the size of the terminal, in rows and columns of text.
|
||||||
Unfortunately \fIpterm\fP does not currently support specifying the
|
Unfortunately \fIpterm\fP does not currently support specifying the
|
||||||
@ -306,6 +313,16 @@ This resource is the same as the \fI\-fb\fP command-line option: it
|
|||||||
controls the font used to display bold text when \fIBoldAsColour\fP
|
controls the font used to display bold text when \fIBoldAsColour\fP
|
||||||
is turned off. The default is unset (the font will be bolded by
|
is turned off. The default is unset (the font will be bolded by
|
||||||
printing it twice at a one-pixel offset).
|
printing it twice at a one-pixel offset).
|
||||||
|
.IP "\fBpterm.WideFont\fP"
|
||||||
|
This resource is the same as the \fI\-fw\fP command-line option: it
|
||||||
|
controls the font used to display double-width characters. The
|
||||||
|
default is unset (double-width characters cannot be displayed).
|
||||||
|
.IP "\fBpterm.WideBoldFont\fP"
|
||||||
|
This resource is the same as the \fI\-fwb\fP command-line option: it
|
||||||
|
controls the font used to display double-width characters in bold,
|
||||||
|
when \fIBoldAsColour\fP is turned off. The default is unset
|
||||||
|
(double-width characters are displayed in bold by printing them
|
||||||
|
twice at a one-pixel offset).
|
||||||
.IP "\fBpterm.ShadowBoldOffset\fP"
|
.IP "\fBpterm.ShadowBoldOffset\fP"
|
||||||
This resource can be set to an integer; the default is \-1. It
|
This resource can be set to an integer; the default is \-1. It
|
||||||
specifies the offset at which text is overprinted when using "shadow
|
specifies the offset at which text is overprinted when using "shadow
|
||||||
|
105
unix/pterm.c
105
unix/pterm.c
@ -39,11 +39,11 @@ struct gui_data {
|
|||||||
GtkBox *hbox;
|
GtkBox *hbox;
|
||||||
GtkAdjustment *sbar_adjust;
|
GtkAdjustment *sbar_adjust;
|
||||||
GdkPixmap *pixmap;
|
GdkPixmap *pixmap;
|
||||||
GdkFont *fonts[2]; /* normal and bold (for now!) */
|
GdkFont *fonts[4]; /* normal, bold, wide, widebold */
|
||||||
struct {
|
struct {
|
||||||
int charset;
|
int charset;
|
||||||
int is_wide;
|
int is_wide;
|
||||||
} fontinfo[2];
|
} fontinfo[4];
|
||||||
GdkCursor *rawcursor, *textcursor, *blankcursor, *currcursor;
|
GdkCursor *rawcursor, *textcursor, *blankcursor, *currcursor;
|
||||||
GdkColor cols[NCOLOURS];
|
GdkColor cols[NCOLOURS];
|
||||||
GdkColormap *colmap;
|
GdkColormap *colmap;
|
||||||
@ -1469,12 +1469,7 @@ void do_text_internal(Context ctx, int x, int y, char *text, int len,
|
|||||||
struct gui_data *inst = dctx->inst;
|
struct gui_data *inst = dctx->inst;
|
||||||
GdkGC *gc = dctx->gc;
|
GdkGC *gc = dctx->gc;
|
||||||
|
|
||||||
int nfg, nbg, t, fontid, shadow, rlen;
|
int nfg, nbg, t, fontid, shadow, rlen, widefactor;
|
||||||
|
|
||||||
/*
|
|
||||||
* NYI:
|
|
||||||
* - Unicode, code pages, and ATTR_WIDE for CJK support.
|
|
||||||
*/
|
|
||||||
|
|
||||||
nfg = 2 * ((attr & ATTR_FGMASK) >> ATTR_FGSHIFT);
|
nfg = 2 * ((attr & ATTR_FGMASK) >> ATTR_FGSHIFT);
|
||||||
nbg = 2 * ((attr & ATTR_BGMASK) >> ATTR_BGSHIFT);
|
nbg = 2 * ((attr & ATTR_BGMASK) >> ATTR_BGSHIFT);
|
||||||
@ -1493,9 +1488,17 @@ void do_text_internal(Context ctx, int x, int y, char *text, int len,
|
|||||||
}
|
}
|
||||||
|
|
||||||
fontid = shadow = 0;
|
fontid = shadow = 0;
|
||||||
|
|
||||||
|
if (attr & ATTR_WIDE) {
|
||||||
|
widefactor = 2;
|
||||||
|
fontid |= 2;
|
||||||
|
} else {
|
||||||
|
widefactor = 1;
|
||||||
|
}
|
||||||
|
|
||||||
if ((attr & ATTR_BOLD) && !cfg.bold_colour) {
|
if ((attr & ATTR_BOLD) && !cfg.bold_colour) {
|
||||||
if (inst->fonts[1])
|
if (inst->fonts[fontid | 1])
|
||||||
fontid = 1;
|
fontid |= 1;
|
||||||
else
|
else
|
||||||
shadow = 1;
|
shadow = 1;
|
||||||
}
|
}
|
||||||
@ -1504,8 +1507,8 @@ void do_text_internal(Context ctx, int x, int y, char *text, int len,
|
|||||||
x *= 2;
|
x *= 2;
|
||||||
if (x >= inst->term->cols)
|
if (x >= inst->term->cols)
|
||||||
return;
|
return;
|
||||||
if (x + len*2 > inst->term->cols)
|
if (x + len*2*widefactor > inst->term->cols)
|
||||||
len = (inst->term->cols-x)/2; /* trim to LH half */
|
len = (inst->term->cols-x)/2/widefactor;/* trim to LH half */
|
||||||
rlen = len * 2;
|
rlen = len * 2;
|
||||||
} else
|
} else
|
||||||
rlen = len;
|
rlen = len;
|
||||||
@ -1515,7 +1518,7 @@ void do_text_internal(Context ctx, int x, int y, char *text, int len,
|
|||||||
|
|
||||||
r.x = x*inst->font_width+cfg.window_border;
|
r.x = x*inst->font_width+cfg.window_border;
|
||||||
r.y = y*inst->font_height+cfg.window_border;
|
r.y = y*inst->font_height+cfg.window_border;
|
||||||
r.width = rlen*inst->font_width;
|
r.width = rlen*widefactor*inst->font_width;
|
||||||
r.height = inst->font_height;
|
r.height = inst->font_height;
|
||||||
gdk_gc_set_clip_rectangle(gc, &r);
|
gdk_gc_set_clip_rectangle(gc, &r);
|
||||||
}
|
}
|
||||||
@ -1524,7 +1527,7 @@ void do_text_internal(Context ctx, int x, int y, char *text, int len,
|
|||||||
gdk_draw_rectangle(inst->pixmap, gc, 1,
|
gdk_draw_rectangle(inst->pixmap, gc, 1,
|
||||||
x*inst->font_width+cfg.window_border,
|
x*inst->font_width+cfg.window_border,
|
||||||
y*inst->font_height+cfg.window_border,
|
y*inst->font_height+cfg.window_border,
|
||||||
rlen*inst->font_width, inst->font_height);
|
rlen*widefactor*inst->font_width, inst->font_height);
|
||||||
|
|
||||||
gdk_gc_set_foreground(gc, &inst->cols[nfg]);
|
gdk_gc_set_foreground(gc, &inst->cols[nfg]);
|
||||||
{
|
{
|
||||||
@ -1538,7 +1541,14 @@ void do_text_internal(Context ctx, int x, int y, char *text, int len,
|
|||||||
wcs[i] = (wchar_t) ((attr & CSET_MASK) + (text[i] & CHAR_MASK));
|
wcs[i] = (wchar_t) ((attr & CSET_MASK) + (text[i] & CHAR_MASK));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (inst->fontinfo[fontid].is_wide) {
|
if (inst->fonts[fontid] == NULL) {
|
||||||
|
/*
|
||||||
|
* The font for this contingency does not exist.
|
||||||
|
* Typically this means we've been given ATTR_WIDE
|
||||||
|
* character and have no wide font. So we display
|
||||||
|
* nothing at all; such is life.
|
||||||
|
*/
|
||||||
|
} else if (inst->fontinfo[fontid].is_wide) {
|
||||||
gwcs = smalloc(sizeof(GdkWChar) * (len+1));
|
gwcs = smalloc(sizeof(GdkWChar) * (len+1));
|
||||||
/*
|
/*
|
||||||
* FIXME: when we have a wide-char equivalent of
|
* FIXME: when we have a wide-char equivalent of
|
||||||
@ -1580,7 +1590,7 @@ void do_text_internal(Context ctx, int x, int y, char *text, int len,
|
|||||||
uheight = inst->font_height - 1;
|
uheight = inst->font_height - 1;
|
||||||
gdk_draw_line(inst->pixmap, gc, x*inst->font_width+cfg.window_border,
|
gdk_draw_line(inst->pixmap, gc, x*inst->font_width+cfg.window_border,
|
||||||
y*inst->font_height + uheight + cfg.window_border,
|
y*inst->font_height + uheight + cfg.window_border,
|
||||||
(x+len)*inst->font_width-1+cfg.window_border,
|
(x+len)*widefactor*inst->font_width-1+cfg.window_border,
|
||||||
y*inst->font_height + uheight + cfg.window_border);
|
y*inst->font_height + uheight + cfg.window_border);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1594,7 +1604,7 @@ void do_text_internal(Context ctx, int x, int y, char *text, int len,
|
|||||||
* try thinking of a better way. :-(
|
* try thinking of a better way. :-(
|
||||||
*/
|
*/
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < len * inst->font_width; i++) {
|
for (i = 0; i < len * widefactor * inst->font_width; i++) {
|
||||||
gdk_draw_pixmap(inst->pixmap, gc, inst->pixmap,
|
gdk_draw_pixmap(inst->pixmap, gc, inst->pixmap,
|
||||||
x*inst->font_width+cfg.window_border + 2*i,
|
x*inst->font_width+cfg.window_border + 2*i,
|
||||||
y*inst->font_height+cfg.window_border,
|
y*inst->font_height+cfg.window_border,
|
||||||
@ -1614,7 +1624,7 @@ void do_text_internal(Context ctx, int x, int y, char *text, int len,
|
|||||||
gdk_draw_pixmap(inst->pixmap, gc, inst->pixmap,
|
gdk_draw_pixmap(inst->pixmap, gc, inst->pixmap,
|
||||||
x*inst->font_width+cfg.window_border,
|
x*inst->font_width+cfg.window_border,
|
||||||
y*inst->font_height+cfg.window_border+dt*i+db,
|
y*inst->font_height+cfg.window_border+dt*i+db,
|
||||||
x*inst->font_width+cfg.window_border,
|
x*widefactor*inst->font_width+cfg.window_border,
|
||||||
y*inst->font_height+cfg.window_border+dt*(i+1),
|
y*inst->font_height+cfg.window_border+dt*(i+1),
|
||||||
len * inst->font_width, inst->font_height-i-1);
|
len * inst->font_width, inst->font_height-i-1);
|
||||||
}
|
}
|
||||||
@ -1628,15 +1638,22 @@ void do_text(Context ctx, int x, int y, char *text, int len,
|
|||||||
struct draw_ctx *dctx = (struct draw_ctx *)ctx;
|
struct draw_ctx *dctx = (struct draw_ctx *)ctx;
|
||||||
struct gui_data *inst = dctx->inst;
|
struct gui_data *inst = dctx->inst;
|
||||||
GdkGC *gc = dctx->gc;
|
GdkGC *gc = dctx->gc;
|
||||||
|
int widefactor;
|
||||||
|
|
||||||
do_text_internal(ctx, x, y, text, len, attr, lattr);
|
do_text_internal(ctx, x, y, text, len, attr, lattr);
|
||||||
|
|
||||||
|
if (attr & ATTR_WIDE) {
|
||||||
|
widefactor = 2;
|
||||||
|
} else {
|
||||||
|
widefactor = 1;
|
||||||
|
}
|
||||||
|
|
||||||
if (lattr != LATTR_NORM) {
|
if (lattr != LATTR_NORM) {
|
||||||
x *= 2;
|
x *= 2;
|
||||||
if (x >= inst->term->cols)
|
if (x >= inst->term->cols)
|
||||||
return;
|
return;
|
||||||
if (x + len*2 > inst->term->cols)
|
if (x + len*2*widefactor > inst->term->cols)
|
||||||
len = (inst->term->cols-x)/2; /* trim to LH half */
|
len = (inst->term->cols-x)/2/widefactor;/* trim to LH half */
|
||||||
len *= 2;
|
len *= 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1645,7 +1662,7 @@ void do_text(Context ctx, int x, int y, char *text, int len,
|
|||||||
y*inst->font_height+cfg.window_border,
|
y*inst->font_height+cfg.window_border,
|
||||||
x*inst->font_width+cfg.window_border,
|
x*inst->font_width+cfg.window_border,
|
||||||
y*inst->font_height+cfg.window_border,
|
y*inst->font_height+cfg.window_border,
|
||||||
len*inst->font_width, inst->font_height);
|
len*widefactor*inst->font_width, inst->font_height);
|
||||||
}
|
}
|
||||||
|
|
||||||
void do_cursor(Context ctx, int x, int y, char *text, int len,
|
void do_cursor(Context ctx, int x, int y, char *text, int len,
|
||||||
@ -1655,7 +1672,7 @@ void do_cursor(Context ctx, int x, int y, char *text, int len,
|
|||||||
struct gui_data *inst = dctx->inst;
|
struct gui_data *inst = dctx->inst;
|
||||||
GdkGC *gc = dctx->gc;
|
GdkGC *gc = dctx->gc;
|
||||||
|
|
||||||
int passive;
|
int passive, widefactor;
|
||||||
|
|
||||||
if (attr & TATTR_PASCURS) {
|
if (attr & TATTR_PASCURS) {
|
||||||
attr &= ~TATTR_PASCURS;
|
attr &= ~TATTR_PASCURS;
|
||||||
@ -1667,12 +1684,18 @@ void do_cursor(Context ctx, int x, int y, char *text, int len,
|
|||||||
}
|
}
|
||||||
do_text_internal(ctx, x, y, text, len, attr, lattr);
|
do_text_internal(ctx, x, y, text, len, attr, lattr);
|
||||||
|
|
||||||
|
if (attr & ATTR_WIDE) {
|
||||||
|
widefactor = 2;
|
||||||
|
} else {
|
||||||
|
widefactor = 1;
|
||||||
|
}
|
||||||
|
|
||||||
if (lattr != LATTR_NORM) {
|
if (lattr != LATTR_NORM) {
|
||||||
x *= 2;
|
x *= 2;
|
||||||
if (x >= inst->term->cols)
|
if (x >= inst->term->cols)
|
||||||
return;
|
return;
|
||||||
if (x + len*2 > inst->term->cols)
|
if (x + len*2*widefactor > inst->term->cols)
|
||||||
len = (inst->term->cols-x)/2; /* trim to LH half */
|
len = (inst->term->cols-x)/2/widefactor;/* trim to LH half */
|
||||||
len *= 2;
|
len *= 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1741,7 +1764,7 @@ void do_cursor(Context ctx, int x, int y, char *text, int len,
|
|||||||
y*inst->font_height+cfg.window_border,
|
y*inst->font_height+cfg.window_border,
|
||||||
x*inst->font_width+cfg.window_border,
|
x*inst->font_width+cfg.window_border,
|
||||||
y*inst->font_height+cfg.window_border,
|
y*inst->font_height+cfg.window_border,
|
||||||
len*inst->font_width, inst->font_height);
|
len*widefactor*inst->font_width, inst->font_height);
|
||||||
}
|
}
|
||||||
|
|
||||||
GdkCursor *make_mouse_ptr(struct gui_data *inst, int cursor_val)
|
GdkCursor *make_mouse_ptr(struct gui_data *inst, int cursor_val)
|
||||||
@ -1923,6 +1946,18 @@ int do_cmdline(int argc, char **argv, int do_everything)
|
|||||||
strncpy(cfg.boldfont, val, sizeof(cfg.boldfont));
|
strncpy(cfg.boldfont, val, sizeof(cfg.boldfont));
|
||||||
cfg.boldfont[sizeof(cfg.boldfont)-1] = '\0';
|
cfg.boldfont[sizeof(cfg.boldfont)-1] = '\0';
|
||||||
|
|
||||||
|
} else if (!strcmp(p, "-fw")) {
|
||||||
|
EXPECTS_ARG;
|
||||||
|
SECOND_PASS_ONLY;
|
||||||
|
strncpy(cfg.widefont, val, sizeof(cfg.widefont));
|
||||||
|
cfg.widefont[sizeof(cfg.widefont)-1] = '\0';
|
||||||
|
|
||||||
|
} else if (!strcmp(p, "-fwb")) {
|
||||||
|
EXPECTS_ARG;
|
||||||
|
SECOND_PASS_ONLY;
|
||||||
|
strncpy(cfg.wideboldfont, val, sizeof(cfg.wideboldfont));
|
||||||
|
cfg.wideboldfont[sizeof(cfg.wideboldfont)-1] = '\0';
|
||||||
|
|
||||||
} else if (!strcmp(p, "-cs")) {
|
} else if (!strcmp(p, "-cs")) {
|
||||||
EXPECTS_ARG;
|
EXPECTS_ARG;
|
||||||
SECOND_PASS_ONLY;
|
SECOND_PASS_ONLY;
|
||||||
@ -2171,6 +2206,26 @@ int main(int argc, char **argv)
|
|||||||
set_font_info(inst, 1);
|
set_font_info(inst, 1);
|
||||||
} else
|
} else
|
||||||
inst->fonts[1] = NULL;
|
inst->fonts[1] = NULL;
|
||||||
|
if (cfg.widefont[0]) {
|
||||||
|
inst->fonts[2] = gdk_font_load(cfg.widefont);
|
||||||
|
if (!inst->fonts[2]) {
|
||||||
|
fprintf(stderr, "pterm: unable to load wide font \"%s\"\n",
|
||||||
|
cfg.boldfont);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
set_font_info(inst, 2);
|
||||||
|
} else
|
||||||
|
inst->fonts[2] = NULL;
|
||||||
|
if (cfg.wideboldfont[0]) {
|
||||||
|
inst->fonts[3] = gdk_font_load(cfg.wideboldfont);
|
||||||
|
if (!inst->fonts[3]) {
|
||||||
|
fprintf(stderr, "pterm: unable to load wide/bold font \"%s\"\n",
|
||||||
|
cfg.boldfont);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
set_font_info(inst, 3);
|
||||||
|
} else
|
||||||
|
inst->fonts[3] = NULL;
|
||||||
|
|
||||||
inst->font_width = gdk_char_width(inst->fonts[0], ' ');
|
inst->font_width = gdk_char_width(inst->fonts[0], ' ');
|
||||||
inst->font_height = inst->fonts[0]->ascent + inst->fonts[0]->descent;
|
inst->font_height = inst->fonts[0]->ascent + inst->fonts[0]->descent;
|
||||||
|
Loading…
Reference in New Issue
Block a user