diff --git a/src/syncterm/conn_conpty.c b/src/syncterm/conn_conpty.c index ada7a910f715453a86558dc4d7d47a9875a5e898..af4e72e73e17fa00d6656f61e36bd107e79d7332 100644 --- a/src/syncterm/conn_conpty.c +++ b/src/syncterm/conn_conpty.c @@ -1,5 +1,6 @@ #define WIN32_LEAN_AND_MEAN #include <stdatomic.h> +#include <stdbool.h> #include <windows.h> #include <wincon.h> @@ -7,23 +8,59 @@ #include "bbslist.h" #include "conn.h" +#include "fonts.h" #include "uifcinit.h" #include "window.h" HANDLE inputRead, inputWrite, outputRead, outputWrite; PROCESS_INFORMATION pi; HPCON cpty; +enum ciolib_codepage codepage; static atomic_bool terminate; +static size_t +get_utf8_span(const uint8_t *b, size_t sz) +{ + size_t ret = 0; + const uint8_t *last = &b[sz - 1]; + + while (b <= last) { + if ((*b & 0x80) == 0) { + ret++; + b++; + } + else if ((*b & 0xe0) == 0xc0) { + b+= 2; + if ((b + 1) <= (last)) + ret += 2; + } + else if ((*b & 0xf0) == 0xe0) { + b+= 3; + if ((b + 2) <= (last)) + ret += 3; + } + else if ((*b & 0xf8) == 0xf0) { + b+= 4; + if ((b + 3) <= (last)) + ret += 4; + } + else + return SIZE_MAX; + } + return ret; +} + static void conpty_input_thread(void *args) { DWORD rd; - int buffered; + size_t buffered; size_t buffer; int i; DWORD ec; + size_t fill = 0; + size_t utf8_span = 0; SetThreadName("PTY Input"); conn_api.input_thread_running = 1; @@ -35,16 +72,28 @@ conpty_input_thread(void *args) else { break; } - if (!ReadFile(outputRead, conn_api.rd_buf, conn_api.rd_buf_size, &rd, NULL)) { + if (!ReadFile(outputRead, conn_api.rd_buf + fill, conn_api.rd_buf_size - fill, &rd, NULL)) { break; } + fill += rd; + utf8_span = get_utf8_span(conn_api.rd_buf, fill); + if (utf8_span == SIZE_MAX) + break; + size_t sz; + char *cps = utf8_to_cp(codepage, conn_api.rd_buf, '?', utf8_span, &sz); + if (cps == NULL) + break; buffered = 0; - while (!terminate && !conn_api.terminate && buffered < rd) { + while (!terminate && !conn_api.terminate && buffered < sz) { pthread_mutex_lock(&(conn_inbuf.mutex)); - buffer = conn_buf_wait_free(&conn_inbuf, rd - buffered, 100); - buffered += conn_buf_put(&conn_inbuf, conn_api.rd_buf + buffered, buffer); + buffer = conn_buf_wait_free(&conn_inbuf, sz - buffered, 100); + buffered += conn_buf_put(&conn_inbuf, cps + buffered, buffer); pthread_mutex_unlock(&(conn_inbuf.mutex)); } + fill -= utf8_span; + if (fill) + memmove(conn_api.rd_buf, &conn_api.rd_buf[utf8_span], fill); + free(cps); } terminate = true; conn_api.input_thread_running = 2; @@ -55,7 +104,6 @@ conpty_output_thread(void *args) { int wr; DWORD ret; - int sent; DWORD ec; SetThreadName("PTY Output"); @@ -74,19 +122,25 @@ conpty_output_thread(void *args) if (wr) { wr = conn_buf_get(&conn_outbuf, conn_api.wr_buf, conn_api.wr_buf_size); pthread_mutex_unlock(&(conn_outbuf.mutex)); - sent = 0; - while (!terminate && !conn_api.terminate && sent < wr) { - if (!WriteFile(inputWrite, conn_api.wr_buf + sent, wr - sent, &ret, NULL)) { + size_t sz; + uint8_t *utf = cp_to_utf8(codepage, conn_api.wr_buf, wr, &sz); + if (utf == NULL) + break; + size_t sent = 0; + while (!terminate && !conn_api.terminate && sent < sz) { + if (!WriteFile(inputWrite, utf + sent, sz - sent, &ret, NULL)) { terminate = true; break; } sent += ret; } + free(utf); } else { pthread_mutex_unlock(&(conn_outbuf.mutex)); } } + terminate = true; conn_api.output_thread_running = 2; } @@ -96,6 +150,7 @@ int conpty_connect(struct bbslist *bbs) int w, h; get_term_win_size(&w, &h, NULL, NULL, &bbs->nostatus); + codepage = conio_fontdata[find_font_id(bbs->font)].cp; COORD size = { .X = w,