From 11d3f59f5afabf39cf2f80eb03b55e1d121b4ce0 Mon Sep 17 00:00:00 2001 From: rswindell <> Date: Fri, 28 Jun 2019 23:04:49 +0000 Subject: [PATCH] Initial support for UTF-8 terminals. At this time, just performs charset translation from CP437 -> UTF-8 and only when using high-level text output functions - so the output from native/DOS doors and scripts that use low-level output methods won't be translated. UTF-8 is auto-detected (only) at this time during answer (before login) by sending a ZWNBSP and checking (via ANSI) if the cursor position moved - an idea "borrowed" from Ozz Nixon (aka SqZ). This commit requires the new "encode" library (src/encode), so you may need to perform a cvs checkout to get that module! --- src/sbbs3/GNUmakefile | 9 +++++---- src/sbbs3/answer.cpp | 21 ++++++++++++++++----- src/sbbs3/con_out.cpp | 18 ++++++++++++++---- src/sbbs3/sbbsdefs.h | 3 ++- 4 files changed, 37 insertions(+), 14 deletions(-) diff --git a/src/sbbs3/GNUmakefile b/src/sbbs3/GNUmakefile index 46a3c1c562..579e2e9c95 100644 --- a/src/sbbs3/GNUmakefile +++ b/src/sbbs3/GNUmakefile @@ -105,12 +105,12 @@ else endif endif -CFLAGS += $(JS_CFLAGS) $(CRYPT_CFLAGS) $(UIFC-MT_CFLAGS) $(XPDEV-MT_CFLAGS) $(SMBLIB_CFLAGS) $(CIOLIB-MT_CFLAGS) +CFLAGS += $(JS_CFLAGS) $(CRYPT_CFLAGS) $(UIFC-MT_CFLAGS) $(XPDEV-MT_CFLAGS) $(SMBLIB_CFLAGS) $(CIOLIB-MT_CFLAGS) $(ENCODE_CFLAGS) $(HASH_CFLAGS) CFLAGS += -I../comio vpath %.c ../comio OBJS += $(MTOBJODIR)$(DIRSEP)comio_nix$(OFILE) JSDOOR_OBJS += $(MTOBJODIR)$(DIRSEP)comio_nix$(OFILE) -LDFLAGS += $(UIFC-MT_LDFLAGS) $(XPDEV-MT_LDFLAGS) $(SMBLIB_LDFLAGS) $(CIOLIB-MT_LDFLAGS) $(JS_LDFLAGS) $(CRYPT_LDFLAGS) +LDFLAGS += $(UIFC-MT_LDFLAGS) $(XPDEV-MT_LDFLAGS) $(SMBLIB_LDFLAGS) $(ENCODE_LDFLAGS) $(HASH_LDFLAGS) $(CIOLIB-MT_LDFLAGS) $(JS_LDFLAGS) $(CRYPT_LDFLAGS) # Monolithic Synchronet executable Build Rule $(SBBSMONO): $(MONO_OBJS) $(OBJS) @@ -118,9 +118,10 @@ $(SBBSMONO): $(MONO_OBJS) $(OBJS) $(QUIET)$(CXX) -o $@ $(LDFLAGS) $(MT_LDFLAGS) $(MONO_OBJS) $(OBJS) $(SBBS_LIBS) $(SMBLIB_LIBS) $(XPDEV-MT_LIBS) $(JS_LIBS) $(CRYPT_LIBS) # Synchronet BBS library Link Rule -$(SBBS): $(JS_DEPS) $(CRYPT_DEPS) $(OBJS) $(LIBS) $(EXTRA_SBBS_DEPENDS) | $(LIBODIR) +$(SBBS): $(JS_DEPS) $(CRYPT_DEPS) $(OBJS) $(LIBS) $(EXTRA_SBBS_DEPENDS) $(ENCODE_LIB) | $(LIBODIR) @echo Linking $@ - $(QUIET)$(MKSHPPLIB) $(LDFLAGS) -o $@ $(OBJS) $(SBBS_LIBS) $(SMBLIB_LIBS) $(LIBS) $(SHLIBOPTS) $(JS_LIBS) $(CRYPT_LIBS) $(XPDEV-MT_LIBS) + @echo $(ENCODE_LIB) + $(QUIET)$(MKSHPPLIB) $(LDFLAGS) -o $@ $(OBJS) $(SBBS_LIBS) $(SMBLIB_LIBS) $(LIBS) $(SHLIBOPTS) $(JS_LIBS) $(CRYPT_LIBS) $(ENCODE_LIBS) $(XPDEV-MT_LIBS) # FTP Server Link Rule $(FTPSRVR): $(MTOBJODIR)/ftpsrvr.o diff --git a/src/sbbs3/answer.cpp b/src/sbbs3/answer.cpp index c990fb058e..97e207e2f9 100644 --- a/src/sbbs3/answer.cpp +++ b/src/sbbs3/answer.cpp @@ -282,13 +282,16 @@ bool sbbs_t::answer() "\x1b[0c" /* Request CTerm version */ "\x1b[255B" /* locate cursor as far down as possible */ "\x1b[255C" /* locate cursor as far right as possible */ - "\b_" /* need a printable at this location to actually move cursor */ + "\b_" /* need a printable char at this location to actually move cursor */ "\x1b[6n" /* Get cursor position */ "\x1b[u" /* restore cursor position */ "\x1b[!_" /* RIP? */ #ifdef SUPPORT_ZUULTERM "\x1b[30;40m\xc2\x9f""Zuul.connection.write('\\x1b""Are you the gatekeeper?')\xc2\x9c" /* ZuulTerm? */ #endif + "\r" /* Move cursor left */ + "\xef\xbb\xbf" // UTF-8 Zero-width non-breaking space + "\x1b[6n" /* Get cursor position (again) */ "\x1b[0m_" /* "Normal" colors */ "\x1b[2J" /* clear screen */ "\x1b[H" /* home cursor */ @@ -340,6 +343,7 @@ bool sbbs_t::answer() char* tokenizer = NULL; char* p = strtok_r(str, "\x1b", &tokenizer); + unsigned cursor_pos_report = 0; while(p != NULL) { int x,y; @@ -347,10 +351,17 @@ bool sbbs_t::answer() SAFECOPY(terminal,"ANSI"); autoterm|=(ANSI|COLOR); if(sscanf(p, "[%u;%uR", &y, &x) == 2) { - lprintf(LOG_DEBUG,"received ANSI cursor position report: %ux%u", x, y); - /* Sanity check the coordinates in the response: */ - if(x >= TERM_COLS_MIN && x <= TERM_COLS_MAX) cols=x; - if(y >= TERM_ROWS_MIN && y <= TERM_ROWS_MAX) rows=y; + cursor_pos_report++; + lprintf(LOG_DEBUG,"received ANSI cursor position report [%u]: %ux%u" + ,cursor_pos_report, x, y); + if(cursor_pos_report == 1) { + /* Sanity check the coordinates in the response: */ + if(x >= TERM_COLS_MIN && x <= TERM_COLS_MAX) cols=x; + if(y >= TERM_ROWS_MIN && y <= TERM_ROWS_MAX) rows=y; + } else { // second report + if(x == 1) // ZWNBSP didn't move cursor + autoterm |= UTF8; + } } else if(sscanf(p, "[=67;84;101;114;109;%u;%u", &x, &y) == 2 && *lastchar(p) == 'c') { lprintf(LOG_INFO,"received CTerm version report: %u.%u", x, y); cterm_version = (x*1000) + y; diff --git a/src/sbbs3/con_out.cpp b/src/sbbs3/con_out.cpp index 5c9662e546..75c4a6666d 100644 --- a/src/sbbs3/con_out.cpp +++ b/src/sbbs3/con_out.cpp @@ -41,6 +41,7 @@ /**********************************************************************/ #include "sbbs.h" +#include "cp437_utf8_tbl.h" /****************************************************************************/ /* Outputs a NULL terminated string locally and remotely (if applicable) */ @@ -402,8 +403,13 @@ int sbbs_t::outchar(char ch) else outchar_esc=0; long term = term_supports(); - if((term&(PETSCII|NO_EXASCII)) == NO_EXASCII && ch&0x80) - ch=exascii_to_ascii_char(ch); /* seven bit table */ + const char* utf8 = NULL; + if(!(term&PETSCII)) { + if((term&NO_EXASCII) && (ch&0x80)) + ch = exascii_to_ascii_char(ch); /* seven bit table */ + else if(term&UTF8) + utf8 = cp437_utf8_tbl[(uchar)ch]; + } if(ch==FF && lncntr > 0 && !tos) { lncntr=0; @@ -452,8 +458,12 @@ int sbbs_t::outchar(char ch) outcom(PETSCII_REVERSE_OFF); if(ch == '\r' && (curatr&0xf0) != 0) // reverse video is disabled upon CR curatr >>= 4; - } else - outcom(ch); + } else { + if(utf8 != NULL) + putcom(utf8); + else + outcom(ch); + } } if(!outchar_esc) { /* Track cursor position locally */ diff --git a/src/sbbs3/sbbsdefs.h b/src/sbbs3/sbbsdefs.h index a5ea7bcd6e..c098ecda7b 100644 --- a/src/sbbs3/sbbsdefs.h +++ b/src/sbbs3/sbbsdefs.h @@ -656,8 +656,9 @@ typedef enum { /* Values for xtrn_t.event */ #define PETSCII (1L<<26) /* Commodore PET/CBM terminal */ #define SWAP_DELETE (1L<<27) /* Swap Delete and Backspace keys */ #define ICE_COLOR (1L<<28) /* Bright background color support */ +#define UTF8 (1L<<29) /* UTF-8 terminal */ -#define TERM_FLAGS (ANSI|COLOR|NO_EXASCII|RIP|WIP|HTML|CTERM_FONTS|PETSCII|SWAP_DELETE|ICE_COLOR) +#define TERM_FLAGS (ANSI|COLOR|NO_EXASCII|RIP|WIP|HTML|CTERM_FONTS|PETSCII|SWAP_DELETE|ICE_COLOR|UTF8) /* Special terminal key mappings */ #define TERM_KEY_HOME CTRL_B -- GitLab