tUse UTF-8 for output in text-mode Windows client - vaccinewars - be a doctor and try to vaccinate the world
(HTM) git clone git://src.adamsgaard.dk/vaccinewars
(DIR) Log
(DIR) Files
(DIR) Refs
(DIR) README
(DIR) LICENSE
---
(DIR) commit 4f094716ada1246cf9fb320593932bcd68526cd3
(DIR) parent 94c1db7f281d242555fb3345ce192e1d4a0068db
(HTM) Author: Ben Webb <ben@salilab.org>
Date: Sun, 15 Nov 2020 00:18:49 -0800
Use UTF-8 for output in text-mode Windows client
Make our Windows curses-like interface work with
UTF-8 text, using Windows Unicode APIs for the actual
output. This should make accented characters, in the
various non-English translations, show up correctly
regardless of which code page is set. Closes #50.
Diffstat:
M src/curses_client/curses_client.c | 7 +++++++
M src/cursesport/Makefile.am | 2 +-
M src/cursesport/cursesport.c | 47 +++++++++++++++++++++++--------
M src/cursesport/cursesport.h | 28 ++++++++++++++--------------
4 files changed, 58 insertions(+), 26 deletions(-)
---
(DIR) diff --git a/src/curses_client/curses_client.c b/src/curses_client/curses_client.c
t@@ -2650,6 +2650,13 @@ void CursesLoop(struct CMDLINE *cmdline)
char c;
Player *Play;
+#ifdef CYGWIN
+ /* On Windows, force UTF-8 rather than the non-Unicode codepage */
+ bind_textdomain_codeset(PACKAGE, "UTF-8");
+ Conv_SetInternalCodeset("UTF-8");
+ WantUTF8Errors(TRUE);
+#endif
+
InitConfiguration(cmdline);
if (!CheckHighScoreFileConfig())
return;
(DIR) diff --git a/src/cursesport/Makefile.am b/src/cursesport/Makefile.am
t@@ -1,4 +1,4 @@
noinst_LIBRARIES = libcursesport.a
libcursesport_a_SOURCES = cursesport.c cursesport.h
-AM_CPPFLAGS= -I../../intl -I${srcdir} -I${srcdir}/.. -I../..
+AM_CPPFLAGS= -I../../intl -I${srcdir} -I${srcdir}/.. -I../.. @GLIB_CFLAGS@
DEFS = @DEFS@
(DIR) diff --git a/src/cursesport/cursesport.c b/src/cursesport/cursesport.c
t@@ -26,6 +26,7 @@
#endif
#include "cursesport.h"
+#include <glib.h>
#ifdef CYGWIN /* Code for native Win32 build under Cygwin */
t@@ -34,7 +35,7 @@ int COLS, LINES;
static int Width, Depth;
static CHAR_INFO RealScreen[25][80], VirtualScreen[25][80];
static HANDLE hOut, hIn;
-static WORD CurAttr = 0;
+static int CurAttr = 0;
static int CurX, CurY;
static WORD Attr[10];
t@@ -57,8 +58,8 @@ void refresh(void)
screenpos.Top = y;
screenpos.Right = Width - 1;
screenpos.Bottom = y;
- WriteConsoleOutput(hOut, &VirtualScreen[y][0], size,
- offset, &screenpos);
+ WriteConsoleOutputW(hOut, &VirtualScreen[y][0], size,
+ offset, &screenpos);
}
}
}
t@@ -81,7 +82,7 @@ SCREEN *newterm(void *a, void *b, void *c)
Width = COLS = 80;
Depth = LINES = 25;
- CurAttr = 1 << 8;
+ CurAttr = 1 << 16;
CurX = 0;
CurY = 0;
for (i = 0; i < 10; i++)
t@@ -181,7 +182,7 @@ void move(int y, int x)
SetConsoleCursorPosition(hOut, coord);
}
-void attrset(WORD newAttr)
+void attrset(int newAttr)
{
CurAttr = newAttr;
}
t@@ -189,21 +190,45 @@ void attrset(WORD newAttr)
void addstr(const char *str)
{
int i;
-
for (i = 0; i < strlen(str); i++)
- addch(str[i]);
+ addch((guchar)str[i]);
}
-void addch(int ch)
+void addch(unsigned ch_and_attr)
{
int attr;
+ unsigned int ch;
+ gunichar gch;
+ /* Keep track of a UTF-8-encoded character */
+ static char utf8_str[4];
+ static int utf8_width = 0;
+ static int utf8_pos = 0;
+
+ ch = ch_and_attr & 0xFFFF;
+
+ if (ch > 0xFF || ch <= 0x7F) {
+ /* Already Unicode (e.g. box-drawing character), or ASCII */
+ VirtualScreen[CurY][CurX].Char.UnicodeChar = ch;
+ } else if (ch & 64) {
+ /* UTF-8 encoded; first byte (get the width) */
+ utf8_width = ch & 16 ? 4 : ch & 32 ? 3 : 2;
+ utf8_pos = 0;
+ utf8_str[utf8_pos++] = ch;
+ return;
+ } else {
+ /* UTF-8 encoded; intermediate or last byte */
+ utf8_str[utf8_pos++] = ch;
+ if (utf8_pos < utf8_width) return;
+ gch = g_utf8_get_char(utf8_str);
+ /* Windows console can only handle 2-byte Unicode */
+ VirtualScreen[CurY][CurX].Char.UnicodeChar = gch > 0xFFFF ? '?' : gch;
+ }
- VirtualScreen[CurY][CurX].Char.AsciiChar = ch % 256;
- attr = ch >> 8;
+ attr = ch_and_attr >> 16;
if (attr > 0)
VirtualScreen[CurY][CurX].Attributes = Attr[attr];
else
- VirtualScreen[CurY][CurX].Attributes = Attr[CurAttr >> 8];
+ VirtualScreen[CurY][CurX].Attributes = Attr[CurAttr >> 16];
if (++CurX >= Width) {
CurX = 0;
if (++CurY >= Depth)
(DIR) diff --git a/src/cursesport/cursesport.h b/src/cursesport/cursesport.h
t@@ -44,18 +44,18 @@ extern int COLS, LINES;
#define COLOR_BLUE 4
#define COLOR_RED 5
-#define COLOR_PAIR(i) ((i) << 8)
-
-#define ACS_VLINE 179
-#define ACS_ULCORNER 218
-#define ACS_HLINE 196
-#define ACS_URCORNER 191
-#define ACS_TTEE 194
-#define ACS_LLCORNER 192
-#define ACS_LRCORNER 217
-#define ACS_BTEE 193
-#define ACS_LTEE 195
-#define ACS_RTEE 180
+#define COLOR_PAIR(i) ((i) << 16)
+
+#define ACS_VLINE 0x2502
+#define ACS_ULCORNER 0x250c
+#define ACS_HLINE 0x2500
+#define ACS_URCORNER 0x2510
+#define ACS_TTEE 0x252c
+#define ACS_LLCORNER 0x2514
+#define ACS_LRCORNER 0x2518
+#define ACS_BTEE 0x2534
+#define ACS_LTEE 0x251c
+#define ACS_RTEE 0x2524
typedef int SCREEN;
t@@ -77,9 +77,9 @@ void keypad(void *, char);
void curs_set(BOOL visible);
void endwin(void);
void move(int y, int x);
-void attrset(WORD newAttr);
+void attrset(int newAttr);
void addstr(const char *str);
-void addch(int ch);
+void addch(unsigned ch);
void mvaddstr(int x, int y, const char *str);
void mvaddch(int x, int y, int ch);