io-console 0.4.6 → 0.5.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/LICENSE.txt +22 -0
- data/README.md +46 -0
- data/{console.c → ext/io/console/console.c} +729 -57
- data/{extconf.rb → ext/io/console/extconf.rb} +9 -5
- data/{win32_vk.inc → ext/io/console/win32_vk.inc} +176 -185
- data/lib/{console → io/console}/size.rb +1 -1
- metadata +15 -36
- checksums.yaml.gz.sig +0 -0
- data/depend +0 -6
- data.tar.gz.sig +0 -0
- metadata.gz.sig +0 -0
@@ -4,6 +4,7 @@
|
|
4
4
|
*/
|
5
5
|
#include "ruby.h"
|
6
6
|
#include "ruby/io.h"
|
7
|
+
#include "ruby/thread.h"
|
7
8
|
|
8
9
|
#ifdef HAVE_UNISTD_H
|
9
10
|
#include <unistd.h>
|
@@ -14,12 +15,6 @@
|
|
14
15
|
#ifdef HAVE_SYS_IOCTL_H
|
15
16
|
#include <sys/ioctl.h>
|
16
17
|
#endif
|
17
|
-
#ifndef RARRAY_CONST_PTR
|
18
|
-
# define RARRAY_CONST_PTR(ary) RARRAY_PTR(ary)
|
19
|
-
#endif
|
20
|
-
#ifndef HAVE_RB_FUNCALLV
|
21
|
-
# define rb_funcallv rb_funcall2
|
22
|
-
#endif
|
23
18
|
|
24
19
|
#if defined HAVE_TERMIOS_H
|
25
20
|
# include <termios.h>
|
@@ -28,7 +23,7 @@ typedef struct termios conmode;
|
|
28
23
|
static int
|
29
24
|
setattr(int fd, conmode *t)
|
30
25
|
{
|
31
|
-
while (tcsetattr(fd,
|
26
|
+
while (tcsetattr(fd, TCSANOW, t)) {
|
32
27
|
if (errno != EINTR) return 0;
|
33
28
|
}
|
34
29
|
return 1;
|
@@ -54,6 +49,7 @@ typedef struct sgttyb conmode;
|
|
54
49
|
# endif
|
55
50
|
#elif defined _WIN32
|
56
51
|
#include <winioctl.h>
|
52
|
+
#include <conio.h>
|
57
53
|
typedef DWORD conmode;
|
58
54
|
|
59
55
|
#define LAST_ERROR rb_w32_map_errno(GetLastError())
|
@@ -79,7 +75,7 @@ getattr(int fd, conmode *t)
|
|
79
75
|
#define SET_LAST_ERROR (0)
|
80
76
|
#endif
|
81
77
|
|
82
|
-
static ID id_getc, id_console, id_close, id_min, id_time;
|
78
|
+
static ID id_getc, id_console, id_close, id_min, id_time, id_intr;
|
83
79
|
#if ENABLE_IO_GETPASS
|
84
80
|
static ID id_gets;
|
85
81
|
#endif
|
@@ -103,27 +99,40 @@ rb_f_send(int argc, VALUE *argv, VALUE recv)
|
|
103
99
|
}
|
104
100
|
#endif
|
105
101
|
|
106
|
-
#ifndef HAVE_RB_SYM2STR
|
107
|
-
# define rb_sym2str(sym) rb_id2str(SYM2ID(sym))
|
108
|
-
#endif
|
109
|
-
|
110
102
|
typedef struct {
|
111
103
|
int vmin;
|
112
104
|
int vtime;
|
105
|
+
int intr;
|
113
106
|
} rawmode_arg_t;
|
114
107
|
|
115
108
|
static rawmode_arg_t *
|
116
|
-
rawmode_opt(int
|
109
|
+
rawmode_opt(int *argcp, VALUE *argv, int min_argc, int max_argc, rawmode_arg_t *opts)
|
117
110
|
{
|
111
|
+
int argc = *argcp;
|
118
112
|
rawmode_arg_t *optp = NULL;
|
119
|
-
VALUE vopts;
|
120
|
-
|
113
|
+
VALUE vopts = Qnil;
|
114
|
+
#ifdef RB_SCAN_ARGS_PASS_CALLED_KEYWORDS
|
115
|
+
argc = rb_scan_args(argc, argv, "*:", NULL, &vopts);
|
116
|
+
#else
|
117
|
+
if (argc > min_argc) {
|
118
|
+
vopts = rb_check_hash_type(argv[argc-1]);
|
119
|
+
if (!NIL_P(vopts)) {
|
120
|
+
argv[argc-1] = vopts;
|
121
|
+
vopts = rb_extract_keywords(&argv[argc-1]);
|
122
|
+
if (!argv[argc-1]) *argcp = --argc;
|
123
|
+
if (!vopts) vopts = Qnil;
|
124
|
+
}
|
125
|
+
}
|
126
|
+
#endif
|
127
|
+
rb_check_arity(argc, min_argc, max_argc);
|
121
128
|
if (!NIL_P(vopts)) {
|
122
129
|
VALUE vmin = rb_hash_aref(vopts, ID2SYM(id_min));
|
123
130
|
VALUE vtime = rb_hash_aref(vopts, ID2SYM(id_time));
|
131
|
+
VALUE intr = rb_hash_aref(vopts, ID2SYM(id_intr));
|
124
132
|
/* default values by `stty raw` */
|
125
133
|
opts->vmin = 1;
|
126
134
|
opts->vtime = 0;
|
135
|
+
opts->intr = 0;
|
127
136
|
if (!NIL_P(vmin)) {
|
128
137
|
opts->vmin = NUM2INT(vmin);
|
129
138
|
optp = opts;
|
@@ -134,6 +143,21 @@ rawmode_opt(int argc, VALUE *argv, rawmode_arg_t *opts)
|
|
134
143
|
opts->vtime = NUM2INT(vtime);
|
135
144
|
optp = opts;
|
136
145
|
}
|
146
|
+
switch (intr) {
|
147
|
+
case Qtrue:
|
148
|
+
opts->intr = 1;
|
149
|
+
optp = opts;
|
150
|
+
break;
|
151
|
+
case Qfalse:
|
152
|
+
opts->intr = 0;
|
153
|
+
optp = opts;
|
154
|
+
break;
|
155
|
+
case Qnil:
|
156
|
+
break;
|
157
|
+
default:
|
158
|
+
rb_raise(rb_eArgError, "true or false expected as intr: %"PRIsVALUE,
|
159
|
+
intr);
|
160
|
+
}
|
137
161
|
}
|
138
162
|
return optp;
|
139
163
|
}
|
@@ -145,24 +169,36 @@ set_rawmode(conmode *t, void *arg)
|
|
145
169
|
cfmakeraw(t);
|
146
170
|
t->c_lflag &= ~(ECHOE|ECHOK);
|
147
171
|
#elif defined HAVE_TERMIOS_H || defined HAVE_TERMIO_H
|
148
|
-
t->c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
|
172
|
+
t->c_iflag &= ~(IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK|ISTRIP|INLCR|IGNCR|ICRNL|IXON|IXOFF|IXANY|IMAXBEL);
|
149
173
|
t->c_oflag &= ~OPOST;
|
150
|
-
t->c_lflag &= ~(ECHO|ECHOE|ECHOK|ECHONL|ICANON|ISIG|IEXTEN);
|
174
|
+
t->c_lflag &= ~(ECHO|ECHOE|ECHOK|ECHONL|ICANON|ISIG|IEXTEN|XCASE);
|
151
175
|
t->c_cflag &= ~(CSIZE|PARENB);
|
152
176
|
t->c_cflag |= CS8;
|
177
|
+
t->c_cc[VMIN] = 1;
|
178
|
+
t->c_cc[VTIME] = 0;
|
153
179
|
#elif defined HAVE_SGTTY_H
|
154
180
|
t->sg_flags &= ~ECHO;
|
155
181
|
t->sg_flags |= RAW;
|
156
182
|
#elif defined _WIN32
|
157
183
|
*t = 0;
|
158
184
|
#endif
|
159
|
-
#if defined HAVE_TERMIOS_H || defined HAVE_TERMIO_H
|
160
185
|
if (arg) {
|
161
186
|
const rawmode_arg_t *r = arg;
|
187
|
+
#ifdef VMIN
|
162
188
|
if (r->vmin >= 0) t->c_cc[VMIN] = r->vmin;
|
189
|
+
#endif
|
190
|
+
#ifdef VTIME
|
163
191
|
if (r->vtime >= 0) t->c_cc[VTIME] = r->vtime;
|
164
|
-
}
|
165
192
|
#endif
|
193
|
+
#ifdef ISIG
|
194
|
+
if (r->intr) {
|
195
|
+
t->c_iflag |= BRKINT;
|
196
|
+
t->c_lflag |= ISIG;
|
197
|
+
t->c_oflag |= OPOST;
|
198
|
+
}
|
199
|
+
#endif
|
200
|
+
(void)r;
|
201
|
+
}
|
166
202
|
}
|
167
203
|
|
168
204
|
static void
|
@@ -242,7 +278,7 @@ get_write_fd(const rb_io_t *fptr)
|
|
242
278
|
#define FD_PER_IO 2
|
243
279
|
|
244
280
|
static VALUE
|
245
|
-
ttymode(VALUE io, VALUE (*func)(VALUE), void (*setter)(conmode *, void *), void *arg)
|
281
|
+
ttymode(VALUE io, VALUE (*func)(VALUE), VALUE farg, void (*setter)(conmode *, void *), void *arg)
|
246
282
|
{
|
247
283
|
rb_io_t *fptr;
|
248
284
|
int status = -1;
|
@@ -273,7 +309,7 @@ ttymode(VALUE io, VALUE (*func)(VALUE), void (*setter)(conmode *, void *), void
|
|
273
309
|
}
|
274
310
|
}
|
275
311
|
if (status == 0) {
|
276
|
-
result = rb_protect(func,
|
312
|
+
result = rb_protect(func, farg, &status);
|
277
313
|
}
|
278
314
|
GetOpenFile(io, fptr);
|
279
315
|
if (fd[0] != -1 && fd[0] == GetReadFD(fptr)) {
|
@@ -297,32 +333,70 @@ ttymode(VALUE io, VALUE (*func)(VALUE), void (*setter)(conmode *, void *), void
|
|
297
333
|
return result;
|
298
334
|
}
|
299
335
|
|
336
|
+
#if !defined _WIN32
|
337
|
+
struct ttymode_callback_args {
|
338
|
+
VALUE (*func)(VALUE, VALUE);
|
339
|
+
VALUE io;
|
340
|
+
VALUE farg;
|
341
|
+
};
|
342
|
+
|
343
|
+
static VALUE
|
344
|
+
ttymode_callback(VALUE args)
|
345
|
+
{
|
346
|
+
struct ttymode_callback_args *argp = (struct ttymode_callback_args *)args;
|
347
|
+
return argp->func(argp->io, argp->farg);
|
348
|
+
}
|
349
|
+
|
350
|
+
static VALUE
|
351
|
+
ttymode_with_io(VALUE io, VALUE (*func)(VALUE, VALUE), VALUE farg, void (*setter)(conmode *, void *), void *arg)
|
352
|
+
{
|
353
|
+
struct ttymode_callback_args cargs;
|
354
|
+
cargs.func = func;
|
355
|
+
cargs.io = io;
|
356
|
+
cargs.farg = farg;
|
357
|
+
return ttymode(io, ttymode_callback, (VALUE)&cargs, setter, arg);
|
358
|
+
}
|
359
|
+
#endif
|
360
|
+
|
300
361
|
/*
|
301
362
|
* call-seq:
|
302
|
-
* io.raw(min: nil, time: nil) {|io| }
|
363
|
+
* io.raw(min: nil, time: nil, intr: nil) {|io| }
|
303
364
|
*
|
304
|
-
* Yields +self+ within raw mode.
|
365
|
+
* Yields +self+ within raw mode, and returns the result of the block.
|
305
366
|
*
|
306
367
|
* STDIN.raw(&:gets)
|
307
368
|
*
|
308
369
|
* will read and return a line without echo back and line editing.
|
309
370
|
*
|
371
|
+
* The parameter +min+ specifies the minimum number of bytes that
|
372
|
+
* should be received when a read operation is performed. (default: 1)
|
373
|
+
*
|
374
|
+
* The parameter +time+ specifies the timeout in _seconds_ with a
|
375
|
+
* precision of 1/10 of a second. (default: 0)
|
376
|
+
*
|
377
|
+
* If the parameter +intr+ is +true+, enables break, interrupt, quit,
|
378
|
+
* and suspend special characters.
|
379
|
+
*
|
380
|
+
* Refer to the manual page of termios for further details.
|
381
|
+
*
|
310
382
|
* You must require 'io/console' to use this method.
|
311
383
|
*/
|
312
384
|
static VALUE
|
313
385
|
console_raw(int argc, VALUE *argv, VALUE io)
|
314
386
|
{
|
315
|
-
rawmode_arg_t opts, *optp = rawmode_opt(argc, argv, &opts);
|
316
|
-
return ttymode(io, rb_yield, set_rawmode, optp);
|
387
|
+
rawmode_arg_t opts, *optp = rawmode_opt(&argc, argv, 0, 0, &opts);
|
388
|
+
return ttymode(io, rb_yield, io, set_rawmode, optp);
|
317
389
|
}
|
318
390
|
|
319
391
|
/*
|
320
392
|
* call-seq:
|
321
|
-
* io.raw!(min: nil, time: nil)
|
393
|
+
* io.raw!(min: nil, time: nil, intr: nil) -> io
|
394
|
+
*
|
395
|
+
* Enables raw mode, and returns +io+.
|
322
396
|
*
|
323
|
-
*
|
397
|
+
* If the terminal mode needs to be back, use <code>io.raw { ... }</code>.
|
324
398
|
*
|
325
|
-
*
|
399
|
+
* See IO#raw for details on the parameters.
|
326
400
|
*
|
327
401
|
* You must require 'io/console' to use this method.
|
328
402
|
*/
|
@@ -332,7 +406,7 @@ console_set_raw(int argc, VALUE *argv, VALUE io)
|
|
332
406
|
conmode t;
|
333
407
|
rb_io_t *fptr;
|
334
408
|
int fd;
|
335
|
-
rawmode_arg_t opts, *optp = rawmode_opt(argc, argv, &opts);
|
409
|
+
rawmode_arg_t opts, *optp = rawmode_opt(&argc, argv, 0, 0, &opts);
|
336
410
|
|
337
411
|
GetOpenFile(io, fptr);
|
338
412
|
fd = GetReadFD(fptr);
|
@@ -357,7 +431,7 @@ console_set_raw(int argc, VALUE *argv, VALUE io)
|
|
357
431
|
static VALUE
|
358
432
|
console_cooked(VALUE io)
|
359
433
|
{
|
360
|
-
return ttymode(io, rb_yield, set_cookedmode, NULL);
|
434
|
+
return ttymode(io, rb_yield, io, set_cookedmode, NULL);
|
361
435
|
}
|
362
436
|
|
363
437
|
/*
|
@@ -385,25 +459,98 @@ console_set_cooked(VALUE io)
|
|
385
459
|
return io;
|
386
460
|
}
|
387
461
|
|
462
|
+
#ifndef _WIN32
|
388
463
|
static VALUE
|
389
464
|
getc_call(VALUE io)
|
390
465
|
{
|
391
466
|
return rb_funcallv(io, id_getc, 0, 0);
|
392
467
|
}
|
468
|
+
#else
|
469
|
+
static void *
|
470
|
+
nogvl_getch(void *p)
|
471
|
+
{
|
472
|
+
int len = 0;
|
473
|
+
wint_t *buf = p, c = _getwch();
|
474
|
+
|
475
|
+
switch (c) {
|
476
|
+
case WEOF:
|
477
|
+
break;
|
478
|
+
case 0x00:
|
479
|
+
case 0xe0:
|
480
|
+
buf[len++] = c;
|
481
|
+
c = _getwch();
|
482
|
+
/* fall through */
|
483
|
+
default:
|
484
|
+
buf[len++] = c;
|
485
|
+
break;
|
486
|
+
}
|
487
|
+
return (void *)(VALUE)len;
|
488
|
+
}
|
489
|
+
#endif
|
393
490
|
|
394
491
|
/*
|
395
492
|
* call-seq:
|
396
|
-
* io.getch(min: nil, time: nil)
|
493
|
+
* io.getch(min: nil, time: nil, intr: nil) -> char
|
397
494
|
*
|
398
495
|
* Reads and returns a character in raw mode.
|
399
496
|
*
|
497
|
+
* See IO#raw for details on the parameters.
|
498
|
+
*
|
400
499
|
* You must require 'io/console' to use this method.
|
401
500
|
*/
|
402
501
|
static VALUE
|
403
502
|
console_getch(int argc, VALUE *argv, VALUE io)
|
404
503
|
{
|
405
|
-
rawmode_arg_t opts, *optp = rawmode_opt(argc, argv, &opts);
|
406
|
-
|
504
|
+
rawmode_arg_t opts, *optp = rawmode_opt(&argc, argv, 0, 0, &opts);
|
505
|
+
#ifndef _WIN32
|
506
|
+
return ttymode(io, getc_call, io, set_rawmode, optp);
|
507
|
+
#else
|
508
|
+
rb_io_t *fptr;
|
509
|
+
VALUE str;
|
510
|
+
wint_t c;
|
511
|
+
int w, len;
|
512
|
+
char buf[8];
|
513
|
+
wint_t wbuf[2];
|
514
|
+
struct timeval *to = NULL, tv;
|
515
|
+
|
516
|
+
GetOpenFile(io, fptr);
|
517
|
+
if (optp) {
|
518
|
+
if (optp->vtime) {
|
519
|
+
to = &tv;
|
520
|
+
tv.tv_sec = optp->vtime / 10;
|
521
|
+
tv.tv_usec = (optp->vtime % 10) * 100000;
|
522
|
+
}
|
523
|
+
if (optp->vmin != 1) {
|
524
|
+
rb_warning("min option ignored");
|
525
|
+
}
|
526
|
+
if (optp->intr) {
|
527
|
+
w = rb_wait_for_single_fd(fptr->fd, RB_WAITFD_IN, to);
|
528
|
+
if (w < 0) rb_eof_error();
|
529
|
+
if (!(w & RB_WAITFD_IN)) return Qnil;
|
530
|
+
}
|
531
|
+
else {
|
532
|
+
rb_warning("vtime option ignored if intr flag is unset");
|
533
|
+
}
|
534
|
+
}
|
535
|
+
len = (int)(VALUE)rb_thread_call_without_gvl(nogvl_getch, wbuf, RUBY_UBF_IO, 0);
|
536
|
+
switch (len) {
|
537
|
+
case 0:
|
538
|
+
return Qnil;
|
539
|
+
case 2:
|
540
|
+
buf[0] = (char)wbuf[0];
|
541
|
+
c = wbuf[1];
|
542
|
+
len = 1;
|
543
|
+
do {
|
544
|
+
buf[len++] = (unsigned char)c;
|
545
|
+
} while ((c >>= CHAR_BIT) && len < (int)sizeof(buf));
|
546
|
+
return rb_str_new(buf, len);
|
547
|
+
default:
|
548
|
+
c = wbuf[0];
|
549
|
+
len = rb_uv_to_utf8(buf, c);
|
550
|
+
str = rb_utf8_str_new(buf, len);
|
551
|
+
return rb_str_conv_enc(str, NULL, rb_default_external_encoding());
|
552
|
+
}
|
553
|
+
#endif
|
407
554
|
}
|
408
555
|
|
409
556
|
/*
|
@@ -421,7 +568,7 @@ console_getch(int argc, VALUE *argv, VALUE io)
|
|
421
568
|
static VALUE
|
422
569
|
console_noecho(VALUE io)
|
423
570
|
{
|
424
|
-
return ttymode(io, rb_yield, set_noecho, NULL);
|
571
|
+
return ttymode(io, rb_yield, io, set_noecho, NULL);
|
425
572
|
}
|
426
573
|
|
427
574
|
/*
|
@@ -473,6 +620,115 @@ console_echo_p(VALUE io)
|
|
473
620
|
return echo_p(&t) ? Qtrue : Qfalse;
|
474
621
|
}
|
475
622
|
|
623
|
+
static const rb_data_type_t conmode_type = {
|
624
|
+
"console-mode",
|
625
|
+
{0, RUBY_TYPED_DEFAULT_FREE,},
|
626
|
+
0, 0,
|
627
|
+
RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
|
628
|
+
};
|
629
|
+
static VALUE cConmode;
|
630
|
+
|
631
|
+
static VALUE
|
632
|
+
conmode_alloc(VALUE klass)
|
633
|
+
{
|
634
|
+
return rb_data_typed_object_zalloc(klass, sizeof(conmode), &conmode_type);
|
635
|
+
}
|
636
|
+
|
637
|
+
static VALUE
|
638
|
+
conmode_new(VALUE klass, const conmode *t)
|
639
|
+
{
|
640
|
+
VALUE obj = conmode_alloc(klass);
|
641
|
+
*(conmode *)DATA_PTR(obj) = *t;
|
642
|
+
return obj;
|
643
|
+
}
|
644
|
+
|
645
|
+
static VALUE
|
646
|
+
conmode_init_copy(VALUE obj, VALUE obj2)
|
647
|
+
{
|
648
|
+
conmode *t = rb_check_typeddata(obj, &conmode_type);
|
649
|
+
conmode *t2 = rb_check_typeddata(obj2, &conmode_type);
|
650
|
+
*t = *t2;
|
651
|
+
return obj;
|
652
|
+
}
|
653
|
+
|
654
|
+
static VALUE
|
655
|
+
conmode_set_echo(VALUE obj, VALUE f)
|
656
|
+
{
|
657
|
+
conmode *t = rb_check_typeddata(obj, &conmode_type);
|
658
|
+
if (RTEST(f))
|
659
|
+
set_echo(t, NULL);
|
660
|
+
else
|
661
|
+
set_noecho(t, NULL);
|
662
|
+
return obj;
|
663
|
+
}
|
664
|
+
|
665
|
+
static VALUE
|
666
|
+
conmode_set_raw(int argc, VALUE *argv, VALUE obj)
|
667
|
+
{
|
668
|
+
conmode *t = rb_check_typeddata(obj, &conmode_type);
|
669
|
+
rawmode_arg_t opts, *optp = rawmode_opt(&argc, argv, 0, 0, &opts);
|
670
|
+
|
671
|
+
set_rawmode(t, optp);
|
672
|
+
return obj;
|
673
|
+
}
|
674
|
+
|
675
|
+
static VALUE
|
676
|
+
conmode_raw_new(int argc, VALUE *argv, VALUE obj)
|
677
|
+
{
|
678
|
+
conmode *r = rb_check_typeddata(obj, &conmode_type);
|
679
|
+
conmode t = *r;
|
680
|
+
rawmode_arg_t opts, *optp = rawmode_opt(&argc, argv, 0, 0, &opts);
|
681
|
+
|
682
|
+
set_rawmode(&t, optp);
|
683
|
+
return conmode_new(rb_obj_class(obj), &t);
|
684
|
+
}
|
685
|
+
|
686
|
+
/*
|
687
|
+
* call-seq:
|
688
|
+
* io.console_mode -> mode
|
689
|
+
*
|
690
|
+
* Returns a data represents the current console mode.
|
691
|
+
*
|
692
|
+
* You must require 'io/console' to use this method.
|
693
|
+
*/
|
694
|
+
static VALUE
|
695
|
+
console_conmode_get(VALUE io)
|
696
|
+
{
|
697
|
+
conmode t;
|
698
|
+
rb_io_t *fptr;
|
699
|
+
int fd;
|
700
|
+
|
701
|
+
GetOpenFile(io, fptr);
|
702
|
+
fd = GetReadFD(fptr);
|
703
|
+
if (!getattr(fd, &t)) rb_sys_fail(0);
|
704
|
+
|
705
|
+
return conmode_new(cConmode, &t);
|
706
|
+
}
|
707
|
+
|
708
|
+
/*
|
709
|
+
* call-seq:
|
710
|
+
* io.console_mode = mode
|
711
|
+
*
|
712
|
+
* Sets the console mode to +mode+.
|
713
|
+
*
|
714
|
+
* You must require 'io/console' to use this method.
|
715
|
+
*/
|
716
|
+
static VALUE
|
717
|
+
console_conmode_set(VALUE io, VALUE mode)
|
718
|
+
{
|
719
|
+
conmode *t, r;
|
720
|
+
rb_io_t *fptr;
|
721
|
+
int fd;
|
722
|
+
|
723
|
+
TypedData_Get_Struct(mode, conmode, &conmode_type, t);
|
724
|
+
r = *t;
|
725
|
+
GetOpenFile(io, fptr);
|
726
|
+
fd = GetReadFD(fptr);
|
727
|
+
if (!setattr(fd, &r)) rb_sys_fail(0);
|
728
|
+
|
729
|
+
return mode;
|
730
|
+
}
|
731
|
+
|
476
732
|
#if defined TIOCGWINSZ
|
477
733
|
typedef struct winsize rb_console_size_t;
|
478
734
|
#define getwinsize(fd, buf) (ioctl((fd), TIOCGWINSZ, (buf)) == 0)
|
@@ -531,16 +787,23 @@ console_set_winsize(VALUE io, VALUE size)
|
|
531
787
|
#if defined _WIN32
|
532
788
|
HANDLE wh;
|
533
789
|
int newrow, newcol;
|
790
|
+
BOOL ret;
|
534
791
|
#endif
|
535
792
|
VALUE row, col, xpixel, ypixel;
|
536
793
|
const VALUE *sz;
|
537
794
|
int fd;
|
795
|
+
long sizelen;
|
538
796
|
|
539
797
|
GetOpenFile(io, fptr);
|
540
798
|
size = rb_Array(size);
|
541
|
-
|
799
|
+
if ((sizelen = RARRAY_LEN(size)) != 2 && sizelen != 4) {
|
800
|
+
rb_raise(rb_eArgError,
|
801
|
+
"wrong number of arguments (given %ld, expected 2 or 4)",
|
802
|
+
sizelen);
|
803
|
+
}
|
542
804
|
sz = RARRAY_CONST_PTR(size);
|
543
|
-
row = sz[0], col = sz[1], xpixel =
|
805
|
+
row = sz[0], col = sz[1], xpixel = ypixel = Qnil;
|
806
|
+
if (sizelen == 4) xpixel = sz[2], ypixel = sz[3];
|
544
807
|
fd = GetWriteFD(fptr);
|
545
808
|
#if defined TIOCSWINSZ
|
546
809
|
ws.ws_row = ws.ws_col = ws.ws_xpixel = ws.ws_ypixel = 0;
|
@@ -562,17 +825,21 @@ console_set_winsize(VALUE io, VALUE size)
|
|
562
825
|
if (!GetConsoleScreenBufferInfo(wh, &ws)) {
|
563
826
|
rb_syserr_fail(LAST_ERROR, "GetConsoleScreenBufferInfo");
|
564
827
|
}
|
565
|
-
|
566
|
-
|
567
|
-
if (!SetConsoleScreenBufferSize(wh, ws.dwSize)) {
|
568
|
-
rb_syserr_fail(LAST_ERROR, "SetConsoleScreenBufferInfo");
|
569
|
-
}
|
570
|
-
}
|
828
|
+
ws.dwSize.X = newcol;
|
829
|
+
ret = SetConsoleScreenBufferSize(wh, ws.dwSize);
|
571
830
|
ws.srWindow.Left = 0;
|
572
831
|
ws.srWindow.Top = 0;
|
573
|
-
ws.srWindow.Right = newcol;
|
574
|
-
ws.srWindow.Bottom = newrow;
|
575
|
-
if (!SetConsoleWindowInfo(wh,
|
832
|
+
ws.srWindow.Right = newcol-1;
|
833
|
+
ws.srWindow.Bottom = newrow-1;
|
834
|
+
if (!SetConsoleWindowInfo(wh, TRUE, &ws.srWindow)) {
|
835
|
+
rb_syserr_fail(LAST_ERROR, "SetConsoleWindowInfo");
|
836
|
+
}
|
837
|
+
/* retry when shrinking buffer after shrunk window */
|
838
|
+
if (!ret && !SetConsoleScreenBufferSize(wh, ws.dwSize)) {
|
839
|
+
rb_syserr_fail(LAST_ERROR, "SetConsoleScreenBufferInfo");
|
840
|
+
}
|
841
|
+
/* remove scrollbar if possible */
|
842
|
+
if (!SetConsoleWindowInfo(wh, TRUE, &ws.srWindow)) {
|
576
843
|
rb_syserr_fail(LAST_ERROR, "SetConsoleWindowInfo");
|
577
844
|
}
|
578
845
|
#endif
|
@@ -580,6 +847,30 @@ console_set_winsize(VALUE io, VALUE size)
|
|
580
847
|
}
|
581
848
|
#endif
|
582
849
|
|
850
|
+
#ifdef _WIN32
|
851
|
+
static VALUE
|
852
|
+
console_check_winsize_changed(VALUE io)
|
853
|
+
{
|
854
|
+
rb_io_t *fptr;
|
855
|
+
HANDLE h;
|
856
|
+
DWORD num;
|
857
|
+
|
858
|
+
GetOpenFile(io, fptr);
|
859
|
+
h = (HANDLE)rb_w32_get_osfhandle(GetReadFD(fptr));
|
860
|
+
while (GetNumberOfConsoleInputEvents(h, &num) && num > 0) {
|
861
|
+
INPUT_RECORD rec;
|
862
|
+
if (ReadConsoleInput(h, &rec, 1, &num)) {
|
863
|
+
if (rec.EventType == WINDOW_BUFFER_SIZE_EVENT) {
|
864
|
+
rb_yield(Qnil);
|
865
|
+
}
|
866
|
+
}
|
867
|
+
}
|
868
|
+
return io;
|
869
|
+
}
|
870
|
+
#else
|
871
|
+
#define console_check_winsize_changed rb_f_notimplement
|
872
|
+
#endif
|
873
|
+
|
583
874
|
/*
|
584
875
|
* call-seq:
|
585
876
|
* io.iflush
|
@@ -675,9 +966,24 @@ console_beep(VALUE io)
|
|
675
966
|
return io;
|
676
967
|
}
|
677
968
|
|
969
|
+
static int
|
970
|
+
mode_in_range(VALUE val, int high, const char *modename)
|
971
|
+
{
|
972
|
+
int mode;
|
973
|
+
if (NIL_P(val)) return 0;
|
974
|
+
if (!RB_INTEGER_TYPE_P(val)) {
|
975
|
+
wrong_value:
|
976
|
+
rb_raise(rb_eArgError, "wrong %s mode: %"PRIsVALUE, modename, val);
|
977
|
+
}
|
978
|
+
if ((mode = NUM2INT(val)) < 0 || mode > high) {
|
979
|
+
goto wrong_value;
|
980
|
+
}
|
981
|
+
return mode;
|
982
|
+
}
|
983
|
+
|
678
984
|
#if defined _WIN32
|
679
985
|
static VALUE
|
680
|
-
console_goto(VALUE io, VALUE
|
986
|
+
console_goto(VALUE io, VALUE y, VALUE x)
|
681
987
|
{
|
682
988
|
rb_io_t *fptr;
|
683
989
|
int fd;
|
@@ -705,15 +1011,159 @@ console_cursor_pos(VALUE io)
|
|
705
1011
|
if (!GetConsoleScreenBufferInfo((HANDLE)rb_w32_get_osfhandle(fd), &ws)) {
|
706
1012
|
rb_syserr_fail(LAST_ERROR, 0);
|
707
1013
|
}
|
708
|
-
return rb_assoc_new(UINT2NUM(ws.dwCursorPosition.
|
1014
|
+
return rb_assoc_new(UINT2NUM(ws.dwCursorPosition.Y), UINT2NUM(ws.dwCursorPosition.X));
|
709
1015
|
}
|
710
1016
|
|
711
1017
|
static VALUE
|
712
|
-
|
1018
|
+
console_move(VALUE io, int y, int x)
|
713
1019
|
{
|
714
|
-
|
715
|
-
|
716
|
-
|
1020
|
+
rb_io_t *fptr;
|
1021
|
+
HANDLE h;
|
1022
|
+
rb_console_size_t ws;
|
1023
|
+
COORD *pos = &ws.dwCursorPosition;
|
1024
|
+
|
1025
|
+
GetOpenFile(io, fptr);
|
1026
|
+
h = (HANDLE)rb_w32_get_osfhandle(GetWriteFD(fptr));
|
1027
|
+
if (!GetConsoleScreenBufferInfo(h, &ws)) {
|
1028
|
+
rb_syserr_fail(LAST_ERROR, 0);
|
1029
|
+
}
|
1030
|
+
pos->X += x;
|
1031
|
+
pos->Y += y;
|
1032
|
+
if (!SetConsoleCursorPosition(h, *pos)) {
|
1033
|
+
rb_syserr_fail(LAST_ERROR, 0);
|
1034
|
+
}
|
1035
|
+
return io;
|
1036
|
+
}
|
1037
|
+
|
1038
|
+
static VALUE
|
1039
|
+
console_goto_column(VALUE io, VALUE val)
|
1040
|
+
{
|
1041
|
+
rb_io_t *fptr;
|
1042
|
+
HANDLE h;
|
1043
|
+
rb_console_size_t ws;
|
1044
|
+
COORD *pos = &ws.dwCursorPosition;
|
1045
|
+
|
1046
|
+
GetOpenFile(io, fptr);
|
1047
|
+
h = (HANDLE)rb_w32_get_osfhandle(GetWriteFD(fptr));
|
1048
|
+
if (!GetConsoleScreenBufferInfo(h, &ws)) {
|
1049
|
+
rb_syserr_fail(LAST_ERROR, 0);
|
1050
|
+
}
|
1051
|
+
pos->X = NUM2INT(val);
|
1052
|
+
if (!SetConsoleCursorPosition(h, *pos)) {
|
1053
|
+
rb_syserr_fail(LAST_ERROR, 0);
|
1054
|
+
}
|
1055
|
+
return io;
|
1056
|
+
}
|
1057
|
+
|
1058
|
+
static void
|
1059
|
+
constat_clear(HANDLE handle, WORD attr, DWORD len, COORD pos)
|
1060
|
+
{
|
1061
|
+
DWORD written;
|
1062
|
+
|
1063
|
+
FillConsoleOutputAttribute(handle, attr, len, pos, &written);
|
1064
|
+
FillConsoleOutputCharacterW(handle, L' ', len, pos, &written);
|
1065
|
+
}
|
1066
|
+
|
1067
|
+
static VALUE
|
1068
|
+
console_erase_line(VALUE io, VALUE val)
|
1069
|
+
{
|
1070
|
+
rb_io_t *fptr;
|
1071
|
+
HANDLE h;
|
1072
|
+
rb_console_size_t ws;
|
1073
|
+
COORD *pos = &ws.dwCursorPosition;
|
1074
|
+
DWORD w;
|
1075
|
+
int mode = mode_in_range(val, 2, "line erase");
|
1076
|
+
|
1077
|
+
GetOpenFile(io, fptr);
|
1078
|
+
h = (HANDLE)rb_w32_get_osfhandle(GetWriteFD(fptr));
|
1079
|
+
if (!GetConsoleScreenBufferInfo(h, &ws)) {
|
1080
|
+
rb_syserr_fail(LAST_ERROR, 0);
|
1081
|
+
}
|
1082
|
+
w = winsize_col(&ws);
|
1083
|
+
switch (mode) {
|
1084
|
+
case 0: /* after cursor */
|
1085
|
+
w -= pos->X;
|
1086
|
+
break;
|
1087
|
+
case 1: /* before *and* cursor */
|
1088
|
+
w = pos->X + 1;
|
1089
|
+
pos->X = 0;
|
1090
|
+
break;
|
1091
|
+
case 2: /* entire line */
|
1092
|
+
pos->X = 0;
|
1093
|
+
break;
|
1094
|
+
}
|
1095
|
+
constat_clear(h, ws.wAttributes, w, *pos);
|
1096
|
+
return io;
|
1097
|
+
}
|
1098
|
+
|
1099
|
+
static VALUE
|
1100
|
+
console_erase_screen(VALUE io, VALUE val)
|
1101
|
+
{
|
1102
|
+
rb_io_t *fptr;
|
1103
|
+
HANDLE h;
|
1104
|
+
rb_console_size_t ws;
|
1105
|
+
COORD *pos = &ws.dwCursorPosition;
|
1106
|
+
DWORD w;
|
1107
|
+
int mode = mode_in_range(val, 3, "screen erase");
|
1108
|
+
|
1109
|
+
GetOpenFile(io, fptr);
|
1110
|
+
h = (HANDLE)rb_w32_get_osfhandle(GetWriteFD(fptr));
|
1111
|
+
if (!GetConsoleScreenBufferInfo(h, &ws)) {
|
1112
|
+
rb_syserr_fail(LAST_ERROR, 0);
|
1113
|
+
}
|
1114
|
+
w = winsize_col(&ws);
|
1115
|
+
switch (mode) {
|
1116
|
+
case 0: /* erase after cursor */
|
1117
|
+
w = (w * (ws.srWindow.Bottom - pos->Y + 1) - pos->X);
|
1118
|
+
break;
|
1119
|
+
case 1: /* erase before *and* cursor */
|
1120
|
+
w = (w * (pos->Y - ws.srWindow.Top) + pos->X + 1);
|
1121
|
+
pos->X = 0;
|
1122
|
+
pos->Y = ws.srWindow.Top;
|
1123
|
+
break;
|
1124
|
+
case 2: /* erase entire screen */
|
1125
|
+
w = (w * winsize_row(&ws));
|
1126
|
+
pos->X = 0;
|
1127
|
+
pos->Y = ws.srWindow.Top;
|
1128
|
+
break;
|
1129
|
+
case 3: /* erase entire screen */
|
1130
|
+
w = (w * ws.dwSize.Y);
|
1131
|
+
pos->X = 0;
|
1132
|
+
pos->Y = 0;
|
1133
|
+
break;
|
1134
|
+
}
|
1135
|
+
constat_clear(h, ws.wAttributes, w, *pos);
|
1136
|
+
return io;
|
1137
|
+
}
|
1138
|
+
|
1139
|
+
static VALUE
|
1140
|
+
console_scroll(VALUE io, int line)
|
1141
|
+
{
|
1142
|
+
rb_io_t *fptr;
|
1143
|
+
HANDLE h;
|
1144
|
+
rb_console_size_t ws;
|
1145
|
+
|
1146
|
+
GetOpenFile(io, fptr);
|
1147
|
+
h = (HANDLE)rb_w32_get_osfhandle(GetWriteFD(fptr));
|
1148
|
+
if (!GetConsoleScreenBufferInfo(h, &ws)) {
|
1149
|
+
rb_syserr_fail(LAST_ERROR, 0);
|
1150
|
+
}
|
1151
|
+
if (line) {
|
1152
|
+
SMALL_RECT scroll;
|
1153
|
+
COORD destination;
|
1154
|
+
CHAR_INFO fill;
|
1155
|
+
scroll.Left = 0;
|
1156
|
+
scroll.Top = line > 0 ? line : 0;
|
1157
|
+
scroll.Right = winsize_col(&ws) - 1;
|
1158
|
+
scroll.Bottom = winsize_row(&ws) - 1 + (line < 0 ? line : 0);
|
1159
|
+
destination.X = 0;
|
1160
|
+
destination.Y = line < 0 ? -line : 0;
|
1161
|
+
fill.Char.UnicodeChar = L' ';
|
1162
|
+
fill.Attributes = ws.wAttributes;
|
1163
|
+
|
1164
|
+
ScrollConsoleScreenBuffer(h, &scroll, NULL, destination, &fill);
|
1165
|
+
}
|
1166
|
+
return io;
|
717
1167
|
}
|
718
1168
|
|
719
1169
|
#include "win32_vk.inc"
|
@@ -744,12 +1194,210 @@ console_key_pressed_p(VALUE io, VALUE k)
|
|
744
1194
|
return GetKeyState(vk) & 0x80 ? Qtrue : Qfalse;
|
745
1195
|
}
|
746
1196
|
#else
|
747
|
-
|
748
|
-
|
749
|
-
|
1197
|
+
struct query_args {
|
1198
|
+
const char *qstr;
|
1199
|
+
int opt;
|
1200
|
+
};
|
1201
|
+
|
1202
|
+
static int
|
1203
|
+
direct_query(VALUE io, const struct query_args *query)
|
1204
|
+
{
|
1205
|
+
if (RB_TYPE_P(io, T_FILE)) {
|
1206
|
+
rb_io_t *fptr;
|
1207
|
+
VALUE wio;
|
1208
|
+
GetOpenFile(io, fptr);
|
1209
|
+
wio = fptr->tied_io_for_writing;
|
1210
|
+
if (wio) {
|
1211
|
+
VALUE s = rb_str_new_cstr(query->qstr);
|
1212
|
+
rb_io_write(wio, s);
|
1213
|
+
rb_io_flush(wio);
|
1214
|
+
return 1;
|
1215
|
+
}
|
1216
|
+
if (write(fptr->fd, query->qstr, strlen(query->qstr)) != -1) {
|
1217
|
+
return 1;
|
1218
|
+
}
|
1219
|
+
if (fptr->fd == 0 &&
|
1220
|
+
write(1, query->qstr, strlen(query->qstr)) != -1) {
|
1221
|
+
return 1;
|
1222
|
+
}
|
1223
|
+
}
|
1224
|
+
return 0;
|
1225
|
+
}
|
1226
|
+
|
1227
|
+
static VALUE
|
1228
|
+
read_vt_response(VALUE io, VALUE query)
|
1229
|
+
{
|
1230
|
+
struct query_args *qargs = (struct query_args *)query;
|
1231
|
+
VALUE result, b;
|
1232
|
+
int opt = 0;
|
1233
|
+
int num = 0;
|
1234
|
+
if (qargs) {
|
1235
|
+
opt = qargs->opt;
|
1236
|
+
if (!direct_query(io, qargs)) return Qnil;
|
1237
|
+
}
|
1238
|
+
if (rb_io_getbyte(io) != INT2FIX(0x1b)) return Qnil;
|
1239
|
+
if (rb_io_getbyte(io) != INT2FIX('[')) return Qnil;
|
1240
|
+
result = rb_ary_new();
|
1241
|
+
while (!NIL_P(b = rb_io_getbyte(io))) {
|
1242
|
+
int c = NUM2UINT(b);
|
1243
|
+
if (c == ';') {
|
1244
|
+
rb_ary_push(result, INT2NUM(num));
|
1245
|
+
num = 0;
|
1246
|
+
}
|
1247
|
+
else if (ISDIGIT(c)) {
|
1248
|
+
num = num * 10 + c - '0';
|
1249
|
+
}
|
1250
|
+
else if (opt && c == opt) {
|
1251
|
+
opt = 0;
|
1252
|
+
}
|
1253
|
+
else {
|
1254
|
+
char last = (char)c;
|
1255
|
+
rb_ary_push(result, INT2NUM(num));
|
1256
|
+
b = rb_str_new(&last, 1);
|
1257
|
+
break;
|
1258
|
+
}
|
1259
|
+
}
|
1260
|
+
return rb_ary_push(result, b);
|
1261
|
+
}
|
1262
|
+
|
1263
|
+
static VALUE
|
1264
|
+
console_vt_response(int argc, VALUE *argv, VALUE io, const struct query_args *qargs)
|
1265
|
+
{
|
1266
|
+
rawmode_arg_t opts, *optp = rawmode_opt(&argc, argv, 0, 1, &opts);
|
1267
|
+
VALUE query = (VALUE)qargs;
|
1268
|
+
VALUE ret = ttymode_with_io(io, read_vt_response, query, set_rawmode, optp);
|
1269
|
+
return ret;
|
1270
|
+
}
|
1271
|
+
|
1272
|
+
static VALUE
|
1273
|
+
console_cursor_pos(VALUE io)
|
1274
|
+
{
|
1275
|
+
static const struct query_args query = {"\033[6n", 0};
|
1276
|
+
VALUE resp = console_vt_response(0, 0, io, &query);
|
1277
|
+
VALUE row, column, term;
|
1278
|
+
unsigned int r, c;
|
1279
|
+
if (!RB_TYPE_P(resp, T_ARRAY) || RARRAY_LEN(resp) != 3) return Qnil;
|
1280
|
+
term = RARRAY_AREF(resp, 2);
|
1281
|
+
if (!RB_TYPE_P(term, T_STRING) || RSTRING_LEN(term) != 1) return Qnil;
|
1282
|
+
if (RSTRING_PTR(term)[0] != 'R') return Qnil;
|
1283
|
+
row = RARRAY_AREF(resp, 0);
|
1284
|
+
column = RARRAY_AREF(resp, 1);
|
1285
|
+
rb_ary_resize(resp, 2);
|
1286
|
+
r = NUM2UINT(row) - 1;
|
1287
|
+
c = NUM2UINT(column) - 1;
|
1288
|
+
RARRAY_ASET(resp, 0, INT2NUM(r));
|
1289
|
+
RARRAY_ASET(resp, 1, INT2NUM(c));
|
1290
|
+
return resp;
|
1291
|
+
}
|
1292
|
+
|
1293
|
+
static VALUE
|
1294
|
+
console_goto(VALUE io, VALUE y, VALUE x)
|
1295
|
+
{
|
1296
|
+
rb_io_write(io, rb_sprintf("\x1b[%d;%dH", NUM2UINT(y)+1, NUM2UINT(x)+1));
|
1297
|
+
return io;
|
1298
|
+
}
|
1299
|
+
|
1300
|
+
static VALUE
|
1301
|
+
console_move(VALUE io, int y, int x)
|
1302
|
+
{
|
1303
|
+
if (x || y) {
|
1304
|
+
VALUE s = rb_str_new_cstr("");
|
1305
|
+
if (y) rb_str_catf(s, "\x1b[%d%c", y < 0 ? -y : y, y < 0 ? 'A' : 'B');
|
1306
|
+
if (x) rb_str_catf(s, "\x1b[%d%c", x < 0 ? -x : x, x < 0 ? 'D' : 'C');
|
1307
|
+
rb_io_write(io, s);
|
1308
|
+
rb_io_flush(io);
|
1309
|
+
}
|
1310
|
+
return io;
|
1311
|
+
}
|
1312
|
+
|
1313
|
+
static VALUE
|
1314
|
+
console_goto_column(VALUE io, VALUE val)
|
1315
|
+
{
|
1316
|
+
rb_io_write(io, rb_sprintf("\x1b[%dG", NUM2UINT(val)+1));
|
1317
|
+
return io;
|
1318
|
+
}
|
1319
|
+
|
1320
|
+
static VALUE
|
1321
|
+
console_erase_line(VALUE io, VALUE val)
|
1322
|
+
{
|
1323
|
+
int mode = mode_in_range(val, 2, "line erase");
|
1324
|
+
rb_io_write(io, rb_sprintf("\x1b[%dK", mode));
|
1325
|
+
return io;
|
1326
|
+
}
|
1327
|
+
|
1328
|
+
static VALUE
|
1329
|
+
console_erase_screen(VALUE io, VALUE val)
|
1330
|
+
{
|
1331
|
+
int mode = mode_in_range(val, 3, "screen erase");
|
1332
|
+
rb_io_write(io, rb_sprintf("\x1b[%dJ", mode));
|
1333
|
+
return io;
|
1334
|
+
}
|
1335
|
+
|
1336
|
+
static VALUE
|
1337
|
+
console_scroll(VALUE io, int line)
|
1338
|
+
{
|
1339
|
+
if (line) {
|
1340
|
+
VALUE s = rb_sprintf("\x1b[%d%c", line < 0 ? -line : line,
|
1341
|
+
line < 0 ? 'T' : 'S');
|
1342
|
+
rb_io_write(io, s);
|
1343
|
+
}
|
1344
|
+
return io;
|
1345
|
+
}
|
750
1346
|
# define console_key_pressed_p rb_f_notimplement
|
751
1347
|
#endif
|
752
1348
|
|
1349
|
+
static VALUE
|
1350
|
+
console_cursor_set(VALUE io, VALUE cpos)
|
1351
|
+
{
|
1352
|
+
cpos = rb_convert_type(cpos, T_ARRAY, "Array", "to_ary");
|
1353
|
+
if (RARRAY_LEN(cpos) != 2) rb_raise(rb_eArgError, "expected 2D coordinate");
|
1354
|
+
return console_goto(io, RARRAY_AREF(cpos, 0), RARRAY_AREF(cpos, 1));
|
1355
|
+
}
|
1356
|
+
|
1357
|
+
static VALUE
|
1358
|
+
console_cursor_up(VALUE io, VALUE val)
|
1359
|
+
{
|
1360
|
+
return console_move(io, -NUM2INT(val), 0);
|
1361
|
+
}
|
1362
|
+
|
1363
|
+
static VALUE
|
1364
|
+
console_cursor_down(VALUE io, VALUE val)
|
1365
|
+
{
|
1366
|
+
return console_move(io, +NUM2INT(val), 0);
|
1367
|
+
}
|
1368
|
+
|
1369
|
+
static VALUE
|
1370
|
+
console_cursor_left(VALUE io, VALUE val)
|
1371
|
+
{
|
1372
|
+
return console_move(io, 0, -NUM2INT(val));
|
1373
|
+
}
|
1374
|
+
|
1375
|
+
static VALUE
|
1376
|
+
console_cursor_right(VALUE io, VALUE val)
|
1377
|
+
{
|
1378
|
+
return console_move(io, 0, +NUM2INT(val));
|
1379
|
+
}
|
1380
|
+
|
1381
|
+
static VALUE
|
1382
|
+
console_scroll_forward(VALUE io, VALUE val)
|
1383
|
+
{
|
1384
|
+
return console_scroll(io, +NUM2INT(val));
|
1385
|
+
}
|
1386
|
+
|
1387
|
+
static VALUE
|
1388
|
+
console_scroll_backward(VALUE io, VALUE val)
|
1389
|
+
{
|
1390
|
+
return console_scroll(io, -NUM2INT(val));
|
1391
|
+
}
|
1392
|
+
|
1393
|
+
static VALUE
|
1394
|
+
console_clear_screen(VALUE io)
|
1395
|
+
{
|
1396
|
+
console_erase_screen(io, INT2FIX(2));
|
1397
|
+
console_goto(io, INT2FIX(0), INT2FIX(0));
|
1398
|
+
return io;
|
1399
|
+
}
|
1400
|
+
|
753
1401
|
/*
|
754
1402
|
* call-seq:
|
755
1403
|
* IO.console -> #<File:/dev/tty>
|
@@ -849,7 +1497,7 @@ console_dev(int argc, VALUE *argv, VALUE klass)
|
|
849
1497
|
|
850
1498
|
/*
|
851
1499
|
* call-seq:
|
852
|
-
* io.getch(min: nil, time: nil)
|
1500
|
+
* io.getch(min: nil, time: nil, intr: nil) -> char
|
853
1501
|
*
|
854
1502
|
* See IO#getch.
|
855
1503
|
*/
|
@@ -869,7 +1517,7 @@ puts_call(VALUE io)
|
|
869
1517
|
static VALUE
|
870
1518
|
getpass_call(VALUE io)
|
871
1519
|
{
|
872
|
-
return ttymode(io, rb_io_gets, set_noecho, NULL);
|
1520
|
+
return ttymode(io, rb_io_gets, io, set_noecho, NULL);
|
873
1521
|
}
|
874
1522
|
|
875
1523
|
static void
|
@@ -878,7 +1526,6 @@ prompt(int argc, VALUE *argv, VALUE io)
|
|
878
1526
|
if (argc > 0 && !NIL_P(argv[0])) {
|
879
1527
|
VALUE str = argv[0];
|
880
1528
|
StringValueCStr(str);
|
881
|
-
rb_check_safe_obj(str);
|
882
1529
|
rb_io_write(io, str);
|
883
1530
|
}
|
884
1531
|
}
|
@@ -948,6 +1595,7 @@ Init_console(void)
|
|
948
1595
|
id_close = rb_intern("close");
|
949
1596
|
id_min = rb_intern("min");
|
950
1597
|
id_time = rb_intern("time");
|
1598
|
+
id_intr = rb_intern("intr");
|
951
1599
|
#ifndef HAVE_RB_F_SEND
|
952
1600
|
id___send__ = rb_intern("__send__");
|
953
1601
|
#endif
|
@@ -964,6 +1612,8 @@ InitVM_console(void)
|
|
964
1612
|
rb_define_method(rb_cIO, "getch", console_getch, -1);
|
965
1613
|
rb_define_method(rb_cIO, "echo=", console_set_echo, 1);
|
966
1614
|
rb_define_method(rb_cIO, "echo?", console_echo_p, 0);
|
1615
|
+
rb_define_method(rb_cIO, "console_mode", console_conmode_get, 0);
|
1616
|
+
rb_define_method(rb_cIO, "console_mode=", console_conmode_set, 1);
|
967
1617
|
rb_define_method(rb_cIO, "noecho", console_noecho, 0);
|
968
1618
|
rb_define_method(rb_cIO, "winsize", console_winsize, 0);
|
969
1619
|
rb_define_method(rb_cIO, "winsize=", console_set_winsize, 1);
|
@@ -974,7 +1624,18 @@ InitVM_console(void)
|
|
974
1624
|
rb_define_method(rb_cIO, "goto", console_goto, 2);
|
975
1625
|
rb_define_method(rb_cIO, "cursor", console_cursor_pos, 0);
|
976
1626
|
rb_define_method(rb_cIO, "cursor=", console_cursor_set, 1);
|
1627
|
+
rb_define_method(rb_cIO, "cursor_up", console_cursor_up, 1);
|
1628
|
+
rb_define_method(rb_cIO, "cursor_down", console_cursor_down, 1);
|
1629
|
+
rb_define_method(rb_cIO, "cursor_left", console_cursor_left, 1);
|
1630
|
+
rb_define_method(rb_cIO, "cursor_right", console_cursor_right, 1);
|
1631
|
+
rb_define_method(rb_cIO, "goto_column", console_goto_column, 1);
|
1632
|
+
rb_define_method(rb_cIO, "erase_line", console_erase_line, 1);
|
1633
|
+
rb_define_method(rb_cIO, "erase_screen", console_erase_screen, 1);
|
1634
|
+
rb_define_method(rb_cIO, "scroll_forward", console_scroll_forward, 1);
|
1635
|
+
rb_define_method(rb_cIO, "scroll_backward", console_scroll_backward, 1);
|
1636
|
+
rb_define_method(rb_cIO, "clear_screen", console_clear_screen, 0);
|
977
1637
|
rb_define_method(rb_cIO, "pressed?", console_key_pressed_p, 1);
|
1638
|
+
rb_define_method(rb_cIO, "check_winsize_changed", console_check_winsize_changed, 0);
|
978
1639
|
#if ENABLE_IO_GETPASS
|
979
1640
|
rb_define_method(rb_cIO, "getpass", console_getpass, -1);
|
980
1641
|
#endif
|
@@ -986,4 +1647,15 @@ InitVM_console(void)
|
|
986
1647
|
rb_define_method(mReadable, "getpass", io_getpass, -1);
|
987
1648
|
#endif
|
988
1649
|
}
|
1650
|
+
{
|
1651
|
+
/* :stopdoc: */
|
1652
|
+
cConmode = rb_define_class_under(rb_cIO, "ConsoleMode", rb_cObject);
|
1653
|
+
rb_define_alloc_func(cConmode, conmode_alloc);
|
1654
|
+
rb_undef_method(cConmode, "initialize");
|
1655
|
+
rb_define_method(cConmode, "initialize_copy", conmode_init_copy, 1);
|
1656
|
+
rb_define_method(cConmode, "echo=", conmode_set_echo, 1);
|
1657
|
+
rb_define_method(cConmode, "raw!", conmode_set_raw, -1);
|
1658
|
+
rb_define_method(cConmode, "raw", conmode_raw_new, -1);
|
1659
|
+
/* :startdoc: */
|
1660
|
+
}
|
989
1661
|
}
|