From 9374bfe37ed5df4ce029510c45313f1ee3e2354c Mon Sep 17 00:00:00 2001 From: rswindell <> Date: Wed, 10 Jul 2019 00:08:29 +0000 Subject: [PATCH] New @-code to output a UNICODE character. 3 different syntaxes: @U+<codepoint-in-hex>@ - automatic CP437 fallback char, if available @U+<codepoint-in-hex|cp437char-in-hex>, specify CP437 fallback char @U+<codepoint-in-hex!cp437char-in-hex>, specify CP437 fallback char (used if no automatic fallback mapping is available) --- src/sbbs3/atcodes.cpp | 23 +++++++++++++++++++++- src/sbbs3/con_out.cpp | 45 +++++++++++++++++++++++++++++++------------ src/sbbs3/sbbs.h | 2 ++ 3 files changed, 57 insertions(+), 13 deletions(-) diff --git a/src/sbbs3/atcodes.cpp b/src/sbbs3/atcodes.cpp index de46a39726..aeddf77812 100644 --- a/src/sbbs3/atcodes.cpp +++ b/src/sbbs3/atcodes.cpp @@ -36,6 +36,8 @@ #include "sbbs.h" #include "cmdshell.h" +#include "utf8.h" +#include "unicode.h" #if defined(_WINSOCKAPI_) extern WSADATA WSAData; @@ -128,7 +130,7 @@ int sbbs_t::show_atcode(const char *instr) const char* sbbs_t::atcode(char* sp, char* str, size_t maxlen) { - char* tp; + char* tp = NULL; uint i; uint ugrp; uint usub; @@ -139,6 +141,25 @@ const char* sbbs_t::atcode(char* sp, char* str, size_t maxlen) str[0]=0; + if(strncmp(sp, "U+", 2) == 0) { // UNICODE + enum unicode_codepoint codepoint = (enum unicode_codepoint)strtoul(sp + 2, &tp, 16); + if(tp == NULL || *tp ==0) + outchar(codepoint, unicode_to_cp437(codepoint)); + else { + char fallback = (char)strtoul(tp + 1, NULL, 16); + if(*tp == '|') + outchar(codepoint, fallback); + else if(*tp == '!') { + char ch = unicode_to_cp437(codepoint); + if(ch != 0) + fallback = ch; + outchar(codepoint, fallback); + } + else return NULL; // Invalid @-code + } + return nulstr; + } + if(!strcmp(sp,"VER")) return(VERSION); diff --git a/src/sbbs3/con_out.cpp b/src/sbbs3/con_out.cpp index 30117ef0c6..0f717979e1 100644 --- a/src/sbbs3/con_out.cpp +++ b/src/sbbs3/con_out.cpp @@ -250,7 +250,7 @@ size_t sbbs_t::utf8_to_cp437(const char* str, size_t len) outchar(*str); return sizeof(char); } - uint32_t codepoint = 0; + enum unicode_codepoint codepoint = UNICODE_UNDEFINED; len = utf8_getc(str, len, &codepoint); if((int)len < 2) { lprintf(LOG_NOTICE, "Invalid UTF-8 sequence: %02X (error = %d)", (uchar)*str, (int)len); @@ -266,7 +266,7 @@ size_t sbbs_t::utf8_to_cp437(const char* str, size_t len) char ch = unicode_to_cp437(codepoint); if(ch) outchar(ch); - else if(!unicode_is_zerowidth(codepoint)) { + else if(unicode_width(codepoint) > 0) { outchar(CP437_CHAR_INVERTED_QUESTION_MARK); char seq[32] = ""; for(size_t i = 0; i < len; i++) @@ -301,7 +301,7 @@ int sbbs_t::rputs(const char *str, size_t len) else if((term&NO_EXASCII) && (ch&0x80)) ch = exascii_to_ascii_char(ch); /* seven bit table */ else if(term&UTF8) { - uint32_t codepoint = cp437_unicode_tbl[(uchar)ch]; + enum unicode_codepoint codepoint = cp437_unicode_tbl[(uchar)ch]; if(codepoint != 0) utf8_putc(utf8, sizeof(utf8) - 1, codepoint); } @@ -451,7 +451,7 @@ int sbbs_t::outchar(char ch) if((term&NO_EXASCII) && (ch&0x80)) ch = exascii_to_ascii_char(ch); /* seven bit table */ else if(term&UTF8) { - uint32_t codepoint = cp437_unicode_tbl[(uchar)ch]; + enum unicode_codepoint codepoint = cp437_unicode_tbl[(uchar)ch]; if(codepoint != 0) utf8_putc(utf8, sizeof(utf8) - 1, codepoint); } @@ -541,14 +541,7 @@ int sbbs_t::outchar(char ch) column=0; break; default: - column++; - if(column >= cols) { // assume terminal has/will auto-line-wrap - lncntr++; - lbuflen = 0; - tos = 0; - lastlinelen = column; - column = 0; - } + inc_column(1); if(!lbuflen) latr=curatr; if(lbuflen<LINE_BUFSIZE) @@ -567,6 +560,34 @@ int sbbs_t::outchar(char ch) return 0; } +int sbbs_t::outchar(enum unicode_codepoint codepoint, char cp437_fallback) +{ + if(term_supports(UTF8)) { + char str[UTF8_MAX_LEN]; + int len = utf8_putc(str, sizeof(str), codepoint); + if(len < 1) + return len; + putcom(str, len); + inc_column(unicode_width(codepoint)); + return 0; + } + if(cp437_fallback == 0) + return 0; + return outchar(cp437_fallback); +} + +void sbbs_t::inc_column(int count) +{ + column += count; + if(column >= cols) { // assume terminal has/will auto-line-wrap + lncntr++; + lbuflen = 0; + tos = 0; + lastlinelen = column; + column = 0; + } +} + void sbbs_t::center(char *instr) { char str[256]; diff --git a/src/sbbs3/sbbs.h b/src/sbbs3/sbbs.h index 9c816c5701..f2efc2a181 100644 --- a/src/sbbs3/sbbs.h +++ b/src/sbbs3/sbbs.h @@ -715,6 +715,8 @@ public: ; void backspace(void); /* Output a destructive backspace via outchar */ int outchar(char ch); /* Output a char - check echo and emu. */ + int outchar(enum unicode_codepoint, char cp437_fallback = 0); + void inc_column(int count); void center(char *str); void clearline(void); void cleartoeol(void); -- GitLab