io-console 0.8.2 → 0.9.4
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 +4 -4
- data/ext/io/console/console.c +621 -40
- data/ext/io/console/extconf.rb +39 -15
- data/ext/io/console/win32_vk.inc +313 -165
- data/lib/io/console/size.rb +4 -2
- metadata +2 -2
data/ext/io/console/console.c
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
static const char *const
|
|
7
|
-
IO_CONSOLE_VERSION = "0.
|
|
7
|
+
IO_CONSOLE_VERSION = "0.9.4";
|
|
8
8
|
|
|
9
9
|
#include "ruby.h"
|
|
10
10
|
#include "ruby/io.h"
|
|
@@ -56,6 +56,13 @@ typedef struct sgttyb conmode;
|
|
|
56
56
|
#include <conio.h>
|
|
57
57
|
typedef DWORD conmode;
|
|
58
58
|
|
|
59
|
+
#ifndef ENABLE_WRAP_AT_EOL_OUTPUT
|
|
60
|
+
# define ENABLE_WRAP_AT_EOL_OUTPUT 0x0002
|
|
61
|
+
#endif
|
|
62
|
+
#ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING
|
|
63
|
+
# define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004
|
|
64
|
+
#endif
|
|
65
|
+
|
|
59
66
|
#define LAST_ERROR rb_w32_map_errno(GetLastError())
|
|
60
67
|
#define SET_LAST_ERROR (errno = LAST_ERROR, 0)
|
|
61
68
|
|
|
@@ -81,7 +88,7 @@ getattr(int fd, conmode *t)
|
|
|
81
88
|
|
|
82
89
|
#define CSI "\x1b\x5b"
|
|
83
90
|
|
|
84
|
-
static ID id_getc, id_close;
|
|
91
|
+
static ID id_getc, id_close, id_timeout;
|
|
85
92
|
static ID id_gets, id_flush, id_chomp_bang;
|
|
86
93
|
|
|
87
94
|
#ifndef HAVE_RB_INTERNED_STR_CSTR
|
|
@@ -89,6 +96,10 @@ static ID id_gets, id_flush, id_chomp_bang;
|
|
|
89
96
|
# define rb_interned_str_cstr(str) rb_str_freeze(rb_usascii_str_new_cstr(str))
|
|
90
97
|
#endif
|
|
91
98
|
|
|
99
|
+
#if !defined(HAVE_RB_CATEGORY_WARN) || !defined(HAVE_CONST_RB_WARN_CATEGORY_DEPRECATED)
|
|
100
|
+
# define rb_category_warn(category, ...) rb_warn(__VA_ARGS__)
|
|
101
|
+
#endif
|
|
102
|
+
|
|
92
103
|
#if defined HAVE_RUBY_FIBER_SCHEDULER_H
|
|
93
104
|
# include "ruby/fiber/scheduler.h"
|
|
94
105
|
#elif defined HAVE_RB_SCHEDULER_TIMEOUT
|
|
@@ -118,22 +129,6 @@ io_path_fallback(VALUE io)
|
|
|
118
129
|
#define rb_io_path io_path_fallback
|
|
119
130
|
#endif
|
|
120
131
|
|
|
121
|
-
#ifndef HAVE_RB_IO_GET_WRITE_IO
|
|
122
|
-
static VALUE
|
|
123
|
-
io_get_write_io_fallback(VALUE io)
|
|
124
|
-
{
|
|
125
|
-
rb_io_t *fptr;
|
|
126
|
-
GetOpenFile(io, fptr);
|
|
127
|
-
VALUE wio = fptr->tied_io_for_writing;
|
|
128
|
-
return wio ? wio : io;
|
|
129
|
-
}
|
|
130
|
-
#define rb_io_get_write_io io_get_write_io_fallback
|
|
131
|
-
#endif
|
|
132
|
-
|
|
133
|
-
#ifndef DHAVE_RB_SYSERR_FAIL_STR
|
|
134
|
-
# define rb_syserr_fail_str(e, mesg) rb_exc_raise(rb_syserr_new_str(e, mesg))
|
|
135
|
-
#endif
|
|
136
|
-
|
|
137
132
|
#define sys_fail(io) do { \
|
|
138
133
|
int err = errno; \
|
|
139
134
|
rb_syserr_fail_str(err, rb_io_path(io)); \
|
|
@@ -183,6 +178,22 @@ typedef struct {
|
|
|
183
178
|
# define NIL_OR_UNDEF_P(obj) (NIL_P(obj) || UNDEF_P(obj))
|
|
184
179
|
#endif
|
|
185
180
|
|
|
181
|
+
static int
|
|
182
|
+
to_vtime(VALUE vtime)
|
|
183
|
+
{
|
|
184
|
+
VALUE v10 = INT2FIX(10);
|
|
185
|
+
vtime = rb_funcall3(vtime, '*', 1, &v10);
|
|
186
|
+
return NUM2INT(vtime);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
static unsigned char
|
|
190
|
+
clamp_uchar(int n)
|
|
191
|
+
{
|
|
192
|
+
if ((unsigned int)n >= UCHAR_MAX) n = UCHAR_MAX;
|
|
193
|
+
else if (n < 0) n = 0;
|
|
194
|
+
return (unsigned char)n;
|
|
195
|
+
}
|
|
196
|
+
|
|
186
197
|
static rawmode_arg_t *
|
|
187
198
|
rawmode_opt(int *argcp, VALUE *argv, int min_argc, int max_argc, rawmode_arg_t *opts)
|
|
188
199
|
{
|
|
@@ -214,13 +225,11 @@ rawmode_opt(int *argcp, VALUE *argv, int min_argc, int max_argc, rawmode_arg_t *
|
|
|
214
225
|
opts->vtime = 0;
|
|
215
226
|
opts->intr = 0;
|
|
216
227
|
if (!NIL_OR_UNDEF_P(vmin)) {
|
|
217
|
-
opts->vmin = NUM2INT(vmin);
|
|
228
|
+
opts->vmin = clamp_uchar(NUM2INT(vmin));
|
|
218
229
|
optp = opts;
|
|
219
230
|
}
|
|
220
231
|
if (!NIL_OR_UNDEF_P(vtime)) {
|
|
221
|
-
|
|
222
|
-
vtime = rb_funcall3(vtime, '*', 1, &v10);
|
|
223
|
-
opts->vtime = NUM2INT(vtime);
|
|
232
|
+
opts->vtime = clamp_uchar(to_vtime(vtime));
|
|
224
233
|
optp = opts;
|
|
225
234
|
}
|
|
226
235
|
switch (intr) {
|
|
@@ -550,7 +559,7 @@ nogvl_getch(void *p)
|
|
|
550
559
|
|
|
551
560
|
/*
|
|
552
561
|
* call-seq:
|
|
553
|
-
* io.getch(min: nil, time: nil, intr: nil) -> char
|
|
562
|
+
* io.getch(min: nil, time: nil, intr: nil) -> char or nil
|
|
554
563
|
*
|
|
555
564
|
* Reads and returns a character in raw mode.
|
|
556
565
|
*
|
|
@@ -635,6 +644,43 @@ console_getch(int argc, VALUE *argv, VALUE io)
|
|
|
635
644
|
#endif
|
|
636
645
|
}
|
|
637
646
|
|
|
647
|
+
/*
|
|
648
|
+
* call-seq:
|
|
649
|
+
* io.input_pending? -> true or false
|
|
650
|
+
*
|
|
651
|
+
* Returns whether input can be read without blocking.
|
|
652
|
+
*
|
|
653
|
+
* You must require 'io/console' to use this method.
|
|
654
|
+
*/
|
|
655
|
+
static VALUE
|
|
656
|
+
console_input_pending_p(VALUE io)
|
|
657
|
+
{
|
|
658
|
+
rb_io_t *fptr;
|
|
659
|
+
|
|
660
|
+
GetOpenFile(io, fptr);
|
|
661
|
+
if (rb_io_read_pending(fptr)) return Qtrue;
|
|
662
|
+
#ifdef _WIN32
|
|
663
|
+
{
|
|
664
|
+
DWORD mode;
|
|
665
|
+
HANDLE h = (HANDLE)rb_w32_get_osfhandle(GetReadFD(io));
|
|
666
|
+
|
|
667
|
+
if (GetConsoleMode(h, &mode)) return _kbhit() ? Qtrue : Qfalse;
|
|
668
|
+
}
|
|
669
|
+
#endif
|
|
670
|
+
#if defined HAVE_RB_IO_WAIT
|
|
671
|
+
return RTEST(rb_io_wait(io, RB_INT2NUM(RUBY_IO_READABLE), INT2FIX(0))) ? Qtrue : Qfalse;
|
|
672
|
+
#else
|
|
673
|
+
{
|
|
674
|
+
struct timeval timeout = {0, 0};
|
|
675
|
+
int result;
|
|
676
|
+
|
|
677
|
+
result = rb_wait_for_single_fd(fptr->fd, RB_WAITFD_IN, &timeout);
|
|
678
|
+
if (result < 0) sys_fail(io);
|
|
679
|
+
return (result & RB_WAITFD_IN) ? Qtrue : Qfalse;
|
|
680
|
+
}
|
|
681
|
+
#endif
|
|
682
|
+
}
|
|
683
|
+
|
|
638
684
|
/*
|
|
639
685
|
* call-seq:
|
|
640
686
|
* io.noecho {|io| }
|
|
@@ -730,6 +776,13 @@ conmode_init_copy(VALUE obj, VALUE obj2)
|
|
|
730
776
|
return obj;
|
|
731
777
|
}
|
|
732
778
|
|
|
779
|
+
static VALUE
|
|
780
|
+
conmode_get_echo(VALUE obj)
|
|
781
|
+
{
|
|
782
|
+
conmode *t = rb_check_typeddata(obj, &conmode_type);
|
|
783
|
+
return echo_p(t) ? Qtrue : Qfalse;
|
|
784
|
+
}
|
|
785
|
+
|
|
733
786
|
static VALUE
|
|
734
787
|
conmode_set_echo(VALUE obj, VALUE f)
|
|
735
788
|
{
|
|
@@ -762,6 +815,122 @@ conmode_raw_new(int argc, VALUE *argv, VALUE obj)
|
|
|
762
815
|
return conmode_new(rb_obj_class(obj), &t);
|
|
763
816
|
}
|
|
764
817
|
|
|
818
|
+
static VALUE
|
|
819
|
+
conmode_get_min(VALUE obj)
|
|
820
|
+
{
|
|
821
|
+
conmode *t = rb_check_typeddata(obj, &conmode_type);
|
|
822
|
+
#ifdef VMIN
|
|
823
|
+
return INT2FIX(t->c_cc[VMIN]);
|
|
824
|
+
#else
|
|
825
|
+
(void)t;
|
|
826
|
+
return Qnil;
|
|
827
|
+
#endif
|
|
828
|
+
}
|
|
829
|
+
|
|
830
|
+
static VALUE
|
|
831
|
+
conmode_set_min(VALUE obj, VALUE min)
|
|
832
|
+
{
|
|
833
|
+
conmode *t = rb_check_typeddata(obj, &conmode_type);
|
|
834
|
+
int vmin = NIL_P(min) ? 1 : clamp_uchar(NUM2INT(min));
|
|
835
|
+
#ifdef VMIN
|
|
836
|
+
t->c_cc[VMIN] = vmin;
|
|
837
|
+
#else
|
|
838
|
+
(void)t;
|
|
839
|
+
(void)vmin;
|
|
840
|
+
#endif
|
|
841
|
+
return min;
|
|
842
|
+
}
|
|
843
|
+
|
|
844
|
+
static VALUE
|
|
845
|
+
conmode_get_time(VALUE obj)
|
|
846
|
+
{
|
|
847
|
+
conmode *t = rb_check_typeddata(obj, &conmode_type);
|
|
848
|
+
#ifdef VTIME
|
|
849
|
+
return rb_rational_new(INT2FIX(t->c_cc[VTIME]), INT2FIX(10));
|
|
850
|
+
#else
|
|
851
|
+
(void)t;
|
|
852
|
+
return Qnil;
|
|
853
|
+
#endif
|
|
854
|
+
}
|
|
855
|
+
|
|
856
|
+
static VALUE
|
|
857
|
+
conmode_set_time(VALUE obj, VALUE time)
|
|
858
|
+
{
|
|
859
|
+
conmode *t = rb_check_typeddata(obj, &conmode_type);
|
|
860
|
+
int vtime = NIL_P(time) ? 0 : clamp_uchar(to_vtime(time));
|
|
861
|
+
#ifdef VTIME
|
|
862
|
+
t->c_cc[VTIME] = vtime;
|
|
863
|
+
#else
|
|
864
|
+
(void)t;
|
|
865
|
+
(void)vtime;
|
|
866
|
+
#endif
|
|
867
|
+
return time;
|
|
868
|
+
}
|
|
869
|
+
|
|
870
|
+
#ifdef _WIN32
|
|
871
|
+
/*
|
|
872
|
+
* call-seq:
|
|
873
|
+
* mode.virtual_terminal_processing? -> true or false
|
|
874
|
+
*
|
|
875
|
+
* Returns whether virtual terminal sequences are processed on output.
|
|
876
|
+
*/
|
|
877
|
+
static VALUE
|
|
878
|
+
conmode_virtual_terminal_processing_p(VALUE obj)
|
|
879
|
+
{
|
|
880
|
+
conmode *t = rb_check_typeddata(obj, &conmode_type);
|
|
881
|
+
return (*t & ENABLE_VIRTUAL_TERMINAL_PROCESSING) ? Qtrue : Qfalse;
|
|
882
|
+
}
|
|
883
|
+
|
|
884
|
+
/*
|
|
885
|
+
* call-seq:
|
|
886
|
+
* mode.virtual_terminal_processing = enabled
|
|
887
|
+
*
|
|
888
|
+
* Enables or disables virtual terminal sequence processing in +mode+.
|
|
889
|
+
* Assign +mode+ to IO#console_mode= to apply the change.
|
|
890
|
+
*/
|
|
891
|
+
static VALUE
|
|
892
|
+
conmode_set_virtual_terminal_processing(VALUE obj, VALUE enabled)
|
|
893
|
+
{
|
|
894
|
+
conmode *t = rb_check_typeddata(obj, &conmode_type);
|
|
895
|
+
if (RTEST(enabled))
|
|
896
|
+
*t |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
|
|
897
|
+
else
|
|
898
|
+
*t &= ~ENABLE_VIRTUAL_TERMINAL_PROCESSING;
|
|
899
|
+
return obj;
|
|
900
|
+
}
|
|
901
|
+
|
|
902
|
+
/*
|
|
903
|
+
* call-seq:
|
|
904
|
+
* mode.wrap_at_eol_output? -> true or false
|
|
905
|
+
*
|
|
906
|
+
* Returns whether output wraps at the end of a line.
|
|
907
|
+
*/
|
|
908
|
+
static VALUE
|
|
909
|
+
conmode_wrap_at_eol_output_p(VALUE obj)
|
|
910
|
+
{
|
|
911
|
+
conmode *t = rb_check_typeddata(obj, &conmode_type);
|
|
912
|
+
return (*t & ENABLE_WRAP_AT_EOL_OUTPUT) ? Qtrue : Qfalse;
|
|
913
|
+
}
|
|
914
|
+
|
|
915
|
+
/*
|
|
916
|
+
* call-seq:
|
|
917
|
+
* mode.wrap_at_eol_output = enabled
|
|
918
|
+
*
|
|
919
|
+
* Enables or disables wrapping at the end of a line in +mode+.
|
|
920
|
+
* Assign +mode+ to IO#console_mode= to apply the change.
|
|
921
|
+
*/
|
|
922
|
+
static VALUE
|
|
923
|
+
conmode_set_wrap_at_eol_output(VALUE obj, VALUE enabled)
|
|
924
|
+
{
|
|
925
|
+
conmode *t = rb_check_typeddata(obj, &conmode_type);
|
|
926
|
+
if (RTEST(enabled))
|
|
927
|
+
*t |= ENABLE_WRAP_AT_EOL_OUTPUT;
|
|
928
|
+
else
|
|
929
|
+
*t &= ~ENABLE_WRAP_AT_EOL_OUTPUT;
|
|
930
|
+
return obj;
|
|
931
|
+
}
|
|
932
|
+
#endif
|
|
933
|
+
|
|
765
934
|
/*
|
|
766
935
|
* call-seq:
|
|
767
936
|
* io.console_mode -> mode
|
|
@@ -861,7 +1030,6 @@ console_set_winsize(VALUE io, VALUE size)
|
|
|
861
1030
|
int newrow, newcol;
|
|
862
1031
|
COORD oldsize;
|
|
863
1032
|
SMALL_RECT oldwindow;
|
|
864
|
-
BOOL ret;
|
|
865
1033
|
#endif
|
|
866
1034
|
VALUE row, col, xpixel, ypixel;
|
|
867
1035
|
const VALUE *sz;
|
|
@@ -963,12 +1131,207 @@ console_set_winsize(VALUE io, VALUE size)
|
|
|
963
1131
|
#endif
|
|
964
1132
|
|
|
965
1133
|
#ifdef _WIN32
|
|
1134
|
+
enum console_input_handle_index {
|
|
1135
|
+
console_input_handle,
|
|
1136
|
+
console_input_wakeup,
|
|
1137
|
+
console_input_handle_count
|
|
1138
|
+
};
|
|
1139
|
+
|
|
1140
|
+
typedef struct {
|
|
1141
|
+
HANDLE handles[console_input_handle_count];
|
|
1142
|
+
INPUT_RECORD *records;
|
|
1143
|
+
DWORD length;
|
|
1144
|
+
DWORD count;
|
|
1145
|
+
DWORD timeout;
|
|
1146
|
+
DWORD wait_result;
|
|
1147
|
+
DWORD error;
|
|
1148
|
+
BOOL result;
|
|
1149
|
+
} read_console_input_args_t;
|
|
1150
|
+
|
|
1151
|
+
static void *
|
|
1152
|
+
nogvl_read_console_input(void *ptr)
|
|
1153
|
+
{
|
|
1154
|
+
read_console_input_args_t *args = ptr;
|
|
1155
|
+
|
|
1156
|
+
args->wait_result = WaitForMultipleObjects(console_input_handle_count,
|
|
1157
|
+
args->handles, FALSE, args->timeout);
|
|
1158
|
+
if (args->wait_result == WAIT_OBJECT_0 + console_input_handle) {
|
|
1159
|
+
args->result = ReadConsoleInputW(args->handles[console_input_handle],
|
|
1160
|
+
args->records, args->length, &args->count);
|
|
1161
|
+
if (!args->result) args->error = GetLastError();
|
|
1162
|
+
}
|
|
1163
|
+
else if (args->wait_result == WAIT_FAILED) {
|
|
1164
|
+
args->error = GetLastError();
|
|
1165
|
+
}
|
|
1166
|
+
return 0;
|
|
1167
|
+
}
|
|
1168
|
+
|
|
1169
|
+
static void
|
|
1170
|
+
ubf_console_input(void *ptr)
|
|
1171
|
+
{
|
|
1172
|
+
read_console_input_args_t *args = ptr;
|
|
1173
|
+
SetEvent(args->handles[console_input_wakeup]);
|
|
1174
|
+
}
|
|
1175
|
+
|
|
1176
|
+
static void
|
|
1177
|
+
console_input_event_set(VALUE event, const char *name, VALUE value)
|
|
1178
|
+
{
|
|
1179
|
+
rb_hash_aset(event, ID2SYM(rb_intern(name)), value);
|
|
1180
|
+
}
|
|
1181
|
+
|
|
1182
|
+
static VALUE
|
|
1183
|
+
console_input_event(const INPUT_RECORD *record)
|
|
1184
|
+
{
|
|
1185
|
+
VALUE event = rb_hash_new();
|
|
1186
|
+
|
|
1187
|
+
switch (record->EventType) {
|
|
1188
|
+
case KEY_EVENT:
|
|
1189
|
+
console_input_event_set(event, "type", ID2SYM(rb_intern("key")));
|
|
1190
|
+
console_input_event_set(event, "key_down", record->Event.KeyEvent.bKeyDown ? Qtrue : Qfalse);
|
|
1191
|
+
console_input_event_set(event, "repeat_count", UINT2NUM(record->Event.KeyEvent.wRepeatCount));
|
|
1192
|
+
console_input_event_set(event, "virtual_key_code", UINT2NUM(record->Event.KeyEvent.wVirtualKeyCode));
|
|
1193
|
+
console_input_event_set(event, "virtual_scan_code", UINT2NUM(record->Event.KeyEvent.wVirtualScanCode));
|
|
1194
|
+
console_input_event_set(event, "unicode_char", UINT2NUM(record->Event.KeyEvent.uChar.UnicodeChar));
|
|
1195
|
+
console_input_event_set(event, "control_key_state", UINT2NUM(record->Event.KeyEvent.dwControlKeyState));
|
|
1196
|
+
break;
|
|
1197
|
+
case MOUSE_EVENT:
|
|
1198
|
+
console_input_event_set(event, "type", ID2SYM(rb_intern("mouse")));
|
|
1199
|
+
console_input_event_set(event, "position", rb_assoc_new(
|
|
1200
|
+
INT2NUM(record->Event.MouseEvent.dwMousePosition.Y),
|
|
1201
|
+
INT2NUM(record->Event.MouseEvent.dwMousePosition.X)));
|
|
1202
|
+
console_input_event_set(event, "button_state", UINT2NUM(record->Event.MouseEvent.dwButtonState));
|
|
1203
|
+
console_input_event_set(event, "control_key_state", UINT2NUM(record->Event.MouseEvent.dwControlKeyState));
|
|
1204
|
+
console_input_event_set(event, "event_flags", UINT2NUM(record->Event.MouseEvent.dwEventFlags));
|
|
1205
|
+
break;
|
|
1206
|
+
case WINDOW_BUFFER_SIZE_EVENT:
|
|
1207
|
+
console_input_event_set(event, "type", ID2SYM(rb_intern("window_buffer_size")));
|
|
1208
|
+
console_input_event_set(event, "size", rb_assoc_new(
|
|
1209
|
+
INT2NUM(record->Event.WindowBufferSizeEvent.dwSize.Y),
|
|
1210
|
+
INT2NUM(record->Event.WindowBufferSizeEvent.dwSize.X)));
|
|
1211
|
+
break;
|
|
1212
|
+
case MENU_EVENT:
|
|
1213
|
+
console_input_event_set(event, "type", ID2SYM(rb_intern("menu")));
|
|
1214
|
+
console_input_event_set(event, "command_id", UINT2NUM(record->Event.MenuEvent.dwCommandId));
|
|
1215
|
+
break;
|
|
1216
|
+
case FOCUS_EVENT:
|
|
1217
|
+
console_input_event_set(event, "type", ID2SYM(rb_intern("focus")));
|
|
1218
|
+
console_input_event_set(event, "set_focus", record->Event.FocusEvent.bSetFocus ? Qtrue : Qfalse);
|
|
1219
|
+
break;
|
|
1220
|
+
default:
|
|
1221
|
+
console_input_event_set(event, "type", UINT2NUM(record->EventType));
|
|
1222
|
+
break;
|
|
1223
|
+
}
|
|
1224
|
+
|
|
1225
|
+
return event;
|
|
1226
|
+
}
|
|
1227
|
+
|
|
1228
|
+
static VALUE
|
|
1229
|
+
console_input_events_read(VALUE vargs)
|
|
1230
|
+
{
|
|
1231
|
+
read_console_input_args_t *args = (read_console_input_args_t *)vargs;
|
|
1232
|
+
VALUE events;
|
|
1233
|
+
DWORD i;
|
|
1234
|
+
|
|
1235
|
+
rb_thread_call_without_gvl(nogvl_read_console_input, args,
|
|
1236
|
+
ubf_console_input, args);
|
|
1237
|
+
if (args->wait_result == WAIT_TIMEOUT) return rb_ary_new();
|
|
1238
|
+
if (args->wait_result != WAIT_OBJECT_0 + console_input_handle ||
|
|
1239
|
+
!args->result) {
|
|
1240
|
+
rb_syserr_fail(rb_w32_map_errno(args->error), 0);
|
|
1241
|
+
}
|
|
1242
|
+
|
|
1243
|
+
events = rb_ary_new_capa(args->count);
|
|
1244
|
+
for (i = 0; i < args->count; ++i) {
|
|
1245
|
+
rb_ary_push(events, console_input_event(&args->records[i]));
|
|
1246
|
+
}
|
|
1247
|
+
return events;
|
|
1248
|
+
}
|
|
1249
|
+
|
|
1250
|
+
static VALUE
|
|
1251
|
+
console_input_events_ensure(VALUE vargs)
|
|
1252
|
+
{
|
|
1253
|
+
read_console_input_args_t *args = (read_console_input_args_t *)vargs;
|
|
1254
|
+
|
|
1255
|
+
CloseHandle(args->handles[console_input_wakeup]);
|
|
1256
|
+
xfree(args->records);
|
|
1257
|
+
return Qnil;
|
|
1258
|
+
}
|
|
1259
|
+
|
|
1260
|
+
/*
|
|
1261
|
+
* call-seq:
|
|
1262
|
+
* io.console_input_events([max_events], timeout: nil) -> array
|
|
1263
|
+
*
|
|
1264
|
+
* Reads up to +max_events+ console input events, preserving their order.
|
|
1265
|
+
* The default is one event. Blocks until at least one event is available,
|
|
1266
|
+
* or for +timeout+ seconds if specified. Returns an empty Array on timeout.
|
|
1267
|
+
*
|
|
1268
|
+
* Each event is returned as a Hash. The +:type+ and remaining keys are:
|
|
1269
|
+
*
|
|
1270
|
+
* - +:key+ : +:key_down+, +:repeat_count+, +:virtual_key_code+,
|
|
1271
|
+
* +:virtual_scan_code+, +:unicode_char+, and +:control_key_state+.
|
|
1272
|
+
* - +:mouse+ : +:position+ ([row, column]), +:button_state+,
|
|
1273
|
+
* +:control_key_state+, and +:event_flags+.
|
|
1274
|
+
* - +:window_buffer_size+ : +:size+ ([rows, columns]).
|
|
1275
|
+
* - +:menu+ : +:command_id+.
|
|
1276
|
+
* - +:focus+ : +:set_focus+.
|
|
1277
|
+
*
|
|
1278
|
+
* This method is Windows only.
|
|
1279
|
+
*
|
|
1280
|
+
* You must require 'io/console' to use this method.
|
|
1281
|
+
*/
|
|
1282
|
+
static VALUE
|
|
1283
|
+
console_input_events(int argc, VALUE *argv, VALUE io)
|
|
1284
|
+
{
|
|
1285
|
+
VALUE vmax = Qnil, vopts = Qnil, vtimeout = Qundef;
|
|
1286
|
+
VALUE values[1];
|
|
1287
|
+
ID keywords[1] = {id_timeout};
|
|
1288
|
+
DWORD max_events = 1;
|
|
1289
|
+
read_console_input_args_t args;
|
|
1290
|
+
|
|
1291
|
+
rb_scan_args(argc, argv, "01:", &vmax, &vopts);
|
|
1292
|
+
if (rb_get_kwargs(vopts, keywords, 0, 1, values)) {
|
|
1293
|
+
vtimeout = values[0];
|
|
1294
|
+
}
|
|
1295
|
+
if (!NIL_P(vmax)) {
|
|
1296
|
+
max_events = NUM2UINT(vmax);
|
|
1297
|
+
if (max_events == 0) rb_raise(rb_eArgError, "max_events must be positive");
|
|
1298
|
+
}
|
|
1299
|
+
|
|
1300
|
+
args.timeout = INFINITE;
|
|
1301
|
+
if (!NIL_OR_UNDEF_P(vtimeout)) {
|
|
1302
|
+
struct timeval timeout = rb_time_interval(vtimeout);
|
|
1303
|
+
uint64_t milliseconds = (uint64_t)timeout.tv_sec * 1000;
|
|
1304
|
+
milliseconds += ((uint64_t)timeout.tv_usec + 999) / 1000;
|
|
1305
|
+
args.timeout = milliseconds < INFINITE ? (DWORD)milliseconds : INFINITE - 1;
|
|
1306
|
+
}
|
|
1307
|
+
|
|
1308
|
+
args.handles[console_input_handle] =
|
|
1309
|
+
(HANDLE)rb_w32_get_osfhandle(GetReadFD(io));
|
|
1310
|
+
args.records = ALLOC_N(INPUT_RECORD, max_events);
|
|
1311
|
+
args.handles[console_input_wakeup] = CreateEvent(NULL, FALSE, FALSE, NULL);
|
|
1312
|
+
if (!args.handles[console_input_wakeup]) {
|
|
1313
|
+
int error = LAST_ERROR;
|
|
1314
|
+
xfree(args.records);
|
|
1315
|
+
rb_syserr_fail(error, 0);
|
|
1316
|
+
}
|
|
1317
|
+
args.length = max_events;
|
|
1318
|
+
args.count = 0;
|
|
1319
|
+
args.wait_result = WAIT_FAILED;
|
|
1320
|
+
args.error = ERROR_SUCCESS;
|
|
1321
|
+
args.result = FALSE;
|
|
1322
|
+
return rb_ensure(console_input_events_read, (VALUE)&args,
|
|
1323
|
+
console_input_events_ensure, (VALUE)&args);
|
|
1324
|
+
}
|
|
1325
|
+
|
|
966
1326
|
/*
|
|
967
1327
|
* call-seq:
|
|
968
1328
|
* io.check_winsize_changed { ... } -> io
|
|
969
1329
|
*
|
|
970
1330
|
* Yields while console input events are queued.
|
|
971
1331
|
*
|
|
1332
|
+
* Deprecated because it discards queued input events other than window buffer
|
|
1333
|
+
* size changes. Use IO#console_input_events instead to preserve all events.
|
|
1334
|
+
*
|
|
972
1335
|
* This method is Windows only.
|
|
973
1336
|
*
|
|
974
1337
|
* You must require 'io/console' to use this method.
|
|
@@ -979,6 +1342,9 @@ console_check_winsize_changed(VALUE io)
|
|
|
979
1342
|
HANDLE h;
|
|
980
1343
|
DWORD num;
|
|
981
1344
|
|
|
1345
|
+
rb_category_warn(RB_WARN_CATEGORY_DEPRECATED,
|
|
1346
|
+
"IO#check_winsize_changed is deprecated; "
|
|
1347
|
+
"use IO#console_input_events instead");
|
|
982
1348
|
h = (HANDLE)rb_w32_get_osfhandle(GetReadFD(io));
|
|
983
1349
|
while (GetNumberOfConsoleInputEvents(h, &num) && num > 0) {
|
|
984
1350
|
INPUT_RECORD rec;
|
|
@@ -991,6 +1357,7 @@ console_check_winsize_changed(VALUE io)
|
|
|
991
1357
|
return io;
|
|
992
1358
|
}
|
|
993
1359
|
#else
|
|
1360
|
+
#define console_input_events rb_f_notimplement
|
|
994
1361
|
#define console_check_winsize_changed rb_f_notimplement
|
|
995
1362
|
#endif
|
|
996
1363
|
|
|
@@ -1291,6 +1658,54 @@ console_cursor_pos(VALUE io)
|
|
|
1291
1658
|
#endif
|
|
1292
1659
|
}
|
|
1293
1660
|
|
|
1661
|
+
static VALUE
|
|
1662
|
+
console_cursor_visibility(VALUE io, int visible)
|
|
1663
|
+
{
|
|
1664
|
+
#ifdef _WIN32
|
|
1665
|
+
HANDLE h = (HANDLE)rb_w32_get_osfhandle(GetWriteFD(io));
|
|
1666
|
+
CONSOLE_CURSOR_INFO info;
|
|
1667
|
+
|
|
1668
|
+
if (!GetConsoleCursorInfo(h, &info)) {
|
|
1669
|
+
rb_syserr_fail(LAST_ERROR, 0);
|
|
1670
|
+
}
|
|
1671
|
+
info.bVisible = visible;
|
|
1672
|
+
if (!SetConsoleCursorInfo(h, &info)) {
|
|
1673
|
+
rb_syserr_fail(LAST_ERROR, 0);
|
|
1674
|
+
}
|
|
1675
|
+
#else
|
|
1676
|
+
rb_io_write(io, rb_str_new_cstr(visible ? CSI "?25h" : CSI "?25l"));
|
|
1677
|
+
#endif
|
|
1678
|
+
return io;
|
|
1679
|
+
}
|
|
1680
|
+
|
|
1681
|
+
/*
|
|
1682
|
+
* call-seq:
|
|
1683
|
+
* io.hide_cursor -> io
|
|
1684
|
+
*
|
|
1685
|
+
* Hides the cursor.
|
|
1686
|
+
*
|
|
1687
|
+
* You must require 'io/console' to use this method.
|
|
1688
|
+
*/
|
|
1689
|
+
static VALUE
|
|
1690
|
+
console_hide_cursor(VALUE io)
|
|
1691
|
+
{
|
|
1692
|
+
return console_cursor_visibility(io, 0);
|
|
1693
|
+
}
|
|
1694
|
+
|
|
1695
|
+
/*
|
|
1696
|
+
* call-seq:
|
|
1697
|
+
* io.show_cursor -> io
|
|
1698
|
+
*
|
|
1699
|
+
* Shows the cursor.
|
|
1700
|
+
*
|
|
1701
|
+
* You must require 'io/console' to use this method.
|
|
1702
|
+
*/
|
|
1703
|
+
static VALUE
|
|
1704
|
+
console_show_cursor(VALUE io)
|
|
1705
|
+
{
|
|
1706
|
+
return console_cursor_visibility(io, 1);
|
|
1707
|
+
}
|
|
1708
|
+
|
|
1294
1709
|
/*
|
|
1295
1710
|
* call-seq:
|
|
1296
1711
|
* io.goto(line, column) -> io
|
|
@@ -1710,7 +2125,7 @@ console_dev(int argc, VALUE *argv, VALUE klass)
|
|
|
1710
2125
|
Check_Type(sym = argv[0], T_SYMBOL);
|
|
1711
2126
|
}
|
|
1712
2127
|
|
|
1713
|
-
|
|
2128
|
+
/* Force the class to be File. */
|
|
1714
2129
|
if (klass == rb_cIO) klass = rb_cFile;
|
|
1715
2130
|
|
|
1716
2131
|
if (console_dev_get(klass, &con)) {
|
|
@@ -1777,7 +2192,7 @@ console_dev(int argc, VALUE *argv, VALUE klass)
|
|
|
1777
2192
|
|
|
1778
2193
|
/*
|
|
1779
2194
|
* call-seq:
|
|
1780
|
-
* io.getch(min: nil, time: nil, intr: nil) -> char
|
|
2195
|
+
* io.getch(min: nil, time: nil, intr: nil) -> char or nil
|
|
1781
2196
|
*
|
|
1782
2197
|
* See IO#getch.
|
|
1783
2198
|
*/
|
|
@@ -1793,10 +2208,17 @@ puts_call(VALUE io)
|
|
|
1793
2208
|
return rb_io_write(io, rb_default_rs);
|
|
1794
2209
|
}
|
|
1795
2210
|
|
|
2211
|
+
static VALUE
|
|
2212
|
+
funcall_with_rs(VALUE obj, ID mid)
|
|
2213
|
+
{
|
|
2214
|
+
const VALUE rs = rb_default_rs; /* rvalue in TruffleRuby */
|
|
2215
|
+
return rb_funcallv(obj, mid, 1, &rs);
|
|
2216
|
+
}
|
|
2217
|
+
|
|
1796
2218
|
static VALUE
|
|
1797
2219
|
gets_call(VALUE io)
|
|
1798
2220
|
{
|
|
1799
|
-
return
|
|
2221
|
+
return funcall_with_rs(io, id_gets);
|
|
1800
2222
|
}
|
|
1801
2223
|
|
|
1802
2224
|
static VALUE
|
|
@@ -1819,8 +2241,7 @@ static VALUE
|
|
|
1819
2241
|
str_chomp(VALUE str)
|
|
1820
2242
|
{
|
|
1821
2243
|
if (!NIL_P(str)) {
|
|
1822
|
-
|
|
1823
|
-
rb_funcallv(str, id_chomp_bang, 1, &rs);
|
|
2244
|
+
funcall_with_rs(str, id_chomp_bang);
|
|
1824
2245
|
}
|
|
1825
2246
|
return str;
|
|
1826
2247
|
}
|
|
@@ -1881,7 +2302,7 @@ io_getpass(int argc, VALUE *argv, VALUE io)
|
|
|
1881
2302
|
* call-seq:
|
|
1882
2303
|
* io.ttyname -> string or nil
|
|
1883
2304
|
*
|
|
1884
|
-
* Returns name of associated terminal (tty) if +io+ is
|
|
2305
|
+
* Returns name of associated terminal (tty) if +io+ is a tty.
|
|
1885
2306
|
* Returns +nil+ otherwise.
|
|
1886
2307
|
*/
|
|
1887
2308
|
static VALUE
|
|
@@ -1893,20 +2314,23 @@ console_ttyname(VALUE io)
|
|
|
1893
2314
|
return rb_usascii_str_new_lit("con");
|
|
1894
2315
|
# elif defined HAVE_TTYNAME_R
|
|
1895
2316
|
{
|
|
2317
|
+
# ifdef TTYNAME_R_RETURNS_CHAR_P
|
|
2318
|
+
# define ttyname_r(fd, name, size) (ttyname_r(fd, name, size) == NULL ? errno : 0)
|
|
2319
|
+
# endif
|
|
1896
2320
|
char termname[1024], *tn = termname;
|
|
1897
2321
|
size_t size = sizeof(termname);
|
|
1898
2322
|
int e;
|
|
1899
|
-
if (ttyname_r(fd, tn, size) == 0)
|
|
2323
|
+
if ((e = ttyname_r(fd, tn, size)) == 0)
|
|
1900
2324
|
return rb_interned_str_cstr(tn);
|
|
1901
|
-
if (
|
|
2325
|
+
if (e == ERANGE) {
|
|
1902
2326
|
VALUE s = rb_str_new(0, size);
|
|
1903
2327
|
while (1) {
|
|
1904
2328
|
tn = RSTRING_PTR(s);
|
|
1905
2329
|
size = rb_str_capacity(s);
|
|
1906
|
-
if (ttyname_r(fd, tn, size) == 0) {
|
|
2330
|
+
if ((e = ttyname_r(fd, tn, size)) == 0) {
|
|
1907
2331
|
return rb_str_to_interned_str(rb_str_resize(s, strlen(tn)));
|
|
1908
2332
|
}
|
|
1909
|
-
if (
|
|
2333
|
+
if (e != ERANGE) break;
|
|
1910
2334
|
if ((size *= 2) >= INT_MAX/2) break;
|
|
1911
2335
|
rb_str_resize(s, size);
|
|
1912
2336
|
}
|
|
@@ -1931,6 +2355,103 @@ console_ttyname(VALUE io)
|
|
|
1931
2355
|
# define console_ttyname rb_f_notimplement
|
|
1932
2356
|
#endif
|
|
1933
2357
|
|
|
2358
|
+
typedef enum {
|
|
2359
|
+
platform_default,
|
|
2360
|
+
#if defined _WIN32
|
|
2361
|
+
platform_cygwin,
|
|
2362
|
+
platform_msys,
|
|
2363
|
+
#endif
|
|
2364
|
+
platform_any,
|
|
2365
|
+
|
|
2366
|
+
platform_default_bit = 1U << platform_default,
|
|
2367
|
+
#if defined _WIN32
|
|
2368
|
+
platform_cygwin_bit = 1U << platform_cygwin,
|
|
2369
|
+
platform_msys_bit = 1U << platform_msys,
|
|
2370
|
+
#endif
|
|
2371
|
+
platform_any_bit = (1U << platform_any) - 1 /* all bits */
|
|
2372
|
+
} console_platform_t;
|
|
2373
|
+
|
|
2374
|
+
/*
|
|
2375
|
+
* call-seq:
|
|
2376
|
+
* io.tty?([mode, ...]) -> true or false
|
|
2377
|
+
*
|
|
2378
|
+
* Returns +true+ if the stream is associated with a terminal device (tty),
|
|
2379
|
+
* +false+ otherwise.
|
|
2380
|
+
*
|
|
2381
|
+
* If one or more +type+s are given, returns +true+ if the stream is
|
|
2382
|
+
* associated with any of the specified tty types.
|
|
2383
|
+
*
|
|
2384
|
+
* - +nil+ : Returns the result of the default tty check, as if no type were
|
|
2385
|
+
* given. It can be combined with other types.
|
|
2386
|
+
* - +:any+ : Returns +true+ for any known kind of tty, including the
|
|
2387
|
+
* default tty.
|
|
2388
|
+
* - +:cygwin+ : Returns +true+ for cygwin tty, on Windows.
|
|
2389
|
+
* - +:msys+ : Returns +true+ for msys2 tty, on Windows.
|
|
2390
|
+
*/
|
|
2391
|
+
static VALUE
|
|
2392
|
+
console_platform_tty_p(int argc, VALUE *argv, VALUE io)
|
|
2393
|
+
{
|
|
2394
|
+
VALUE ret = Qfalse;
|
|
2395
|
+
int mode = 0;
|
|
2396
|
+
|
|
2397
|
+
if (argc > 0) {
|
|
2398
|
+
int i;
|
|
2399
|
+
for (i = 0; i < argc; ++i) {
|
|
2400
|
+
VALUE m = argv[i];
|
|
2401
|
+
if (NIL_P(m)) {
|
|
2402
|
+
mode |= platform_default_bit;
|
|
2403
|
+
continue;
|
|
2404
|
+
}
|
|
2405
|
+
Check_Type(m, T_SYMBOL);
|
|
2406
|
+
if (m == ID2SYM(rb_intern("any"))) {
|
|
2407
|
+
mode |= platform_any_bit;
|
|
2408
|
+
}
|
|
2409
|
+
#if defined _WIN32
|
|
2410
|
+
else if (m == ID2SYM(rb_intern("cygwin"))) {
|
|
2411
|
+
mode |= platform_cygwin_bit;
|
|
2412
|
+
}
|
|
2413
|
+
else if (m == ID2SYM(rb_intern("msys"))) {
|
|
2414
|
+
mode |= platform_msys_bit;
|
|
2415
|
+
}
|
|
2416
|
+
#endif
|
|
2417
|
+
else {
|
|
2418
|
+
rb_raise(rb_eArgError, "unknown tty type: %+" PRIsVALUE, m);
|
|
2419
|
+
}
|
|
2420
|
+
}
|
|
2421
|
+
}
|
|
2422
|
+
if ((mode & platform_default_bit) || (mode == 0)) {
|
|
2423
|
+
ret = rb_call_super(0, 0);
|
|
2424
|
+
}
|
|
2425
|
+
if ((mode & ~platform_default_bit) && !RTEST(ret)) {
|
|
2426
|
+
#if defined _WIN32
|
|
2427
|
+
if (mode & (platform_cygwin_bit | platform_msys_bit)) {
|
|
2428
|
+
struct {
|
|
2429
|
+
FILE_NAME_INFO info;
|
|
2430
|
+
WCHAR rest[MAX_PATH];
|
|
2431
|
+
} buffer;
|
|
2432
|
+
|
|
2433
|
+
HANDLE h = (HANDLE)rb_w32_get_osfhandle(GetReadFD(io));
|
|
2434
|
+
if ((GetFileType(h) == FILE_TYPE_PIPE) &&
|
|
2435
|
+
GetFileInformationByHandleEx(h, FileNameInfo, &buffer, sizeof(buffer))) {
|
|
2436
|
+
WCHAR *const name = buffer.info.FileName;
|
|
2437
|
+
DWORD len = buffer.info.FileNameLength / sizeof(WCHAR);
|
|
2438
|
+
name[len] = L'\0';
|
|
2439
|
+
# define tty_pipe_p(type) \
|
|
2440
|
+
(memcmp(name, L"\\" #type "-", sizeof(L"\\" #type)) == 0 && \
|
|
2441
|
+
wcsstr(&name[rb_strlen_lit("\\" #type "-")], L"-pty") != NULL)
|
|
2442
|
+
if (!ret && (mode & platform_cygwin_bit)) {
|
|
2443
|
+
ret = tty_pipe_p(cygwin);
|
|
2444
|
+
}
|
|
2445
|
+
if (!ret && (mode & platform_msys_bit)) {
|
|
2446
|
+
ret = tty_pipe_p(msys);
|
|
2447
|
+
}
|
|
2448
|
+
}
|
|
2449
|
+
}
|
|
2450
|
+
#endif
|
|
2451
|
+
}
|
|
2452
|
+
return ret;
|
|
2453
|
+
}
|
|
2454
|
+
|
|
1934
2455
|
/*
|
|
1935
2456
|
* IO console methods
|
|
1936
2457
|
*/
|
|
@@ -1952,6 +2473,7 @@ Init_console(void)
|
|
|
1952
2473
|
id_flush = rb_intern("flush");
|
|
1953
2474
|
id_chomp_bang = rb_intern("chomp!");
|
|
1954
2475
|
id_close = rb_intern("close");
|
|
2476
|
+
id_timeout = rb_intern("timeout");
|
|
1955
2477
|
#define init_rawmode_opt_id(name) \
|
|
1956
2478
|
rawmode_opt_ids[kwd_##name] = rb_intern(#name)
|
|
1957
2479
|
init_rawmode_opt_id(min);
|
|
@@ -1966,11 +2488,31 @@ Init_console(void)
|
|
|
1966
2488
|
void
|
|
1967
2489
|
InitVM_console(void)
|
|
1968
2490
|
{
|
|
2491
|
+
/* :nodoc: */
|
|
2492
|
+
VALUE mConsole = rb_define_module_under(rb_cIO, "Console");
|
|
2493
|
+
#ifdef _WIN32
|
|
2494
|
+
/* :nodoc: */
|
|
2495
|
+
VALUE mWindows = rb_define_module_under(mConsole, "Windows");
|
|
2496
|
+
#define define_win32_const(name) rb_define_const(mWindows, #name, UINT2NUM(name))
|
|
2497
|
+
EACH_VK(define_win32_const,;);
|
|
2498
|
+
define_win32_const(RIGHT_ALT_PRESSED);
|
|
2499
|
+
define_win32_const(LEFT_ALT_PRESSED);
|
|
2500
|
+
define_win32_const(RIGHT_CTRL_PRESSED);
|
|
2501
|
+
define_win32_const(LEFT_CTRL_PRESSED);
|
|
2502
|
+
define_win32_const(SHIFT_PRESSED);
|
|
2503
|
+
define_win32_const(NUMLOCK_ON);
|
|
2504
|
+
define_win32_const(SCROLLLOCK_ON);
|
|
2505
|
+
define_win32_const(CAPSLOCK_ON);
|
|
2506
|
+
define_win32_const(ENHANCED_KEY);
|
|
2507
|
+
#undef define_win32_const
|
|
2508
|
+
#endif
|
|
2509
|
+
|
|
1969
2510
|
rb_define_method(rb_cIO, "raw", console_raw, -1);
|
|
1970
2511
|
rb_define_method(rb_cIO, "raw!", console_set_raw, -1);
|
|
1971
2512
|
rb_define_method(rb_cIO, "cooked", console_cooked, 0);
|
|
1972
2513
|
rb_define_method(rb_cIO, "cooked!", console_set_cooked, 0);
|
|
1973
2514
|
rb_define_method(rb_cIO, "getch", console_getch, -1);
|
|
2515
|
+
rb_define_method(rb_cIO, "input_pending?", console_input_pending_p, 0);
|
|
1974
2516
|
rb_define_method(rb_cIO, "echo=", console_set_echo, 1);
|
|
1975
2517
|
rb_define_method(rb_cIO, "echo?", console_echo_p, 0);
|
|
1976
2518
|
rb_define_method(rb_cIO, "console_mode", console_conmode_get, 0);
|
|
@@ -1985,6 +2527,8 @@ InitVM_console(void)
|
|
|
1985
2527
|
rb_define_method(rb_cIO, "goto", console_goto, 2);
|
|
1986
2528
|
rb_define_method(rb_cIO, "cursor", console_cursor_pos, 0);
|
|
1987
2529
|
rb_define_method(rb_cIO, "cursor=", console_cursor_set, 1);
|
|
2530
|
+
rb_define_method(rb_cIO, "hide_cursor", console_hide_cursor, 0);
|
|
2531
|
+
rb_define_method(rb_cIO, "show_cursor", console_show_cursor, 0);
|
|
1988
2532
|
rb_define_method(rb_cIO, "cursor_up", console_cursor_up, 1);
|
|
1989
2533
|
rb_define_method(rb_cIO, "cursor_down", console_cursor_down, 1);
|
|
1990
2534
|
rb_define_method(rb_cIO, "cursor_left", console_cursor_left, 1);
|
|
@@ -1996,27 +2540,64 @@ InitVM_console(void)
|
|
|
1996
2540
|
rb_define_method(rb_cIO, "scroll_backward", console_scroll_backward, 1);
|
|
1997
2541
|
rb_define_method(rb_cIO, "clear_screen", console_clear_screen, 0);
|
|
1998
2542
|
rb_define_method(rb_cIO, "pressed?", console_key_pressed_p, 1);
|
|
2543
|
+
rb_define_method(rb_cIO, "console_input_events", console_input_events, -1);
|
|
1999
2544
|
rb_define_method(rb_cIO, "check_winsize_changed", console_check_winsize_changed, 0);
|
|
2000
2545
|
rb_define_method(rb_cIO, "getpass", console_getpass, -1);
|
|
2001
2546
|
rb_define_method(rb_cIO, "ttyname", console_ttyname, 0);
|
|
2547
|
+
{
|
|
2548
|
+
/* :nodoc: */
|
|
2549
|
+
VALUE platform = rb_define_module_under(rb_cIO, "platform_tty");
|
|
2550
|
+
{
|
|
2551
|
+
VALUE rb_cIO = platform;
|
|
2552
|
+
rb_define_method(rb_cIO, "tty?", console_platform_tty_p, -1);
|
|
2553
|
+
rb_define_method(rb_cIO, "isatty", console_platform_tty_p, -1);
|
|
2554
|
+
}
|
|
2555
|
+
#ifdef HAVE_RB_PREPEND_MODULE
|
|
2556
|
+
rb_prepend_module(rb_cIO, platform);
|
|
2557
|
+
#else
|
|
2558
|
+
rb_funcall(rb_cIO, rb_intern_const("prepend"), 1, platform);
|
|
2559
|
+
#endif
|
|
2560
|
+
}
|
|
2002
2561
|
rb_define_singleton_method(rb_cIO, "console", console_dev, -1);
|
|
2003
2562
|
{
|
|
2004
|
-
/* :
|
|
2563
|
+
/* :nodoc: */
|
|
2005
2564
|
VALUE mReadable = rb_define_module_under(rb_cIO, "generic_readable");
|
|
2006
|
-
/* :startdoc: */
|
|
2007
2565
|
rb_define_method(mReadable, "getch", io_getch, -1);
|
|
2008
2566
|
rb_define_method(mReadable, "getpass", io_getpass, -1);
|
|
2009
2567
|
}
|
|
2010
2568
|
{
|
|
2011
|
-
/* :
|
|
2012
|
-
|
|
2013
|
-
|
|
2569
|
+
/* :nodoc: */
|
|
2570
|
+
VALUE version = rb_obj_freeze(rb_str_new_cstr(IO_CONSOLE_VERSION));
|
|
2571
|
+
ID cid, deprecate_constant = rb_intern_const("deprecate_constant");
|
|
2572
|
+
rb_define_const(mConsole, "VERSION", version);
|
|
2573
|
+
/* :nodoc: */
|
|
2574
|
+
cConmode = rb_define_class_under(mConsole, "Mode", rb_cObject);
|
|
2575
|
+
|
|
2576
|
+
/* old internal names; do not use */
|
|
2577
|
+
cid = rb_intern_const("ConsoleMode");
|
|
2578
|
+
rb_const_set(rb_cIO, cid, cConmode);
|
|
2579
|
+
rb_funcall(rb_cIO, deprecate_constant, 1, ID2SYM(cid));
|
|
2580
|
+
cid = rb_intern_const("VERSION");
|
|
2581
|
+
rb_const_set(cConmode, cid, version);
|
|
2582
|
+
rb_funcall(cConmode, deprecate_constant, 1, ID2SYM(cid));
|
|
2583
|
+
|
|
2014
2584
|
rb_define_alloc_func(cConmode, conmode_alloc);
|
|
2015
2585
|
rb_undef_method(cConmode, "initialize");
|
|
2016
2586
|
rb_define_method(cConmode, "initialize_copy", conmode_init_copy, 1);
|
|
2587
|
+
rb_define_method(cConmode, "echo?", conmode_get_echo, 0);
|
|
2588
|
+
rb_define_method(cConmode, "echo", conmode_get_echo, 0);
|
|
2017
2589
|
rb_define_method(cConmode, "echo=", conmode_set_echo, 1);
|
|
2018
2590
|
rb_define_method(cConmode, "raw!", conmode_set_raw, -1);
|
|
2019
2591
|
rb_define_method(cConmode, "raw", conmode_raw_new, -1);
|
|
2020
|
-
|
|
2592
|
+
rb_define_method(cConmode, "min", conmode_get_min, 0);
|
|
2593
|
+
rb_define_method(cConmode, "min=", conmode_set_min, 1);
|
|
2594
|
+
rb_define_method(cConmode, "time", conmode_get_time, 0);
|
|
2595
|
+
rb_define_method(cConmode, "time=", conmode_set_time, 1);
|
|
2596
|
+
#ifdef _WIN32
|
|
2597
|
+
rb_define_method(cConmode, "virtual_terminal_processing?", conmode_virtual_terminal_processing_p, 0);
|
|
2598
|
+
rb_define_method(cConmode, "virtual_terminal_processing=", conmode_set_virtual_terminal_processing, 1);
|
|
2599
|
+
rb_define_method(cConmode, "wrap_at_eol_output?", conmode_wrap_at_eol_output_p, 0);
|
|
2600
|
+
rb_define_method(cConmode, "wrap_at_eol_output=", conmode_set_wrap_at_eol_output, 1);
|
|
2601
|
+
#endif
|
|
2021
2602
|
}
|
|
2022
2603
|
}
|