summaryrefslogtreecommitdiff
path: root/ext/io/console
diff options
context:
space:
mode:
Diffstat (limited to 'ext/io/console')
-rw-r--r--ext/io/console/console.c53
1 files changed, 41 insertions, 12 deletions
diff --git a/ext/io/console/console.c b/ext/io/console/console.c
index 42b000fc30..e59284e434 100644
--- a/ext/io/console/console.c
+++ b/ext/io/console/console.c
@@ -175,17 +175,21 @@ set_rawmode(conmode *t, void *arg)
#elif defined _WIN32
*t = 0;
#endif
-#if defined HAVE_TERMIOS_H || defined HAVE_TERMIO_H
if (arg) {
const rawmode_arg_t *r = arg;
+#ifdef VMIN
if (r->vmin >= 0) t->c_cc[VMIN] = r->vmin;
+#endif
+#ifdef VTIME
if (r->vtime >= 0) t->c_cc[VTIME] = r->vtime;
+#endif
+#ifdef ISIG
if (r->intr) {
t->c_iflag |= BRKINT|IXON;
t->c_lflag |= ISIG|IEXTEN;
}
- }
#endif
+ }
}
static void
@@ -449,6 +453,28 @@ getc_call(VALUE io)
{
return rb_funcallv(io, id_getc, 0, 0);
}
+#else
+static VALUE
+nogvl_getch(void *p)
+{
+ int len = 0;
+ wint_t *buf = p, c = _getwch();
+
+ switch (c) {
+ case WEOF:
+ break;
+ return (VALUE)0;
+ case 0x00:
+ case 0xe0:
+ buf[len++] = c;
+ c = _getwch();
+ /* fall through */
+ default:
+ buf[len++] = c;
+ break;
+ }
+ return (VALUE)len;
+}
#endif
/*
@@ -473,6 +499,7 @@ console_getch(int argc, VALUE *argv, VALUE io)
wint_t c;
int w, len;
char buf[8];
+ wint_t wbuf[2];
struct timeval *to = NULL, tv;
GetOpenFile(io, fptr);
@@ -485,24 +512,26 @@ console_getch(int argc, VALUE *argv, VALUE io)
if (optp->vmin != 1) {
rb_warning("min option ignored");
}
+ if (optp->intr) {
+ w = rb_wait_for_single_fd(fptr->fd, RB_WAITFD_IN, to);
+ if (w < 0) rb_eof_error();
+ if (!(w & RB_WAITFD_IN)) return Qnil;
+ }
}
- w = rb_wait_for_single_fd(fptr->fd, RB_WAITFD_IN, to);
- if (w < 0) rb_eof_error();
- if (!(w & RB_WAITFD_IN)) return Qnil;
- c = _getwch();
- switch (c) {
- case WEOF:
+ len = (int)rb_thread_io_blocking_region(nogvl_getch, wbuf, fptr->fd);
+ switch (len) {
+ case 0:
return Qnil;
- case 0x00:
- case 0xe0:
- buf[0] = (char)c;
- c = _getwch();
+ case 2:
+ buf[0] = (char)wbuf[0];
+ c = wbuf[1];
len = 1;
do {
buf[len++] = (unsigned char)c;
} while ((c >>= CHAR_BIT) && len < (int)sizeof(buf));
return rb_str_new(buf, len);
default:
+ c = wbuf[0];
len = rb_uv_to_utf8(buf, c);
str = rb_utf8_str_new(buf, len);
return rb_str_conv_enc(str, NULL, rb_default_external_encoding());