diff options
author | robertabcd <robertabcd@63ad8ddf-47c3-0310-b6dd-a9e9d9715204> | 2013-03-23 01:56:10 +0800 |
---|---|---|
committer | robertabcd <robertabcd@63ad8ddf-47c3-0310-b6dd-a9e9d9715204> | 2013-03-23 01:56:10 +0800 |
commit | 2ebc1d6719fc7d7be7415b67667ed8a78f04b0c2 (patch) | |
tree | c9dcfe9800905432c6e3845f13660c02b33d3b11 | |
parent | c124ecaf322fdfc717defe4d2af11eb398f5148c (diff) | |
download | pttbbs-2ebc1d6719fc7d7be7415b67667ed8a78f04b0c2.tar pttbbs-2ebc1d6719fc7d7be7415b67667ed8a78f04b0c2.tar.gz pttbbs-2ebc1d6719fc7d7be7415b67667ed8a78f04b0c2.tar.bz2 pttbbs-2ebc1d6719fc7d7be7415b67667ed8a78f04b0c2.tar.lz pttbbs-2ebc1d6719fc7d7be7415b67667ed8a78f04b0c2.tar.xz pttbbs-2ebc1d6719fc7d7be7415b67667ed8a78f04b0c2.tar.zst pttbbs-2ebc1d6719fc7d7be7415b67667ed8a78f04b0c2.zip |
boardd: UTF-8 conversion improvement.
Handle in-character ANSI color escapes.
Also add optional extended ANSI color codes to preserve information.
git-svn-id: http://opensvn.csie.org/pttbbs/trunk@5820 63ad8ddf-47c3-0310-b6dd-a9e9d9715204
-rw-r--r-- | pttbbs/daemon/boardd/boardd.c | 112 |
1 files changed, 108 insertions, 4 deletions
diff --git a/pttbbs/daemon/boardd/boardd.c b/pttbbs/daemon/boardd/boardd.c index e7933d6e..c372e962 100644 --- a/pttbbs/daemon/boardd/boardd.c +++ b/pttbbs/daemon/boardd/boardd.c @@ -167,6 +167,47 @@ answer_key(struct evbuffer *buf, const char *key) } } +#ifdef EXTENDED_INCHAR_ANSI +static int +move_string_end(char **buf) +{ + int n = 0; + while (**buf != '\0') { + (*buf)++; + n++; + } + return n; +} + +// Make extended ANSI control code +// fg, bg, bright are the original color code (eg. 30, 42, 1) +// provide -1 means no change +// all -1 means reset +static void +make_ext_ansi_ctrl(char *buf, int size, int fg, int bg, int bright) +{ + int sep = 0; + strncpy(buf, "\033[", size); + size -= move_string_end(&buf); + if (bright >= 0) { + snprintf(buf, size, "%s11%d", sep ? ";" : "", bright); + size -= move_string_end(&buf); + sep = 1; + } + if (fg >= 0) { + snprintf(buf, size, "%s1%d", sep ? ";" : "", fg); + size -= move_string_end(&buf); + sep = 1; + } + if (bg >= 0) { + snprintf(buf, size, "%s1%d", sep ? ";" : "", bg); + size -= move_string_end(&buf); + sep = 1; + } + snprintf(buf, size, "m"); +} +#endif + #ifdef CONVERT_TO_UTF8 // Converts given evbuffer contents to UTF-8 and returns the new buffer. @@ -175,7 +216,7 @@ answer_key(struct evbuffer *buf, const char *key) struct evbuffer * evbuffer_b2u(struct evbuffer *source) { - unsigned char c[2]; + unsigned char c[16]; int out = 0; if (evbuffer_get_length(source) == 0) @@ -194,9 +235,72 @@ evbuffer_b2u(struct evbuffer *source) out++; } else { // Big5 + int todrain = 2; + + // Handle in-character colors + int fg = -1, bg = -1, bright = -1; + int n = evbuffer_copyout(source, c, sizeof(c)); + if (n < 2) + break; + while (c[1] == '\033') { + c[n - 1] = '\0'; + + // At least have \033[m + if (n < 4 || c[2] != '[') + break; + + unsigned char *p = c + 3; + if (*p == 'm') { + // ANSI reset + fg = 7; + bg = 0; + bright = 0; + } + while (1) { + int v = (int) strtol((char *)p, (char **)&p, 10); + if (*p != 'm' && *p != ';') + break; + + if (v == 0) + bright = 0; + else if (v == 1) + bright = 1; + else if (v >= 30 && v <= 37) + fg = v; + else if (v >= 40 && v <= 47) + bg = v; + + if (*p == 'm') + break; + p++; + } + if (*p != 'm') { + // Skip malicious or unsupported codes + fg = bg = bright = -1; + break; + } else { + evbuffer_drain(source, p - c + 1); + todrain = 1; // We keep a byte on buffer, so fix offset + n = evbuffer_copyout(source, c + 1, sizeof(c) - 1); + if (n < 1) + break; + n++; + } + } +#ifdef EXTENDED_INCHAR_ANSI + // Output control codes before the Big5 character + if (fg >= 0 || bg >= 0 || bright >= 0) { + char ansicode[24]; + make_ext_ansi_ctrl(ansicode, sizeof(ansicode), fg, bg, bright); + int dlen = evbuffer_add_printf(destination, ansicode, strlen(ansicode)); + if (dlen < 0) + break; + out += dlen; + } +#endif - // Copy both bytes from source buffer - if (evbuffer_copyout(source, c, 2) != 2) + // n may be changed, check again + if (n < 2) break; uint8_t utf8[4]; @@ -207,7 +311,7 @@ evbuffer_b2u(struct evbuffer *source) break; // Remove DBCS character from source buffer - evbuffer_drain(source, 2); + evbuffer_drain(source, todrain); out += len; } } |