diff --git a/include/winX.h b/include/winX.h index f408aee04..9cc55e09a 100644 --- a/include/winX.h +++ b/include/winX.h @@ -513,5 +513,9 @@ extern void genl_outrip(winid, int, time_t); extern void X11_preference_update(const char *); extern void X11_update_inventory(int); extern win_request_info *X11_ctrl_nhwindow(winid, int, win_request_info *); +extern X11_map_symbol X11_glyph_char(const glyph_info *); +#ifdef ENHANCED_SYMBOLS +extern XFontStruct *X11_unicode_font(Display *, XFontStruct *); +#endif #endif /* WINX_H */ diff --git a/win/X11/winX.c b/win/X11/winX.c index 59cbb933e..28d3e4da5 100644 --- a/win/X11/winX.c +++ b/win/X11/winX.c @@ -2925,4 +2925,126 @@ nh_keyscroll(Widget viewport, XEvent *event, String *params, } } +/* Convert CP437 or DECgraphics to Unicode */ +X11_map_symbol +X11_glyph_char(const glyph_info *glyphinfo) +{ +#ifdef ENHANCED_SYMBOLS + /* CP437 to Unicode mapping according to the Unicode Consortium */ + static const uint16 cp437[256] = { + 0x0020, 0x263A, 0x263B, 0x2665, 0x2666, 0x2663, 0x2660, 0x2022, + 0x25D8, 0x25CB, 0x25D9, 0x2642, 0x2640, 0x266A, 0x266B, 0x263C, + 0x25BA, 0x25C4, 0x2195, 0x203C, 0x00B6, 0x00A7, 0x25AC, 0x21A8, + 0x2191, 0x2193, 0x2192, 0x2190, 0x221F, 0x2194, 0x25B2, 0x25BC, + 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, + 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f, + 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, + 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, + 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, + 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, + 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, + 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f, + 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, + 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f, + 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, + 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x2302, + 0x00c7, 0x00fc, 0x00e9, 0x00e2, 0x00e4, 0x00e0, 0x00e5, 0x00e7, + 0x00ea, 0x00eb, 0x00e8, 0x00ef, 0x00ee, 0x00ec, 0x00c4, 0x00c5, + 0x00c9, 0x00e6, 0x00c6, 0x00f4, 0x00f6, 0x00f2, 0x00fb, 0x00f9, + 0x00ff, 0x00d6, 0x00dc, 0x00a2, 0x00a3, 0x00a5, 0x20a7, 0x0192, + 0x00e1, 0x00ed, 0x00f3, 0x00fa, 0x00f1, 0x00d1, 0x00aa, 0x00ba, + 0x00bf, 0x2310, 0x00ac, 0x00bd, 0x00bc, 0x00a1, 0x00ab, 0x00bb, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, + 0x2555, 0x2563, 0x2551, 0x2557, 0x255d, 0x255c, 0x255b, 0x2510, + 0x2514, 0x2534, 0x252c, 0x251c, 0x2500, 0x253c, 0x255e, 0x255f, + 0x255a, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256c, 0x2567, + 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256b, + 0x256a, 0x2518, 0x250c, 0x2588, 0x2584, 0x258c, 0x2590, 0x2580, + 0x03b1, 0x00df, 0x0393, 0x03c0, 0x03a3, 0x03c3, 0x00b5, 0x03c4, + 0x03a6, 0x0398, 0x03a9, 0x03b4, 0x221e, 0x03c6, 0x03b5, 0x2229, + 0x2261, 0x00b1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00f7, 0x2248, + 0x00b0, 0x2219, 0x00b7, 0x221a, 0x207f, 0x00b2, 0x25a0, 0x00a0 + }; + /* Display DECgraphics as Unicode */ + static const uint16 decgraphics[128] = { + 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, + 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F, + 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, + 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F, + 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, + 0x0028, 0x0029, 0x002A, 0x2192, 0x2190, 0x2191, 0x2193, 0x002F, + 0x2588, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, + 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F, + 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, + 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F, + 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, + 0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F, + 0x2666, 0x2592, 0x0062, 0x0063, 0x0064, 0x0065, 0x00B0, 0x00B1, + 0x2591, 0x00A4, 0x2518, 0x2510, 0x250C, 0x2514, 0x253C, 0x23BA, + 0x23BB, 0x2500, 0x23BC, 0x23BD, 0x251C, 0x2524, 0x2534, 0x252C, + 0x2502, 0x2264, 0x2265, 0x03C0, 0x2260, 0x00A3, 0x00B7, 0x007F + }; + X11_map_symbol och; + + if (SYMHANDLING(H_UTF8) && glyphinfo->gm.u != NULL && glyphinfo->gm.u->utf8str != NULL) { + och = glyphinfo->gm.u->utf32ch; + } else { + och = (uchar) glyphinfo->ttychar; + if (SYMHANDLING(H_IBM)) { + och = cp437[och]; + } else if ((SYMHANDLING(H_DEC) || SYMHANDLING(H_CURS)) && och >= 0x80) { + och = decgraphics[och & 0x7F]; + } + } + + return och; +#else + return (char) glyphinfo->ttychar; +#endif +} + +#ifdef ENHANCED_SYMBOLS +/* Given an XFontStruct, return a corresponding font that supports Unicode */ +XFontStruct * +X11_unicode_font(Display *display, XFontStruct *font) +{ + Atom font_atom; + if (!XGetFontProperty(font, XA_FONT, &font_atom)) { + return NULL; + } + + const char *font_name = XGetAtomName(display, font_atom); + if (font_name == NULL) { + return NULL; + } + + /* Proceed to the registry name */ + unsigned dashes = 13; + const char *p = font_name; + while (dashes != 0) { + const char *q = strchr(p, '-'); + if (q == NULL) { + break; + } + p = q + 1; + --dashes; + } + + /* Substitute "iso10646-1" for the registry name and encoding */ + size_t len = (size_t) (p - font_name); + char unicode_font[BUFSZ]; + if (dashes != 0 || len + 11 > sizeof(unicode_font)) { + return NULL; + } + + memcpy(unicode_font, font_name, len); + strcpy(unicode_font + len, "iso10646-1"); + font_name = unicode_font; + + Font font_id = XLoadFont(display, font_name); + XFontStruct *unifont = XQueryFont(display, font_id); + return unifont; +} +#endif /* ENHANCED_SYMBOLS */ + /*winX.c*/ diff --git a/win/X11/winmap.c b/win/X11/winmap.c index 1ee30626e..a99ebef5a 100644 --- a/win/X11/winmap.c +++ b/win/X11/winmap.c @@ -59,7 +59,6 @@ extern int total_tiles_used, Tile_corr; #define NH_INVERSE_COLOR 0x40000000 #define NH_ENHANCED_COLOR 0x80000000 -static X11_map_symbol glyph_char(const glyph_info *glyphinfo); static GC X11_make_gc(struct xwindow *wp, struct text_map_info_t *text_map, X11_color color, boolean inverted); #ifdef ENHANCED_SYMBOLS @@ -136,7 +135,7 @@ X11_print_glyph( color = glyphinfo->gm.sym.color; special = glyphinfo->gm.glyphflags; - ch = glyph_char(glyphinfo); + ch = X11_glyph_char(glyphinfo); if (glyphinfo->gm.customcolor != 0) { if ((glyphinfo->gm.customcolor & NH_BASIC_COLOR) != 0) { @@ -196,83 +195,6 @@ X11_print_glyph( } } -static X11_map_symbol -glyph_char(const glyph_info *glyphinfo) -{ -#ifdef ENHANCED_SYMBOLS - /* CP437 to Unicode mapping according to the Unicode Consortium */ - static const uint16 cp437[256] = { - 0x0020, 0x263A, 0x263B, 0x2665, 0x2666, 0x2663, 0x2660, 0x2022, - 0x25D8, 0x25CB, 0x25D9, 0x2642, 0x2640, 0x266A, 0x266B, 0x263C, - 0x25BA, 0x25C4, 0x2195, 0x203C, 0x00B6, 0x00A7, 0x25AC, 0x21A8, - 0x2191, 0x2193, 0x2192, 0x2190, 0x221F, 0x2194, 0x25B2, 0x25BC, - 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, - 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f, - 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, - 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, - 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, - 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, - 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, - 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f, - 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, - 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f, - 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, - 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x2302, - 0x00c7, 0x00fc, 0x00e9, 0x00e2, 0x00e4, 0x00e0, 0x00e5, 0x00e7, - 0x00ea, 0x00eb, 0x00e8, 0x00ef, 0x00ee, 0x00ec, 0x00c4, 0x00c5, - 0x00c9, 0x00e6, 0x00c6, 0x00f4, 0x00f6, 0x00f2, 0x00fb, 0x00f9, - 0x00ff, 0x00d6, 0x00dc, 0x00a2, 0x00a3, 0x00a5, 0x20a7, 0x0192, - 0x00e1, 0x00ed, 0x00f3, 0x00fa, 0x00f1, 0x00d1, 0x00aa, 0x00ba, - 0x00bf, 0x2310, 0x00ac, 0x00bd, 0x00bc, 0x00a1, 0x00ab, 0x00bb, - 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, - 0x2555, 0x2563, 0x2551, 0x2557, 0x255d, 0x255c, 0x255b, 0x2510, - 0x2514, 0x2534, 0x252c, 0x251c, 0x2500, 0x253c, 0x255e, 0x255f, - 0x255a, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256c, 0x2567, - 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256b, - 0x256a, 0x2518, 0x250c, 0x2588, 0x2584, 0x258c, 0x2590, 0x2580, - 0x03b1, 0x00df, 0x0393, 0x03c0, 0x03a3, 0x03c3, 0x00b5, 0x03c4, - 0x03a6, 0x0398, 0x03a9, 0x03b4, 0x221e, 0x03c6, 0x03b5, 0x2229, - 0x2261, 0x00b1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00f7, 0x2248, - 0x00b0, 0x2219, 0x00b7, 0x221a, 0x207f, 0x00b2, 0x25a0, 0x00a0 - }; - /* Display DECgraphics as Unicode */ - static const uint16 decgraphics[128] = { - 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, - 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F, - 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, - 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F, - 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, - 0x0028, 0x0029, 0x002A, 0x2192, 0x2190, 0x2191, 0x2193, 0x002F, - 0x2588, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, - 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F, - 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, - 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F, - 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, - 0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F, - 0x2666, 0x2592, 0x0062, 0x0063, 0x0064, 0x0065, 0x00B0, 0x00B1, - 0x2591, 0x00A4, 0x2518, 0x2510, 0x250C, 0x2514, 0x253C, 0x23BA, - 0x23BB, 0x2500, 0x23BC, 0x23BD, 0x251C, 0x2524, 0x2534, 0x252C, - 0x2502, 0x2264, 0x2265, 0x03C0, 0x2260, 0x00A3, 0x00B7, 0x007F - }; - X11_map_symbol och; - - if (SYMHANDLING(H_UTF8) && glyphinfo->gm.u != NULL && glyphinfo->gm.u->utf8str != NULL) { - och = glyphinfo->gm.u->utf32ch; - } else { - och = (uchar) glyphinfo->ttychar; - if (SYMHANDLING(H_IBM)) { - och = cp437[och]; - } else if ((SYMHANDLING(H_DEC) || SYMHANDLING(H_CURS)) && och >= 0x80) { - och = decgraphics[och & 0x7F]; - } - } - - return och; -#else - return (char) glyphinfo->ttychar; -#endif -} - #ifdef CLIPPING /* * The is the tty clip call. Since X can resize at any time, we can't depend @@ -1806,50 +1728,14 @@ X11_set_map_font(struct xwindow *wp) { struct map_info_t *map_info = wp->map_information; XFontStruct *fs; - Atom font_atom; - const char *font_name; - unsigned dashes; - const char *p; - size_t len; - char unicode_font[BUFSZ]; - Font font_id; /* Query the configured font for the map */ fs = WindowFontStruct(wp->w); - map_info->text_map.font = fs; - if (!XGetFontProperty(fs, XA_FONT, &font_atom)) { - return; - } - font_name = XGetAtomName(XtDisplay(wp->w), font_atom); - if (font_name == NULL) { - return; - } - /* Proceed to the registry name */ - dashes = 13; - p = font_name; - while (dashes != 0) { - const char *q = strchr(p, '-'); - if (q == NULL) { - break; - } - p = q + 1; - --dashes; - } - - /* Substitute "iso10646-1" for the registry name and encoding */ - len = (size_t) (p - font_name); - if (dashes != 0 || len + 11 > sizeof(unicode_font)) { - return; - } - - memcpy(unicode_font, font_name, len); - strcpy(unicode_font + len, "iso10646-1"); - font_name = unicode_font; - - font_id = XLoadFont(XtDisplay(wp->w), font_name); - map_info->text_map.font = XQueryFont(XtDisplay(wp->w), font_id); - if (map_info->text_map.font == NULL) { + XFontStruct *unifont = X11_unicode_font(XtDisplay(wp->w), fs); + if (unifont != NULL) { + map_info->text_map.font = unifont; + } else { /* Fallback in case no iso10646 */ map_info->text_map.font = fs; } diff --git a/win/X11/winstat.c b/win/X11/winstat.c index 29cde2327..ea464a329 100644 --- a/win/X11/winstat.c +++ b/win/X11/winstat.c @@ -693,7 +693,6 @@ X11_status_update_tty( int color, unsigned long *colormasks) /* bitmask of highlights for conditions */ { - printf("fld=%d\n", fld); fflush(stdout); switch (fld) { case BL_RESET: case BL_FLUSH: @@ -1260,9 +1259,6 @@ tty_render_text(Widget w, int x, int y, const char *text, int color, int attr, Pixel fgpixel, bgpixel; XFontStruct *font; int goldwidth = 0; -#ifdef ENHANCED_SYMBOLS - XFontStruct *unifont = NULL; -#endif /* Get default foreground and background colors, and font */ num_args = 0; @@ -1290,21 +1286,50 @@ tty_render_text(Widget w, int x, int y, const char *text, int color, int attr, if (is_gold && memcmp(text, "\\G", 2) == 0) { char *end; unsigned long glyphcode = strtoul(text+2, &end, 16); - if ((glyphcode >> 16) == svc.context.rndencode && *end == ':') { + if ((glyphcode >> 16) == (unsigned) svc.context.rndencode && *end == ':') { /* We have a proper glyph code */ glyph_info glyphinfo; glyphcode &= 0xFFFF; map_glyphinfo(0, 0, glyphcode, 0, &glyphinfo); - { - char goldstr[2]; - goldstr[0] = glyphinfo.ttychar; - goldstr[1] = 0; - goldwidth = XTextWidth(font, goldstr, strlen(goldstr)); + X11_map_symbol goldsym = X11_glyph_char(&glyphinfo); +#ifdef ENHANCED_SYMBOLS + if (goldsym > 0xFFFF) { + /* No support for supplementary planes */ + goldsym = GOLD_SYM; + } + if (goldsym > 0x7F) { + XFontStruct *unifont = X11_unicode_font(XtDisplay(w), font); + + if (unifont != NULL) { + XChar2b goldstr[1]; + values.font = unifont->fid; + GC ggc2 = XtGetGC(w, + GCFunction | GCForeground | GCBackground | GCFont, + &values); + + goldstr[0].byte1 = goldsym >> 8; + goldstr[0].byte2 = goldsym & 0xFF; + goldwidth = XTextWidth16(font, goldstr, 1); + + /* Render the string */ + XDrawImageString16(XtDisplay(w), XtWindow(w), ggc, + x, y + font->max_bounds.ascent, + goldstr, 1); + + XFreeFont(XtDisplay(w), unifont); + XtReleaseGC(w, ggc2); + } + } +#endif + if (goldwidth == 0) { + char goldstr[1]; + goldstr[0] = (char) goldsym; + goldwidth = XTextWidth(font, goldstr, 1); /* Render the string */ XDrawImageString(XtDisplay(w), XtWindow(w), ggc, x, y + font->max_bounds.ascent, - goldstr, strlen(goldstr)); + goldstr, 1); } text = end; @@ -1321,11 +1346,6 @@ tty_render_text(Widget w, int x, int y, const char *text, int color, int attr, /* Release resources */ XtReleaseGC(w, ggc); -#ifdef ENHANCED_SYMBOLS - if (unifont != NULL) { - XFreeFont(XtDisplay(w), unifont); - } -#endif /* Caller will advance x by the width */ return goldwidth + width;