IBMgraphics/UTF-8 patch for 3.4.3
Jump to navigation
Jump to search
This post to rec.games.roguelike.nethack describes a patch for NetHack 3.4.3 to allow the TTY mode to display IBMgraphics on terminals that support UTF-8.
The complete thread can be found in the Wayback Machine's archive of Google Groups. Google Groups itself only sporadically allows reading of direct links to posts. This post contains a patch, and Google Groups' mangling of whitespace is a problem. The text below is recovered from the Internet Archive.
Some line breaks are undone, to give a patch that applies cleanly.
The patch is based on an earlier one for NetHack 3.4.0, which is not known to have survived in unmangled form.
Path: border1.nntp.dca.giganews.com!nntp.giganews.com!postnews.google.com!e4g2000prn.googlegroups.com!not-for-mail From: Stephen Anthony Uy <email address redacted> Newsgroups: rec.games.roguelike.nethack Subject: [PATCH] Port of Ray Chason's patch for IBMgraphics on UTF-8 terminals to v3.4.3. Date: Tue, 15 Sep 2009 13:47:23 -0700 (PDT) Organization: http://groups.google.com Lines: 452 Message-ID: <41823c16-aef0-4939-a93d-2fbbe3534e79@e4g2000prn.googlegroups.com> NNTP-Posting-Host: 76.170.88.3 Mime-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1 X-Trace: posting.google.com 1253047643 4853 127.0.0.1 (15 Sep 2009 20:47:23 GMT) X-Complaints-To: groups-abuse@google.com NNTP-Posting-Date: Tue, 15 Sep 2009 20:47:23 +0000 (UTC) Complaints-To: groups-abuse@google.com Injection-Info: e4g2000prn.googlegroups.com; posting-host=76.170.88.3; posting-account=oP41LwoAAAAlf7EaPwc7NmyRmxwusHf3 User-Agent: G2/1.0 X-HTTP-UserAgent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.14) Gecko/2009090216 Ubuntu/9.04 (jaunty) Firefox/3.0.14,gzip(gfe),gzip(gfe) Bytes: 13161 Xref: number.nntp.dca.giganews.com rec.games.roguelike.nethack:372500 This is a port of a patch from 2002 which implemented IBMgraphics on UTF-8-capable terminals. The patch was produced using git v1.6.0.4. I'm currently using this with great success on gnome-terminal; YMMV. Original patch: http://groups.google.com/group/rec.games.roguelike.nethack/ browse_thread/thread/a20fed2561a6abb7 Original explanation of patch: http://groups.google.com/group/rec.games.roguelike.nethack/ browse_frm/thread/f94adf32bd098847/5d88a63ae67d706f --- include/config.h | 3 ++ src/drawing.c | 7 ++++- src/mapglyph.c | 1 + sys/share/ioctl.c | 31 +++++++++++++++------ sys/share/unixtty.c | 49 +++++++++++++++++++++++++++++++--- sys/unix/unixmain.c | 28 +++++++++++++------ sys/unix/unixunix.c | 31 +++++++++++++++------ win/tty/wintty.c | 74 +++++++++++++++++++++++++++++++++++++++++++ ++++++++ 8 files changed, 192 insertions(+), 32 deletions(-) diff --git a/include/config.h b/include/config.h index 376bdea..99a39ba 100644 --- a/include/config.h +++ b/include/config.h @@ -48,6 +48,9 @@ /* #define GNOME_GRAPHICS */ /* Gnome interface */ /* #define MSWIN_GRAPHICS */ /* Windows NT, CE, Graphics */ +/* Define to display IBMgraphics via UTF-8 */ +#define UNICODE + /* * Define the default window system. This should be one that is compiled * into your system (see defines above). Known window systems are: diff --git a/src/drawing.c b/src/drawing.c index da39614..96e91d9 100644 --- a/src/drawing.c +++ b/src/drawing.c @@ -741,10 +741,15 @@ static const uchar r_oc_syms[MAXOCLASSES] = { static const uchar IBM_r_oc_syms[MAXOCLASSES] = { /* a la EPYX Rogue */ /* 0*/ '\0', ILLOBJ_SYM, -# if defined(MSDOS) || defined(OS2) || ( defined(WIN32) && !defined(MSWIN_GRAPHICS) ) +# if defined(UNICODE) || defined(MSDOS) || defined(OS2) || ( defined(WIN32) && !defined(MSWIN_GRAPHICS) ) 0x18, /* weapon: up arrow */ +# ifdef UNICODE + 0x0a, /* armor: Vert rect with o */ + 0x0b, /* ring: circle with arrow */ +# else /* 0x0a, */ ARMOR_SYM, /* armor: Vert rect with o */ /* 0x09, */ RING_SYM, /* ring: circle with arrow */ +# endif /* 5*/ 0x0c, /* amulet: "female" symbol */ TOOL_SYM, 0x05, /* food: club (as in cards) */ diff --git a/src/mapglyph.c b/src/mapglyph.c index 92fbd17..66e2b93 100644 --- a/src/mapglyph.c +++ b/src/mapglyph.c @@ -3,6 +3,7 @@ /* NetHack may be freely redistributed. See license for details. */ #include "hack.h" +#include "tcap.h" #if defined(TTY_GRAPHICS) #include "wintty.h" /* for prototype of has_color() only */ #endif diff --git a/sys/share/ioctl.c b/sys/share/ioctl.c index 8349281..fee4a5d 100644 --- a/sys/share/ioctl.c +++ b/sys/share/ioctl.c @@ -68,13 +68,18 @@ struct termio termio; #include "tcap.h" /* for LI and CO */ #endif -#ifdef _M_UNIX +#ifdef UNICODE +extern void NDECL(utf8_mapon); +extern void NDECL(utf8_mapoff); +#else +# ifdef _M_UNIX extern void NDECL(sco_mapon); extern void NDECL(sco_mapoff); -#endif -#ifdef __linux__ +# endif +# ifdef __linux__ extern void NDECL(linux_mapon); extern void NDECL(linux_mapoff); +# endif #endif #ifdef AUX @@ -157,11 +162,15 @@ dosuspend() # ifdef SIGTSTP if(signal(SIGTSTP, SIG_IGN) == SIG_DFL) { suspend_nhwindows((char *)0); -# ifdef _M_UNIX +# ifdef UNICODE + utf8_mapon(); +# else +# ifdef _M_UNIX sco_mapon(); -# endif -# ifdef __linux__ +# endif +# ifdef __linux__ linux_mapon(); +# endif # endif (void) signal(SIGTSTP, SIG_DFL); # ifdef AUX @@ -169,11 +178,15 @@ dosuspend() # else (void) kill(0, SIGTSTP); # endif -# ifdef _M_UNIX +# ifdef UNICODE + utf8_mapoff(); +# else +# ifdef _M_UNIX sco_mapoff(); -# endif -# ifdef __linux__ +# endif +# ifdef __linux__ linux_mapoff(); +# endif # endif resume_nhwindows(); } else { diff --git a/sys/share/unixtty.c b/sys/share/unixtty.c index 05b76b4..967ff4b 100644 --- a/sys/share/unixtty.c +++ b/sys/share/unixtty.c @@ -307,7 +307,48 @@ introff() /* disable kbd interrupts if required*/ #endif } -#ifdef _M_UNIX /* SCO UNIX (3.2.4), from Andreas Arens */ +#ifdef UNICODE +void NDECL(utf8_mapon); +void NDECL(utf8_mapoff); +void NDECL(init_utf8_cons); + +void +utf8_mapon() +{ +# ifdef TTY_GRAPHICS + if (!strcmp(windowprocs.name, "tty")) { + fwrite("\033%@", 1, 3, stdout); + } +# endif +} + +void +utf8_mapoff() +{ +# ifdef TTY_GRAPHICS + if (!strcmp(windowprocs.name, "tty")) { + fwrite("\033%G", 1, 3, stdout); + } +# endif +} + +void +init_utf8_cons() +{ +# ifdef TTY_GRAPHICS + if (!strcmp(windowprocs.name, "tty")) { + atexit(utf8_mapon); + utf8_mapoff(); +# ifdef TEXTCOLOR + if (has_colors()) + iflags.use_color = TRUE; +# endif + } +# endif +} +#endif + +#if defined(_M_UNIX) && !defined(UNICODE) /* SCO UNIX (3.2.4), from Andreas Arens */ # include <sys/console.h> # define BSIZE (E_TABSZ*2) @@ -373,10 +414,10 @@ init_sco_cons() } # endif } -#endif /* _M_UNIX */ +#endif /* _M_UNIX && !UNICODE */ -#ifdef __linux__ /* via Jesse Thilo and Ben Gertzfield */ +#if defined(__linux__) && !defined(UNICODE) /* via Jesse Thilo and Ben Gertzfield */ # include <sys/vt.h> int linux_flag_console = 0; @@ -430,7 +471,7 @@ init_linux_cons() } # endif } -#endif /* __linux__ */ +#endif /* __linux__ && !UNICODE */ #ifndef __begui__ /* the Be GUI will define its own error proc */ diff --git a/sys/unix/unixmain.c b/sys/unix/unixmain.c index a13514f..fe1a488 100644 --- a/sys/unix/unixmain.c +++ b/sys/unix/unixmain.c @@ -30,13 +30,17 @@ static void FDECL(chdirx, (const char *,BOOLEAN_P)); static boolean NDECL(whoami); static void FDECL(process_options, (int, char **)); -#ifdef _M_UNIX +#ifdef UNICODE +extern void NDECL(init_utf8_cons); +#else +# ifdef _M_UNIX extern void NDECL(check_sco_console); extern void NDECL(init_sco_cons); -#endif -#ifdef __linux__ +# endif +# ifdef __linux__ extern void NDECL(check_linux_console); extern void NDECL(init_linux_cons); +# endif #endif static void NDECL(wd_message); @@ -143,20 +147,26 @@ char *argv[]; chdirx(dir,1); #endif -#ifdef _M_UNIX +#ifndef UNICODE +# ifdef _M_UNIX check_sco_console(); -#endif -#ifdef __linux__ +# endif +# ifdef __linux__ check_linux_console(); +# endif #endif initoptions(); init_nhwindows(&argc,argv); exact_username = whoami(); -#ifdef _M_UNIX +#ifdef UNICODE + init_utf8_cons(); +#else +# ifdef _M_UNIX init_sco_cons(); -#endif -#ifdef __linux__ +# endif +# ifdef __linux__ init_linux_cons(); +# endif #endif /* diff --git a/sys/unix/unixunix.c b/sys/unix/unixunix.c index c2f84eb..b3b55c7 100644 --- a/sys/unix/unixunix.c +++ b/sys/unix/unixunix.c @@ -13,13 +13,18 @@ #endif #include <signal.h> -#ifdef _M_UNIX +#ifdef UNICODE +extern void NDECL(utf8_mapon); +extern void NDECL(utf8_mapoff); +#else +# ifdef _M_UNIX extern void NDECL(sco_mapon); extern void NDECL(sco_mapoff); -#endif -#ifdef __linux__ +# endif +# ifdef __linux__ extern void NDECL(linux_mapon); extern void NDECL(linux_mapoff); +# endif #endif #ifndef NHSTDC @@ -258,11 +263,15 @@ int wt; { register int f; suspend_nhwindows((char *)0); /* also calls end_screen() */ -#ifdef _M_UNIX +#ifdef UNICODE + utf8_mapon(); +#else +# ifdef _M_UNIX sco_mapon(); -#endif -#ifdef __linux__ +# endif +# ifdef __linux__ linux_mapon(); +# endif #endif if((f = fork()) == 0){ /* child */ (void) setgid(getgid()); @@ -280,11 +289,15 @@ int wt; (void) signal(SIGINT,SIG_IGN); (void) signal(SIGQUIT,SIG_IGN); (void) wait( (int *) 0); -#ifdef _M_UNIX +#ifdef UNICODE + utf8_mapoff(); +#else +# ifdef _M_UNIX sco_mapoff(); -#endif -#ifdef __linux__ +# endif +# ifdef __linux__ linux_mapoff(); +# endif #endif (void) signal(SIGINT, (SIG_RET_TYPE) done1); #ifdef WIZARD diff --git a/win/tty/wintty.c b/win/tty/wintty.c index 9cba7d7..a8605b9 100644 --- a/win/tty/wintty.c +++ b/win/tty/wintty.c @@ -25,6 +25,10 @@ extern void msmsg(const char *,...); # endif #endif +#ifdef UNICODE +static void FDECL (put_utf8, (int)); +#endif + #ifndef NO_TERMS #include "tcap.h" @@ -1709,7 +1713,11 @@ tty_putsym(window, x, y, ch) case NHW_MAP: case NHW_BASE: tty_curs(window, x, y); +#ifdef UNICODE + put_utf8(ch); /* To print the currency symbol on the Rogue level */ +#else (void) putchar(ch); +#endif ttyDisplay->curx++; cw->curx++; break; @@ -2320,6 +2328,67 @@ end_glyphout() #endif } +#ifdef UNICODE +static void +put_utf8(ch) +int ch; +{ + /* CP437 to Unicode mapping according to the Unicode Consortium */ + static ushort cp437[] = + { + 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 + }; + ushort code; + + /* Convert selected code to UTF-8 */ + code = cp437[ch & 0xFF]; + if (code < 0x80) { + putchar(code); + } + else if (code < 0x0800) { + putchar(0xC0 | ((code>> 6) & 0x1F)); + putchar(0x80 | ( code & 0x3F)); + } + else { + putchar(0xE0 | ((code>>12) & 0x1F)); + putchar(0x80 | ((code>> 6) & 0x3F)); + putchar(0x80 | ( code & 0x3F)); + } +} +# endif + + #ifndef WIN32 void g_putch(in_ch) @@ -2330,7 +2399,12 @@ int in_ch; # if defined(ASCIIGRAPH) && !defined(NO_TERMS) if (iflags.IBMgraphics || iflags.eight_bit_tty) { /* IBM-compatible displays don't need other stuff */ +# ifdef UNICODE + /* IBM graphics via UTF-8 */ + put_utf8(ch); +# else (void) putchar(ch); +# endif } else if (ch & 0x80) { if (!GFlag || HE_resets_AS) { graph_on(); -- 1.6.0.4