Support for double-width (CJK) characters, using the xterm-like
authorsimon <simon@cda61777-01e9-0310-a592-d414129be87e>
Wed, 1 Jan 2003 21:53:22 +0000 (21:53 +0000)
committersimon <simon@cda61777-01e9-0310-a592-d414129be87e>
Wed, 1 Jan 2003 21:53:22 +0000 (21:53 +0000)
options -fw and -fwb to specify wide and wide-bold fonts.

git-svn-id: svn://svn.tartarus.org/sgt/putty@2412 cda61777-01e9-0310-a592-d414129be87e

putty.h
unix/pterm.1
unix/pterm.c

diff --git a/putty.h b/putty.h
index 3ff9e9d..113d355 100644 (file)
--- a/putty.h
+++ b/putty.h
@@ -349,7 +349,9 @@ struct config_tag {
     int stamp_utmp;
     int login_shell;
     int scrollbar_on_left;
-    char boldfont[64];
+    char boldfont[256];
+    char widefont[256];
+    char wideboldfont[256];
     int shadowboldoffset;
 };
 
index 0cad725..e08d033 100644 (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
 and you do not specify a bold font, \fIpterm\fP will overprint the
 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"
 Specify the size of the terminal, in rows and columns of text.
 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
 is turned off. The default is unset (the font will be bolded by
 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"
 This resource can be set to an integer; the default is \-1. It
 specifies the offset at which text is overprinted when using "shadow
index 9c86b32..fa9fe1d 100644 (file)
@@ -39,11 +39,11 @@ struct gui_data {
     GtkBox *hbox;
     GtkAdjustment *sbar_adjust;
     GdkPixmap *pixmap;
-    GdkFont *fonts[2];                 /* normal and bold (for now!) */
+    GdkFont *fonts[4];                 /* normal, bold, wide, widebold */
     struct {
        int charset;
        int is_wide;
-    } fontinfo[2];
+    } fontinfo[4];
     GdkCursor *rawcursor, *textcursor, *blankcursor, *currcursor;
     GdkColor cols[NCOLOURS];
     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;
     GdkGC *gc = dctx->gc;
 
-    int nfg, nbg, t, fontid, shadow, rlen;
-
-    /*
-     * NYI:
-     *  - Unicode, code pages, and ATTR_WIDE for CJK support.
-     */
+    int nfg, nbg, t, fontid, shadow, rlen, widefactor;
 
     nfg = 2 * ((attr & ATTR_FGMASK) >> ATTR_FGSHIFT);
     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;
+
+    if (attr & ATTR_WIDE) {
+       widefactor = 2;
+       fontid |= 2;
+    } else {
+       widefactor = 1;
+    }
+
     if ((attr & ATTR_BOLD) && !cfg.bold_colour) {
-       if (inst->fonts[1])
-           fontid = 1;
+       if (inst->fonts[fontid | 1])
+           fontid |= 1;
        else
            shadow = 1;
     }
@@ -1504,8 +1507,8 @@ void do_text_internal(Context ctx, int x, int y, char *text, int len,
        x *= 2;
        if (x >= inst->term->cols)
            return;
-       if (x + len*2 > inst->term->cols)
-           len = (inst->term->cols-x)/2;    /* trim to LH half */
+       if (x + len*2*widefactor > inst->term->cols)
+           len = (inst->term->cols-x)/2/widefactor;/* trim to LH half */
        rlen = len * 2;
     } else
        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.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;
        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,
                       x*inst->font_width+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]);
     {
@@ -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));
        }
 
-       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));
            /*
             * 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;
        gdk_draw_line(inst->pixmap, gc, x*inst->font_width+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);
     }
 
@@ -1594,7 +1604,7 @@ void do_text_internal(Context ctx, int x, int y, char *text, int len,
         * try thinking of a better way. :-(
         */
        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,
                            x*inst->font_width+cfg.window_border + 2*i,
                            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,
                                x*inst->font_width+cfg.window_border,
                                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),
                                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 gui_data *inst = dctx->inst;
     GdkGC *gc = dctx->gc;
+    int widefactor;
 
     do_text_internal(ctx, x, y, text, len, attr, lattr);
 
+    if (attr & ATTR_WIDE) {
+       widefactor = 2;
+    } else {
+       widefactor = 1;
+    }
+
     if (lattr != LATTR_NORM) {
        x *= 2;
        if (x >= inst->term->cols)
            return;
-       if (x + len*2 > inst->term->cols)
-           len = (inst->term->cols-x)/2;    /* trim to LH half */
+       if (x + len*2*widefactor > inst->term->cols)
+           len = (inst->term->cols-x)/2/widefactor;/* trim to LH half */
        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,
                    x*inst->font_width+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,
@@ -1655,7 +1672,7 @@ void do_cursor(Context ctx, int x, int y, char *text, int len,
     struct gui_data *inst = dctx->inst;
     GdkGC *gc = dctx->gc;
 
-    int passive;
+    int passive, widefactor;
 
     if (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);
 
+    if (attr & ATTR_WIDE) {
+       widefactor = 2;
+    } else {
+       widefactor = 1;
+    }
+
     if (lattr != LATTR_NORM) {
        x *= 2;
        if (x >= inst->term->cols)
            return;
-       if (x + len*2 > inst->term->cols)
-           len = (inst->term->cols-x)/2;    /* trim to LH half */
+       if (x + len*2*widefactor > inst->term->cols)
+           len = (inst->term->cols-x)/2/widefactor;/* trim to LH half */
        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,
                    x*inst->font_width+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)
@@ -1923,6 +1946,18 @@ int do_cmdline(int argc, char **argv, int do_everything)
            strncpy(cfg.boldfont, val, sizeof(cfg.boldfont));
            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")) {
            EXPECTS_ARG;
            SECOND_PASS_ONLY;
@@ -2171,6 +2206,26 @@ int main(int argc, char **argv)
        set_font_info(inst, 1);
     } else
        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_height = inst->fonts[0]->ascent + inst->fonts[0]->descent;