From 6d733565c2df1b34c7f0b7d43d97f80f714a64b9 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Tue, 14 May 2019 14:19:15 +0900 Subject: io/console: support wide character input on Windows --- ext/io/console/console.c | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) (limited to 'ext/io') diff --git a/ext/io/console/console.c b/ext/io/console/console.c index 54ff34492e..0df67257d8 100644 --- a/ext/io/console/console.c +++ b/ext/io/console/console.c @@ -48,6 +48,7 @@ typedef struct sgttyb conmode; # endif #elif defined _WIN32 #include +#include typedef DWORD conmode; #define LAST_ERROR rb_w32_map_errno(GetLastError()) @@ -385,11 +386,13 @@ console_set_cooked(VALUE io) return io; } +#ifndef _WIN32 static VALUE getc_call(VALUE io) { return rb_funcallv(io, id_getc, 0, 0); } +#endif /* * call-seq: @@ -405,7 +408,43 @@ static VALUE console_getch(int argc, VALUE *argv, VALUE io) { rawmode_arg_t opts, *optp = rawmode_opt(argc, argv, &opts); +#ifndef _WIN32 return ttymode(io, getc_call, set_rawmode, optp); +#else + rb_io_t *fptr; + VALUE str; + wint_t c; + int w, len; + char buf[8]; + + GetOpenFile(io, fptr); + if (optp) { + rb_warning("option ignored"); + } + w = rb_wait_for_single_fd(fptr->fd, RB_WAITFD_IN, NULL); + if (w < 0) rb_eof_error(); + if (!(w & RB_WAITFD_IN)) return Qnil; + c = _getwch(); + switch (c) { + case WEOF: + return Qnil; + case 0x00: + case 0xe0: + buf[0] = (char)c; + c = _getwch(); + len = 1; + do { + buf[len++] = (unsigned char)c; + } while ((c >>= CHAR_BIT) && len < sizeof(buf)); + return rb_str_new(buf, len); + default: + len = rb_uv_to_utf8(buf, c); + str = rb_enc_str_new(0, 0, rb_default_external_encoding()); + rb_str_cat_conv_enc_opts(str, 0, buf, len, rb_utf8_encoding(), + 0, Qnil); + return str; + } +#endif } /* -- cgit v1.2.3