1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-01-10 01:48:00 +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:
Simon Tatham 2003-01-01 21:53:22 +00:00
parent 7bdd57f300
commit d97ac46223
3 changed files with 100 additions and 26 deletions

View File

@ -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;
}; };

View File

@ -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

View File

@ -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;