summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrobertabcd <robertabcd@63ad8ddf-47c3-0310-b6dd-a9e9d9715204>2013-03-23 01:56:10 +0800
committerrobertabcd <robertabcd@63ad8ddf-47c3-0310-b6dd-a9e9d9715204>2013-03-23 01:56:10 +0800
commit2ebc1d6719fc7d7be7415b67667ed8a78f04b0c2 (patch)
treec9dcfe9800905432c6e3845f13660c02b33d3b11
parentc124ecaf322fdfc717defe4d2af11eb398f5148c (diff)
downloadpttbbs-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.c112
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;
}
}