tUse UTF-8 for output in text-mode Windows client - vaccinewars - be a doctor a… | |
git clone git://src.adamsgaard.dk/vaccinewars | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
commit 4f094716ada1246cf9fb320593932bcd68526cd3 | |
parent 94c1db7f281d242555fb3345ce192e1d4a0068db | |
Author: Ben Webb <[email protected]> | |
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(-) | |
--- | |
diff --git a/src/curses_client/curses_client.c b/src/curses_client/curses_clien… | |
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; | |
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@ | |
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) | |
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); | |