summaryrefslogtreecommitdiff
path: root/ext/io/console
diff options
context:
space:
mode:
authorNobuyoshi Nakada <nobu@ruby-lang.org>2019-09-26 09:54:24 +0900
committerNobuyoshi Nakada <nobu@ruby-lang.org>2019-09-26 09:59:27 +0900
commit5357ceb1ca454e2b3c5c173c638054cf705e4752 (patch)
tree4248d6b3a291991c851c2ecfc23e9cd3c7557bd8 /ext/io/console
parent9b106987050b06e3495e6ec5d3da152557fad8a0 (diff)
[ruby/io-console] Defer creating VT query string
https://github.com/ruby/io-console/commit/3d69c577a4
Diffstat (limited to 'ext/io/console')
-rw-r--r--ext/io/console/console.c32
1 files changed, 23 insertions, 9 deletions
diff --git a/ext/io/console/console.c b/ext/io/console/console.c
index d6896542686..4f0470940ac 100644
--- a/ext/io/console/console.c
+++ b/ext/io/console/console.c
@@ -1151,8 +1151,13 @@ console_key_pressed_p(VALUE io, VALUE k)
return GetKeyState(vk) & 0x80 ? Qtrue : Qfalse;
}
#else
+struct query_args {
+ const char *qstr;
+ int opt;
+};
+
static int
-direct_query(VALUE io, VALUE query)
+direct_query(VALUE io, const struct query_args *query)
{
if (RB_TYPE_P(io, T_FILE)) {
rb_io_t *fptr;
@@ -1160,15 +1165,16 @@ direct_query(VALUE io, VALUE query)
GetOpenFile(io, fptr);
wio = fptr->tied_io_for_writing;
if (wio) {
- rb_io_write(wio, query);
+ VALUE s = rb_str_new_cstr(query->qstr);
+ rb_io_write(wio, s);
rb_io_flush(wio);
return 1;
}
- if (write(fptr->fd, RSTRING_PTR(query), RSTRING_LEN(query)) != -1) {
+ if (write(fptr->fd, query->qstr, strlen(query->qstr)) != -1) {
return 1;
}
if (fptr->fd == 0 &&
- write(1, RSTRING_PTR(query), RSTRING_LEN(query)) != -1) {
+ write(1, query->qstr, strlen(query->qstr)) != -1) {
return 1;
}
}
@@ -1178,9 +1184,14 @@ direct_query(VALUE io, VALUE query)
static VALUE
read_vt_response(VALUE io, VALUE query)
{
+ struct query_args *qargs = (struct query_args *)query;
VALUE result, b;
+ int opt = 0;
int num = 0;
- if (!NIL_P(query) && !direct_query(io, query)) return Qnil;
+ if (qargs) {
+ opt = qargs->opt;
+ if (!direct_query(io, qargs)) return Qnil;
+ }
if (rb_io_getbyte(io) != INT2FIX(0x1b)) return Qnil;
if (rb_io_getbyte(io) != INT2FIX('[')) return Qnil;
result = rb_ary_new();
@@ -1193,6 +1204,9 @@ read_vt_response(VALUE io, VALUE query)
else if (ISDIGIT(c)) {
num = num * 10 + c - '0';
}
+ else if (opt && c == opt) {
+ opt = 0;
+ }
else {
char last = (char)c;
rb_ary_push(result, INT2NUM(num));
@@ -1204,10 +1218,10 @@ read_vt_response(VALUE io, VALUE query)
}
static VALUE
-console_vt_response(int argc, VALUE *argv, VALUE io)
+console_vt_response(int argc, VALUE *argv, VALUE io, const struct query_args *qargs)
{
rawmode_arg_t opts, *optp = rawmode_opt(&argc, argv, 0, 1, &opts);
- VALUE query = argc ? argv[0] : Qnil;
+ VALUE query = (VALUE)qargs;
VALUE ret = ttymode_with_io(io, read_vt_response, query, set_rawmode, optp);
return ret;
}
@@ -1215,8 +1229,8 @@ console_vt_response(int argc, VALUE *argv, VALUE io)
static VALUE
console_cursor_pos(VALUE io)
{
- VALUE query = rb_str_new_cstr("\033[6n");
- VALUE resp = console_vt_response(1, &query, io);
+ static const struct query_args query = {"\033[6n", 0};
+ VALUE resp = console_vt_response(0, 0, io, &query);
VALUE row, column, term;
unsigned int r, c;
if (!RB_TYPE_P(resp, T_ARRAY) || RARRAY_LEN(resp) != 3) return Qnil;