io-console 0.8.1 → 0.9.0
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 +590 -44
- data/ext/io/console/extconf.rb +13 -14
- data/ext/io/console/win32_vk.inc +313 -165
- 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.0";
|
|
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)); \
|
|
@@ -550,7 +545,7 @@ nogvl_getch(void *p)
|
|
|
550
545
|
|
|
551
546
|
/*
|
|
552
547
|
* call-seq:
|
|
553
|
-
* io.getch(min: nil, time: nil, intr: nil) -> char
|
|
548
|
+
* io.getch(min: nil, time: nil, intr: nil) -> char or nil
|
|
554
549
|
*
|
|
555
550
|
* Reads and returns a character in raw mode.
|
|
556
551
|
*
|
|
@@ -635,6 +630,43 @@ console_getch(int argc, VALUE *argv, VALUE io)
|
|
|
635
630
|
#endif
|
|
636
631
|
}
|
|
637
632
|
|
|
633
|
+
/*
|
|
634
|
+
* call-seq:
|
|
635
|
+
* io.input_pending? -> true or false
|
|
636
|
+
*
|
|
637
|
+
* Returns whether input can be read without blocking.
|
|
638
|
+
*
|
|
639
|
+
* You must require 'io/console' to use this method.
|
|
640
|
+
*/
|
|
641
|
+
static VALUE
|
|
642
|
+
console_input_pending_p(VALUE io)
|
|
643
|
+
{
|
|
644
|
+
rb_io_t *fptr;
|
|
645
|
+
|
|
646
|
+
GetOpenFile(io, fptr);
|
|
647
|
+
if (rb_io_read_pending(fptr)) return Qtrue;
|
|
648
|
+
#ifdef _WIN32
|
|
649
|
+
{
|
|
650
|
+
DWORD mode;
|
|
651
|
+
HANDLE h = (HANDLE)rb_w32_get_osfhandle(GetReadFD(io));
|
|
652
|
+
|
|
653
|
+
if (GetConsoleMode(h, &mode)) return _kbhit() ? Qtrue : Qfalse;
|
|
654
|
+
}
|
|
655
|
+
#endif
|
|
656
|
+
#if defined HAVE_RB_IO_WAIT
|
|
657
|
+
return RTEST(rb_io_wait(io, RB_INT2NUM(RUBY_IO_READABLE), INT2FIX(0))) ? Qtrue : Qfalse;
|
|
658
|
+
#else
|
|
659
|
+
{
|
|
660
|
+
struct timeval timeout = {0, 0};
|
|
661
|
+
int result;
|
|
662
|
+
|
|
663
|
+
result = rb_wait_for_single_fd(fptr->fd, RB_WAITFD_IN, &timeout);
|
|
664
|
+
if (result < 0) sys_fail(io);
|
|
665
|
+
return (result & RB_WAITFD_IN) ? Qtrue : Qfalse;
|
|
666
|
+
}
|
|
667
|
+
#endif
|
|
668
|
+
}
|
|
669
|
+
|
|
638
670
|
/*
|
|
639
671
|
* call-seq:
|
|
640
672
|
* io.noecho {|io| }
|
|
@@ -762,6 +794,70 @@ conmode_raw_new(int argc, VALUE *argv, VALUE obj)
|
|
|
762
794
|
return conmode_new(rb_obj_class(obj), &t);
|
|
763
795
|
}
|
|
764
796
|
|
|
797
|
+
#ifdef _WIN32
|
|
798
|
+
/*
|
|
799
|
+
* call-seq:
|
|
800
|
+
* mode.virtual_terminal_processing? -> true or false
|
|
801
|
+
*
|
|
802
|
+
* Returns whether virtual terminal sequences are processed on output.
|
|
803
|
+
*/
|
|
804
|
+
static VALUE
|
|
805
|
+
conmode_virtual_terminal_processing_p(VALUE obj)
|
|
806
|
+
{
|
|
807
|
+
conmode *t = rb_check_typeddata(obj, &conmode_type);
|
|
808
|
+
return (*t & ENABLE_VIRTUAL_TERMINAL_PROCESSING) ? Qtrue : Qfalse;
|
|
809
|
+
}
|
|
810
|
+
|
|
811
|
+
/*
|
|
812
|
+
* call-seq:
|
|
813
|
+
* mode.virtual_terminal_processing = enabled
|
|
814
|
+
*
|
|
815
|
+
* Enables or disables virtual terminal sequence processing in +mode+.
|
|
816
|
+
* Assign +mode+ to IO#console_mode= to apply the change.
|
|
817
|
+
*/
|
|
818
|
+
static VALUE
|
|
819
|
+
conmode_set_virtual_terminal_processing(VALUE obj, VALUE enabled)
|
|
820
|
+
{
|
|
821
|
+
conmode *t = rb_check_typeddata(obj, &conmode_type);
|
|
822
|
+
if (RTEST(enabled))
|
|
823
|
+
*t |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
|
|
824
|
+
else
|
|
825
|
+
*t &= ~ENABLE_VIRTUAL_TERMINAL_PROCESSING;
|
|
826
|
+
return obj;
|
|
827
|
+
}
|
|
828
|
+
|
|
829
|
+
/*
|
|
830
|
+
* call-seq:
|
|
831
|
+
* mode.wrap_at_eol_output? -> true or false
|
|
832
|
+
*
|
|
833
|
+
* Returns whether output wraps at the end of a line.
|
|
834
|
+
*/
|
|
835
|
+
static VALUE
|
|
836
|
+
conmode_wrap_at_eol_output_p(VALUE obj)
|
|
837
|
+
{
|
|
838
|
+
conmode *t = rb_check_typeddata(obj, &conmode_type);
|
|
839
|
+
return (*t & ENABLE_WRAP_AT_EOL_OUTPUT) ? Qtrue : Qfalse;
|
|
840
|
+
}
|
|
841
|
+
|
|
842
|
+
/*
|
|
843
|
+
* call-seq:
|
|
844
|
+
* mode.wrap_at_eol_output = enabled
|
|
845
|
+
*
|
|
846
|
+
* Enables or disables wrapping at the end of a line in +mode+.
|
|
847
|
+
* Assign +mode+ to IO#console_mode= to apply the change.
|
|
848
|
+
*/
|
|
849
|
+
static VALUE
|
|
850
|
+
conmode_set_wrap_at_eol_output(VALUE obj, VALUE enabled)
|
|
851
|
+
{
|
|
852
|
+
conmode *t = rb_check_typeddata(obj, &conmode_type);
|
|
853
|
+
if (RTEST(enabled))
|
|
854
|
+
*t |= ENABLE_WRAP_AT_EOL_OUTPUT;
|
|
855
|
+
else
|
|
856
|
+
*t &= ~ENABLE_WRAP_AT_EOL_OUTPUT;
|
|
857
|
+
return obj;
|
|
858
|
+
}
|
|
859
|
+
#endif
|
|
860
|
+
|
|
765
861
|
/*
|
|
766
862
|
* call-seq:
|
|
767
863
|
* io.console_mode -> mode
|
|
@@ -840,6 +936,9 @@ console_winsize(VALUE io)
|
|
|
840
936
|
return rb_assoc_new(INT2NUM(winsize_row(&ws)), INT2NUM(winsize_col(&ws)));
|
|
841
937
|
}
|
|
842
938
|
|
|
939
|
+
static VALUE console_scroll(VALUE io, int line);
|
|
940
|
+
static VALUE console_goto(VALUE io, VALUE y, VALUE x);
|
|
941
|
+
|
|
843
942
|
/*
|
|
844
943
|
* call-seq:
|
|
845
944
|
* io.winsize = [rows, columns]
|
|
@@ -856,7 +955,8 @@ console_set_winsize(VALUE io, VALUE size)
|
|
|
856
955
|
#if defined _WIN32
|
|
857
956
|
HANDLE wh;
|
|
858
957
|
int newrow, newcol;
|
|
859
|
-
|
|
958
|
+
COORD oldsize;
|
|
959
|
+
SMALL_RECT oldwindow;
|
|
860
960
|
#endif
|
|
861
961
|
VALUE row, col, xpixel, ypixel;
|
|
862
962
|
const VALUE *sz;
|
|
@@ -891,18 +991,62 @@ console_set_winsize(VALUE io, VALUE size)
|
|
|
891
991
|
if (!GetConsoleScreenBufferInfo(wh, &ws)) {
|
|
892
992
|
rb_syserr_fail(LAST_ERROR, "GetConsoleScreenBufferInfo");
|
|
893
993
|
}
|
|
994
|
+
oldsize = ws.dwSize;
|
|
995
|
+
oldwindow = ws.srWindow;
|
|
996
|
+
if (ws.srWindow.Right + 1 < newcol) {
|
|
997
|
+
ws.dwSize.X = newcol;
|
|
998
|
+
}
|
|
999
|
+
if (ws.dwSize.Y < newrow) {
|
|
1000
|
+
ws.dwSize.Y = newrow;
|
|
1001
|
+
}
|
|
1002
|
+
/* expand screen buffer first if needed */
|
|
1003
|
+
if (!SetConsoleScreenBufferSize(wh, ws.dwSize)) {
|
|
1004
|
+
rb_syserr_fail(LAST_ERROR, "SetConsoleScreenBufferInfo");
|
|
1005
|
+
}
|
|
1006
|
+
/* refresh ws for new dwMaximumWindowSize */
|
|
1007
|
+
if (!GetConsoleScreenBufferInfo(wh, &ws)) {
|
|
1008
|
+
rb_syserr_fail(LAST_ERROR, "GetConsoleScreenBufferInfo");
|
|
1009
|
+
}
|
|
1010
|
+
/* check new size before modifying buffer content */
|
|
1011
|
+
if (newrow <= 0 || newcol <= 0 ||
|
|
1012
|
+
newrow > ws.dwMaximumWindowSize.Y ||
|
|
1013
|
+
newcol > ws.dwMaximumWindowSize.X) {
|
|
1014
|
+
SetConsoleScreenBufferSize(wh, oldsize);
|
|
1015
|
+
/* remove scrollbar if possible */
|
|
1016
|
+
SetConsoleWindowInfo(wh, TRUE, &oldwindow);
|
|
1017
|
+
rb_raise(rb_eArgError, "out of range winsize: [%d, %d]", newrow, newcol);
|
|
1018
|
+
}
|
|
1019
|
+
/* shrink screen buffer width */
|
|
894
1020
|
ws.dwSize.X = newcol;
|
|
895
|
-
|
|
1021
|
+
/* shrink screen buffer height if window height were the same */
|
|
1022
|
+
if (oldsize.Y == ws.srWindow.Bottom - ws.srWindow.Top + 1) {
|
|
1023
|
+
ws.dwSize.Y = newrow;
|
|
1024
|
+
}
|
|
896
1025
|
ws.srWindow.Left = 0;
|
|
897
|
-
ws.srWindow.
|
|
898
|
-
ws.srWindow.
|
|
899
|
-
ws.srWindow.Bottom
|
|
1026
|
+
ws.srWindow.Right = newcol - 1;
|
|
1027
|
+
ws.srWindow.Bottom = ws.srWindow.Top + newrow -1;
|
|
1028
|
+
if (ws.dwCursorPosition.Y > ws.srWindow.Bottom) {
|
|
1029
|
+
console_scroll(io, ws.dwCursorPosition.Y - ws.srWindow.Bottom);
|
|
1030
|
+
ws.dwCursorPosition.Y = ws.srWindow.Bottom;
|
|
1031
|
+
console_goto(io, INT2FIX(ws.dwCursorPosition.Y), INT2FIX(ws.dwCursorPosition.X));
|
|
1032
|
+
}
|
|
1033
|
+
if (ws.srWindow.Bottom > ws.dwSize.Y - 1) {
|
|
1034
|
+
console_scroll(io, ws.srWindow.Bottom - (ws.dwSize.Y - 1));
|
|
1035
|
+
ws.dwCursorPosition.Y -= ws.srWindow.Bottom - (ws.dwSize.Y - 1);
|
|
1036
|
+
console_goto(io, INT2FIX(ws.dwCursorPosition.Y), INT2FIX(ws.dwCursorPosition.X));
|
|
1037
|
+
ws.srWindow.Bottom = ws.dwSize.Y - 1;
|
|
1038
|
+
}
|
|
1039
|
+
ws.srWindow.Top = ws.srWindow.Bottom - (newrow - 1);
|
|
1040
|
+
/* perform changes to winsize */
|
|
900
1041
|
if (!SetConsoleWindowInfo(wh, TRUE, &ws.srWindow)) {
|
|
901
|
-
|
|
1042
|
+
int last_error = LAST_ERROR;
|
|
1043
|
+
SetConsoleScreenBufferSize(wh, oldsize);
|
|
1044
|
+
rb_syserr_fail(last_error, "SetConsoleWindowInfo");
|
|
902
1045
|
}
|
|
903
|
-
/*
|
|
904
|
-
if (
|
|
905
|
-
|
|
1046
|
+
/* perform screen buffer shrinking if necessary */
|
|
1047
|
+
if ((ws.dwSize.Y < oldsize.Y || ws.dwSize.X < oldsize.X) &&
|
|
1048
|
+
!SetConsoleScreenBufferSize(wh, ws.dwSize)) {
|
|
1049
|
+
rb_syserr_fail(LAST_ERROR, "SetConsoleScreenBufferInfo");
|
|
906
1050
|
}
|
|
907
1051
|
/* remove scrollbar if possible */
|
|
908
1052
|
if (!SetConsoleWindowInfo(wh, TRUE, &ws.srWindow)) {
|
|
@@ -914,12 +1058,207 @@ console_set_winsize(VALUE io, VALUE size)
|
|
|
914
1058
|
#endif
|
|
915
1059
|
|
|
916
1060
|
#ifdef _WIN32
|
|
1061
|
+
enum console_input_handle_index {
|
|
1062
|
+
console_input_handle,
|
|
1063
|
+
console_input_wakeup,
|
|
1064
|
+
console_input_handle_count
|
|
1065
|
+
};
|
|
1066
|
+
|
|
1067
|
+
typedef struct {
|
|
1068
|
+
HANDLE handles[console_input_handle_count];
|
|
1069
|
+
INPUT_RECORD *records;
|
|
1070
|
+
DWORD length;
|
|
1071
|
+
DWORD count;
|
|
1072
|
+
DWORD timeout;
|
|
1073
|
+
DWORD wait_result;
|
|
1074
|
+
DWORD error;
|
|
1075
|
+
BOOL result;
|
|
1076
|
+
} read_console_input_args_t;
|
|
1077
|
+
|
|
1078
|
+
static void *
|
|
1079
|
+
nogvl_read_console_input(void *ptr)
|
|
1080
|
+
{
|
|
1081
|
+
read_console_input_args_t *args = ptr;
|
|
1082
|
+
|
|
1083
|
+
args->wait_result = WaitForMultipleObjects(console_input_handle_count,
|
|
1084
|
+
args->handles, FALSE, args->timeout);
|
|
1085
|
+
if (args->wait_result == WAIT_OBJECT_0 + console_input_handle) {
|
|
1086
|
+
args->result = ReadConsoleInputW(args->handles[console_input_handle],
|
|
1087
|
+
args->records, args->length, &args->count);
|
|
1088
|
+
if (!args->result) args->error = GetLastError();
|
|
1089
|
+
}
|
|
1090
|
+
else if (args->wait_result == WAIT_FAILED) {
|
|
1091
|
+
args->error = GetLastError();
|
|
1092
|
+
}
|
|
1093
|
+
return 0;
|
|
1094
|
+
}
|
|
1095
|
+
|
|
1096
|
+
static void
|
|
1097
|
+
ubf_console_input(void *ptr)
|
|
1098
|
+
{
|
|
1099
|
+
read_console_input_args_t *args = ptr;
|
|
1100
|
+
SetEvent(args->handles[console_input_wakeup]);
|
|
1101
|
+
}
|
|
1102
|
+
|
|
1103
|
+
static void
|
|
1104
|
+
console_input_event_set(VALUE event, const char *name, VALUE value)
|
|
1105
|
+
{
|
|
1106
|
+
rb_hash_aset(event, ID2SYM(rb_intern(name)), value);
|
|
1107
|
+
}
|
|
1108
|
+
|
|
1109
|
+
static VALUE
|
|
1110
|
+
console_input_event(const INPUT_RECORD *record)
|
|
1111
|
+
{
|
|
1112
|
+
VALUE event = rb_hash_new();
|
|
1113
|
+
|
|
1114
|
+
switch (record->EventType) {
|
|
1115
|
+
case KEY_EVENT:
|
|
1116
|
+
console_input_event_set(event, "type", ID2SYM(rb_intern("key")));
|
|
1117
|
+
console_input_event_set(event, "key_down", record->Event.KeyEvent.bKeyDown ? Qtrue : Qfalse);
|
|
1118
|
+
console_input_event_set(event, "repeat_count", UINT2NUM(record->Event.KeyEvent.wRepeatCount));
|
|
1119
|
+
console_input_event_set(event, "virtual_key_code", UINT2NUM(record->Event.KeyEvent.wVirtualKeyCode));
|
|
1120
|
+
console_input_event_set(event, "virtual_scan_code", UINT2NUM(record->Event.KeyEvent.wVirtualScanCode));
|
|
1121
|
+
console_input_event_set(event, "unicode_char", UINT2NUM(record->Event.KeyEvent.uChar.UnicodeChar));
|
|
1122
|
+
console_input_event_set(event, "control_key_state", UINT2NUM(record->Event.KeyEvent.dwControlKeyState));
|
|
1123
|
+
break;
|
|
1124
|
+
case MOUSE_EVENT:
|
|
1125
|
+
console_input_event_set(event, "type", ID2SYM(rb_intern("mouse")));
|
|
1126
|
+
console_input_event_set(event, "position", rb_assoc_new(
|
|
1127
|
+
INT2NUM(record->Event.MouseEvent.dwMousePosition.Y),
|
|
1128
|
+
INT2NUM(record->Event.MouseEvent.dwMousePosition.X)));
|
|
1129
|
+
console_input_event_set(event, "button_state", UINT2NUM(record->Event.MouseEvent.dwButtonState));
|
|
1130
|
+
console_input_event_set(event, "control_key_state", UINT2NUM(record->Event.MouseEvent.dwControlKeyState));
|
|
1131
|
+
console_input_event_set(event, "event_flags", UINT2NUM(record->Event.MouseEvent.dwEventFlags));
|
|
1132
|
+
break;
|
|
1133
|
+
case WINDOW_BUFFER_SIZE_EVENT:
|
|
1134
|
+
console_input_event_set(event, "type", ID2SYM(rb_intern("window_buffer_size")));
|
|
1135
|
+
console_input_event_set(event, "size", rb_assoc_new(
|
|
1136
|
+
INT2NUM(record->Event.WindowBufferSizeEvent.dwSize.Y),
|
|
1137
|
+
INT2NUM(record->Event.WindowBufferSizeEvent.dwSize.X)));
|
|
1138
|
+
break;
|
|
1139
|
+
case MENU_EVENT:
|
|
1140
|
+
console_input_event_set(event, "type", ID2SYM(rb_intern("menu")));
|
|
1141
|
+
console_input_event_set(event, "command_id", UINT2NUM(record->Event.MenuEvent.dwCommandId));
|
|
1142
|
+
break;
|
|
1143
|
+
case FOCUS_EVENT:
|
|
1144
|
+
console_input_event_set(event, "type", ID2SYM(rb_intern("focus")));
|
|
1145
|
+
console_input_event_set(event, "set_focus", record->Event.FocusEvent.bSetFocus ? Qtrue : Qfalse);
|
|
1146
|
+
break;
|
|
1147
|
+
default:
|
|
1148
|
+
console_input_event_set(event, "type", UINT2NUM(record->EventType));
|
|
1149
|
+
break;
|
|
1150
|
+
}
|
|
1151
|
+
|
|
1152
|
+
return event;
|
|
1153
|
+
}
|
|
1154
|
+
|
|
1155
|
+
static VALUE
|
|
1156
|
+
console_input_events_read(VALUE vargs)
|
|
1157
|
+
{
|
|
1158
|
+
read_console_input_args_t *args = (read_console_input_args_t *)vargs;
|
|
1159
|
+
VALUE events;
|
|
1160
|
+
DWORD i;
|
|
1161
|
+
|
|
1162
|
+
rb_thread_call_without_gvl(nogvl_read_console_input, args,
|
|
1163
|
+
ubf_console_input, args);
|
|
1164
|
+
if (args->wait_result == WAIT_TIMEOUT) return rb_ary_new();
|
|
1165
|
+
if (args->wait_result != WAIT_OBJECT_0 + console_input_handle ||
|
|
1166
|
+
!args->result) {
|
|
1167
|
+
rb_syserr_fail(rb_w32_map_errno(args->error), 0);
|
|
1168
|
+
}
|
|
1169
|
+
|
|
1170
|
+
events = rb_ary_new_capa(args->count);
|
|
1171
|
+
for (i = 0; i < args->count; ++i) {
|
|
1172
|
+
rb_ary_push(events, console_input_event(&args->records[i]));
|
|
1173
|
+
}
|
|
1174
|
+
return events;
|
|
1175
|
+
}
|
|
1176
|
+
|
|
1177
|
+
static VALUE
|
|
1178
|
+
console_input_events_ensure(VALUE vargs)
|
|
1179
|
+
{
|
|
1180
|
+
read_console_input_args_t *args = (read_console_input_args_t *)vargs;
|
|
1181
|
+
|
|
1182
|
+
CloseHandle(args->handles[console_input_wakeup]);
|
|
1183
|
+
xfree(args->records);
|
|
1184
|
+
return Qnil;
|
|
1185
|
+
}
|
|
1186
|
+
|
|
1187
|
+
/*
|
|
1188
|
+
* call-seq:
|
|
1189
|
+
* io.console_input_events([max_events], timeout: nil) -> array
|
|
1190
|
+
*
|
|
1191
|
+
* Reads up to +max_events+ console input events, preserving their order.
|
|
1192
|
+
* The default is one event. Blocks until at least one event is available,
|
|
1193
|
+
* or for +timeout+ seconds if specified. Returns an empty Array on timeout.
|
|
1194
|
+
*
|
|
1195
|
+
* Each event is returned as a Hash. The +:type+ and remaining keys are:
|
|
1196
|
+
*
|
|
1197
|
+
* - +:key+ : +:key_down+, +:repeat_count+, +:virtual_key_code+,
|
|
1198
|
+
* +:virtual_scan_code+, +:unicode_char+, and +:control_key_state+.
|
|
1199
|
+
* - +:mouse+ : +:position+ ([row, column]), +:button_state+,
|
|
1200
|
+
* +:control_key_state+, and +:event_flags+.
|
|
1201
|
+
* - +:window_buffer_size+ : +:size+ ([rows, columns]).
|
|
1202
|
+
* - +:menu+ : +:command_id+.
|
|
1203
|
+
* - +:focus+ : +:set_focus+.
|
|
1204
|
+
*
|
|
1205
|
+
* This method is Windows only.
|
|
1206
|
+
*
|
|
1207
|
+
* You must require 'io/console' to use this method.
|
|
1208
|
+
*/
|
|
1209
|
+
static VALUE
|
|
1210
|
+
console_input_events(int argc, VALUE *argv, VALUE io)
|
|
1211
|
+
{
|
|
1212
|
+
VALUE vmax = Qnil, vopts = Qnil, vtimeout = Qundef;
|
|
1213
|
+
VALUE values[1];
|
|
1214
|
+
ID keywords[1] = {id_timeout};
|
|
1215
|
+
DWORD max_events = 1;
|
|
1216
|
+
read_console_input_args_t args;
|
|
1217
|
+
|
|
1218
|
+
rb_scan_args(argc, argv, "01:", &vmax, &vopts);
|
|
1219
|
+
if (rb_get_kwargs(vopts, keywords, 0, 1, values)) {
|
|
1220
|
+
vtimeout = values[0];
|
|
1221
|
+
}
|
|
1222
|
+
if (!NIL_P(vmax)) {
|
|
1223
|
+
max_events = NUM2UINT(vmax);
|
|
1224
|
+
if (max_events == 0) rb_raise(rb_eArgError, "max_events must be positive");
|
|
1225
|
+
}
|
|
1226
|
+
|
|
1227
|
+
args.timeout = INFINITE;
|
|
1228
|
+
if (!NIL_OR_UNDEF_P(vtimeout)) {
|
|
1229
|
+
struct timeval timeout = rb_time_interval(vtimeout);
|
|
1230
|
+
uint64_t milliseconds = (uint64_t)timeout.tv_sec * 1000;
|
|
1231
|
+
milliseconds += ((uint64_t)timeout.tv_usec + 999) / 1000;
|
|
1232
|
+
args.timeout = milliseconds < INFINITE ? (DWORD)milliseconds : INFINITE - 1;
|
|
1233
|
+
}
|
|
1234
|
+
|
|
1235
|
+
args.handles[console_input_handle] =
|
|
1236
|
+
(HANDLE)rb_w32_get_osfhandle(GetReadFD(io));
|
|
1237
|
+
args.records = ALLOC_N(INPUT_RECORD, max_events);
|
|
1238
|
+
args.handles[console_input_wakeup] = CreateEvent(NULL, FALSE, FALSE, NULL);
|
|
1239
|
+
if (!args.handles[console_input_wakeup]) {
|
|
1240
|
+
int error = LAST_ERROR;
|
|
1241
|
+
xfree(args.records);
|
|
1242
|
+
rb_syserr_fail(error, 0);
|
|
1243
|
+
}
|
|
1244
|
+
args.length = max_events;
|
|
1245
|
+
args.count = 0;
|
|
1246
|
+
args.wait_result = WAIT_FAILED;
|
|
1247
|
+
args.error = ERROR_SUCCESS;
|
|
1248
|
+
args.result = FALSE;
|
|
1249
|
+
return rb_ensure(console_input_events_read, (VALUE)&args,
|
|
1250
|
+
console_input_events_ensure, (VALUE)&args);
|
|
1251
|
+
}
|
|
1252
|
+
|
|
917
1253
|
/*
|
|
918
1254
|
* call-seq:
|
|
919
1255
|
* io.check_winsize_changed { ... } -> io
|
|
920
1256
|
*
|
|
921
1257
|
* Yields while console input events are queued.
|
|
922
1258
|
*
|
|
1259
|
+
* Deprecated because it discards queued input events other than window buffer
|
|
1260
|
+
* size changes. Use IO#console_input_events instead to preserve all events.
|
|
1261
|
+
*
|
|
923
1262
|
* This method is Windows only.
|
|
924
1263
|
*
|
|
925
1264
|
* You must require 'io/console' to use this method.
|
|
@@ -930,6 +1269,9 @@ console_check_winsize_changed(VALUE io)
|
|
|
930
1269
|
HANDLE h;
|
|
931
1270
|
DWORD num;
|
|
932
1271
|
|
|
1272
|
+
rb_category_warn(RB_WARN_CATEGORY_DEPRECATED,
|
|
1273
|
+
"IO#check_winsize_changed is deprecated; "
|
|
1274
|
+
"use IO#console_input_events instead");
|
|
933
1275
|
h = (HANDLE)rb_w32_get_osfhandle(GetReadFD(io));
|
|
934
1276
|
while (GetNumberOfConsoleInputEvents(h, &num) && num > 0) {
|
|
935
1277
|
INPUT_RECORD rec;
|
|
@@ -942,6 +1284,7 @@ console_check_winsize_changed(VALUE io)
|
|
|
942
1284
|
return io;
|
|
943
1285
|
}
|
|
944
1286
|
#else
|
|
1287
|
+
#define console_input_events rb_f_notimplement
|
|
945
1288
|
#define console_check_winsize_changed rb_f_notimplement
|
|
946
1289
|
#endif
|
|
947
1290
|
|
|
@@ -1221,7 +1564,7 @@ console_cursor_pos(VALUE io)
|
|
|
1221
1564
|
if (!GetConsoleScreenBufferInfo((HANDLE)rb_w32_get_osfhandle(fd), &ws)) {
|
|
1222
1565
|
rb_syserr_fail(LAST_ERROR, 0);
|
|
1223
1566
|
}
|
|
1224
|
-
return rb_assoc_new(UINT2NUM(ws.dwCursorPosition.Y), UINT2NUM(ws.dwCursorPosition.X));
|
|
1567
|
+
return rb_assoc_new(UINT2NUM(ws.dwCursorPosition.Y - ws.srWindow.Top), UINT2NUM(ws.dwCursorPosition.X));
|
|
1225
1568
|
#else
|
|
1226
1569
|
static const struct query_args query = {"\033[6n", 0};
|
|
1227
1570
|
VALUE resp = console_vt_response(0, 0, io, &query);
|
|
@@ -1242,6 +1585,54 @@ console_cursor_pos(VALUE io)
|
|
|
1242
1585
|
#endif
|
|
1243
1586
|
}
|
|
1244
1587
|
|
|
1588
|
+
static VALUE
|
|
1589
|
+
console_cursor_visibility(VALUE io, int visible)
|
|
1590
|
+
{
|
|
1591
|
+
#ifdef _WIN32
|
|
1592
|
+
HANDLE h = (HANDLE)rb_w32_get_osfhandle(GetWriteFD(io));
|
|
1593
|
+
CONSOLE_CURSOR_INFO info;
|
|
1594
|
+
|
|
1595
|
+
if (!GetConsoleCursorInfo(h, &info)) {
|
|
1596
|
+
rb_syserr_fail(LAST_ERROR, 0);
|
|
1597
|
+
}
|
|
1598
|
+
info.bVisible = visible;
|
|
1599
|
+
if (!SetConsoleCursorInfo(h, &info)) {
|
|
1600
|
+
rb_syserr_fail(LAST_ERROR, 0);
|
|
1601
|
+
}
|
|
1602
|
+
#else
|
|
1603
|
+
rb_io_write(io, rb_str_new_cstr(visible ? CSI "?25h" : CSI "?25l"));
|
|
1604
|
+
#endif
|
|
1605
|
+
return io;
|
|
1606
|
+
}
|
|
1607
|
+
|
|
1608
|
+
/*
|
|
1609
|
+
* call-seq:
|
|
1610
|
+
* io.hide_cursor -> io
|
|
1611
|
+
*
|
|
1612
|
+
* Hides the cursor.
|
|
1613
|
+
*
|
|
1614
|
+
* You must require 'io/console' to use this method.
|
|
1615
|
+
*/
|
|
1616
|
+
static VALUE
|
|
1617
|
+
console_hide_cursor(VALUE io)
|
|
1618
|
+
{
|
|
1619
|
+
return console_cursor_visibility(io, 0);
|
|
1620
|
+
}
|
|
1621
|
+
|
|
1622
|
+
/*
|
|
1623
|
+
* call-seq:
|
|
1624
|
+
* io.show_cursor -> io
|
|
1625
|
+
*
|
|
1626
|
+
* Shows the cursor.
|
|
1627
|
+
*
|
|
1628
|
+
* You must require 'io/console' to use this method.
|
|
1629
|
+
*/
|
|
1630
|
+
static VALUE
|
|
1631
|
+
console_show_cursor(VALUE io)
|
|
1632
|
+
{
|
|
1633
|
+
return console_cursor_visibility(io, 1);
|
|
1634
|
+
}
|
|
1635
|
+
|
|
1245
1636
|
/*
|
|
1246
1637
|
* call-seq:
|
|
1247
1638
|
* io.goto(line, column) -> io
|
|
@@ -1254,11 +1645,17 @@ static VALUE
|
|
|
1254
1645
|
console_goto(VALUE io, VALUE y, VALUE x)
|
|
1255
1646
|
{
|
|
1256
1647
|
#ifdef _WIN32
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
pos
|
|
1260
|
-
|
|
1261
|
-
|
|
1648
|
+
HANDLE h;
|
|
1649
|
+
rb_console_size_t ws;
|
|
1650
|
+
COORD *pos = &ws.dwCursorPosition;
|
|
1651
|
+
|
|
1652
|
+
h = (HANDLE)rb_w32_get_osfhandle(GetWriteFD(io));
|
|
1653
|
+
if (!GetConsoleScreenBufferInfo(h, &ws)) {
|
|
1654
|
+
rb_syserr_fail(LAST_ERROR, 0);
|
|
1655
|
+
}
|
|
1656
|
+
pos->X = NUM2UINT(x);
|
|
1657
|
+
pos->Y = ws.srWindow.Top + NUM2UINT(y);
|
|
1658
|
+
if (!SetConsoleCursorPosition(h, *pos)) {
|
|
1262
1659
|
rb_syserr_fail(LAST_ERROR, 0);
|
|
1263
1660
|
}
|
|
1264
1661
|
#else
|
|
@@ -1651,13 +2048,11 @@ console_dev(int argc, VALUE *argv, VALUE klass)
|
|
|
1651
2048
|
VALUE con = 0;
|
|
1652
2049
|
VALUE sym = 0;
|
|
1653
2050
|
|
|
1654
|
-
rb_check_arity(argc, 0, UNLIMITED_ARGUMENTS);
|
|
1655
|
-
|
|
1656
2051
|
if (argc) {
|
|
1657
2052
|
Check_Type(sym = argv[0], T_SYMBOL);
|
|
1658
2053
|
}
|
|
1659
2054
|
|
|
1660
|
-
|
|
2055
|
+
/* Force the class to be File. */
|
|
1661
2056
|
if (klass == rb_cIO) klass = rb_cFile;
|
|
1662
2057
|
|
|
1663
2058
|
if (console_dev_get(klass, &con)) {
|
|
@@ -1724,7 +2119,7 @@ console_dev(int argc, VALUE *argv, VALUE klass)
|
|
|
1724
2119
|
|
|
1725
2120
|
/*
|
|
1726
2121
|
* call-seq:
|
|
1727
|
-
* io.getch(min: nil, time: nil, intr: nil) -> char
|
|
2122
|
+
* io.getch(min: nil, time: nil, intr: nil) -> char or nil
|
|
1728
2123
|
*
|
|
1729
2124
|
* See IO#getch.
|
|
1730
2125
|
*/
|
|
@@ -1878,6 +2273,103 @@ console_ttyname(VALUE io)
|
|
|
1878
2273
|
# define console_ttyname rb_f_notimplement
|
|
1879
2274
|
#endif
|
|
1880
2275
|
|
|
2276
|
+
typedef enum {
|
|
2277
|
+
platform_default,
|
|
2278
|
+
#if defined _WIN32
|
|
2279
|
+
platform_cygwin,
|
|
2280
|
+
platform_msys,
|
|
2281
|
+
#endif
|
|
2282
|
+
platform_any,
|
|
2283
|
+
|
|
2284
|
+
platform_default_bit = 1U << platform_default,
|
|
2285
|
+
#if defined _WIN32
|
|
2286
|
+
platform_cygwin_bit = 1U << platform_cygwin,
|
|
2287
|
+
platform_msys_bit = 1U << platform_msys,
|
|
2288
|
+
#endif
|
|
2289
|
+
platform_any_bit = (1U << platform_any) - 1 /* all bits */
|
|
2290
|
+
} console_platform_t;
|
|
2291
|
+
|
|
2292
|
+
/*
|
|
2293
|
+
* call-seq:
|
|
2294
|
+
* io.tty?([mode, ...]) -> true or false
|
|
2295
|
+
*
|
|
2296
|
+
* Returns +true+ if the stream is associated with a terminal device (tty),
|
|
2297
|
+
* +false+ otherwise.
|
|
2298
|
+
*
|
|
2299
|
+
* If one or more +type+s are given, returns +true+ if the stream is
|
|
2300
|
+
* associated with any of the specified tty types.
|
|
2301
|
+
*
|
|
2302
|
+
* - +nil+ : Returns the result of the default tty check, as if no type were
|
|
2303
|
+
* given. It can be combined with other types.
|
|
2304
|
+
* - +:any+ : Returns +true+ for any known kind of tty, including the
|
|
2305
|
+
* default tty.
|
|
2306
|
+
* - +:cygwin+ : Returns +true+ for cygwin tty, on Windows.
|
|
2307
|
+
* - +:msys+ : Returns +true+ for msys2 tty, on Windows.
|
|
2308
|
+
*/
|
|
2309
|
+
static VALUE
|
|
2310
|
+
console_platform_tty_p(int argc, VALUE *argv, VALUE io)
|
|
2311
|
+
{
|
|
2312
|
+
VALUE ret = Qfalse;
|
|
2313
|
+
int mode = 0;
|
|
2314
|
+
|
|
2315
|
+
if (argc > 0) {
|
|
2316
|
+
int i;
|
|
2317
|
+
for (i = 0; i < argc; ++i) {
|
|
2318
|
+
VALUE m = argv[i];
|
|
2319
|
+
if (NIL_P(m)) {
|
|
2320
|
+
mode |= platform_default_bit;
|
|
2321
|
+
continue;
|
|
2322
|
+
}
|
|
2323
|
+
Check_Type(m, T_SYMBOL);
|
|
2324
|
+
if (m == ID2SYM(rb_intern("any"))) {
|
|
2325
|
+
mode |= platform_any_bit;
|
|
2326
|
+
}
|
|
2327
|
+
#if defined _WIN32
|
|
2328
|
+
else if (m == ID2SYM(rb_intern("cygwin"))) {
|
|
2329
|
+
mode |= platform_cygwin_bit;
|
|
2330
|
+
}
|
|
2331
|
+
else if (m == ID2SYM(rb_intern("msys"))) {
|
|
2332
|
+
mode |= platform_msys_bit;
|
|
2333
|
+
}
|
|
2334
|
+
#endif
|
|
2335
|
+
else {
|
|
2336
|
+
rb_raise(rb_eArgError, "unknown tty type: %+" PRIsVALUE, m);
|
|
2337
|
+
}
|
|
2338
|
+
}
|
|
2339
|
+
}
|
|
2340
|
+
if ((mode & platform_default_bit) || (mode == 0)) {
|
|
2341
|
+
ret = rb_call_super(0, 0);
|
|
2342
|
+
}
|
|
2343
|
+
if ((mode & ~platform_default_bit) && !RTEST(ret)) {
|
|
2344
|
+
#if defined _WIN32
|
|
2345
|
+
if (mode & (platform_cygwin_bit | platform_msys_bit)) {
|
|
2346
|
+
struct {
|
|
2347
|
+
FILE_NAME_INFO info;
|
|
2348
|
+
WCHAR rest[MAX_PATH];
|
|
2349
|
+
} buffer;
|
|
2350
|
+
|
|
2351
|
+
HANDLE h = (HANDLE)rb_w32_get_osfhandle(GetReadFD(io));
|
|
2352
|
+
if ((GetFileType(h) == FILE_TYPE_PIPE) &&
|
|
2353
|
+
GetFileInformationByHandleEx(h, FileNameInfo, &buffer, sizeof(buffer))) {
|
|
2354
|
+
WCHAR *const name = buffer.info.FileName;
|
|
2355
|
+
DWORD len = buffer.info.FileNameLength / sizeof(WCHAR);
|
|
2356
|
+
name[len] = L'\0';
|
|
2357
|
+
# define tty_pipe_p(type) \
|
|
2358
|
+
(memcmp(name, L"\\" #type "-", sizeof(L"\\" #type)) == 0 && \
|
|
2359
|
+
wcsstr(&name[rb_strlen_lit("\\" #type "-")], L"-pty") != NULL)
|
|
2360
|
+
if (!ret && (mode & platform_cygwin_bit)) {
|
|
2361
|
+
ret = tty_pipe_p(cygwin);
|
|
2362
|
+
}
|
|
2363
|
+
if (!ret && (mode & platform_msys_bit)) {
|
|
2364
|
+
ret = tty_pipe_p(msys);
|
|
2365
|
+
}
|
|
2366
|
+
}
|
|
2367
|
+
}
|
|
2368
|
+
#endif
|
|
2369
|
+
}
|
|
2370
|
+
return ret;
|
|
2371
|
+
}
|
|
2372
|
+
|
|
1881
2373
|
/*
|
|
1882
2374
|
* IO console methods
|
|
1883
2375
|
*/
|
|
@@ -1899,6 +2391,7 @@ Init_console(void)
|
|
|
1899
2391
|
id_flush = rb_intern("flush");
|
|
1900
2392
|
id_chomp_bang = rb_intern("chomp!");
|
|
1901
2393
|
id_close = rb_intern("close");
|
|
2394
|
+
id_timeout = rb_intern("timeout");
|
|
1902
2395
|
#define init_rawmode_opt_id(name) \
|
|
1903
2396
|
rawmode_opt_ids[kwd_##name] = rb_intern(#name)
|
|
1904
2397
|
init_rawmode_opt_id(min);
|
|
@@ -1913,11 +2406,31 @@ Init_console(void)
|
|
|
1913
2406
|
void
|
|
1914
2407
|
InitVM_console(void)
|
|
1915
2408
|
{
|
|
2409
|
+
/* :nodoc: */
|
|
2410
|
+
VALUE mConsole = rb_define_module_under(rb_cIO, "Console");
|
|
2411
|
+
#ifdef _WIN32
|
|
2412
|
+
/* :nodoc: */
|
|
2413
|
+
VALUE mWindows = rb_define_module_under(mConsole, "Windows");
|
|
2414
|
+
#define define_win32_const(name) rb_define_const(mWindows, #name, UINT2NUM(name))
|
|
2415
|
+
EACH_VK(define_win32_const,;);
|
|
2416
|
+
define_win32_const(RIGHT_ALT_PRESSED);
|
|
2417
|
+
define_win32_const(LEFT_ALT_PRESSED);
|
|
2418
|
+
define_win32_const(RIGHT_CTRL_PRESSED);
|
|
2419
|
+
define_win32_const(LEFT_CTRL_PRESSED);
|
|
2420
|
+
define_win32_const(SHIFT_PRESSED);
|
|
2421
|
+
define_win32_const(NUMLOCK_ON);
|
|
2422
|
+
define_win32_const(SCROLLLOCK_ON);
|
|
2423
|
+
define_win32_const(CAPSLOCK_ON);
|
|
2424
|
+
define_win32_const(ENHANCED_KEY);
|
|
2425
|
+
#undef define_win32_const
|
|
2426
|
+
#endif
|
|
2427
|
+
|
|
1916
2428
|
rb_define_method(rb_cIO, "raw", console_raw, -1);
|
|
1917
2429
|
rb_define_method(rb_cIO, "raw!", console_set_raw, -1);
|
|
1918
2430
|
rb_define_method(rb_cIO, "cooked", console_cooked, 0);
|
|
1919
2431
|
rb_define_method(rb_cIO, "cooked!", console_set_cooked, 0);
|
|
1920
2432
|
rb_define_method(rb_cIO, "getch", console_getch, -1);
|
|
2433
|
+
rb_define_method(rb_cIO, "input_pending?", console_input_pending_p, 0);
|
|
1921
2434
|
rb_define_method(rb_cIO, "echo=", console_set_echo, 1);
|
|
1922
2435
|
rb_define_method(rb_cIO, "echo?", console_echo_p, 0);
|
|
1923
2436
|
rb_define_method(rb_cIO, "console_mode", console_conmode_get, 0);
|
|
@@ -1932,6 +2445,8 @@ InitVM_console(void)
|
|
|
1932
2445
|
rb_define_method(rb_cIO, "goto", console_goto, 2);
|
|
1933
2446
|
rb_define_method(rb_cIO, "cursor", console_cursor_pos, 0);
|
|
1934
2447
|
rb_define_method(rb_cIO, "cursor=", console_cursor_set, 1);
|
|
2448
|
+
rb_define_method(rb_cIO, "hide_cursor", console_hide_cursor, 0);
|
|
2449
|
+
rb_define_method(rb_cIO, "show_cursor", console_show_cursor, 0);
|
|
1935
2450
|
rb_define_method(rb_cIO, "cursor_up", console_cursor_up, 1);
|
|
1936
2451
|
rb_define_method(rb_cIO, "cursor_down", console_cursor_down, 1);
|
|
1937
2452
|
rb_define_method(rb_cIO, "cursor_left", console_cursor_left, 1);
|
|
@@ -1943,27 +2458,58 @@ InitVM_console(void)
|
|
|
1943
2458
|
rb_define_method(rb_cIO, "scroll_backward", console_scroll_backward, 1);
|
|
1944
2459
|
rb_define_method(rb_cIO, "clear_screen", console_clear_screen, 0);
|
|
1945
2460
|
rb_define_method(rb_cIO, "pressed?", console_key_pressed_p, 1);
|
|
2461
|
+
rb_define_method(rb_cIO, "console_input_events", console_input_events, -1);
|
|
1946
2462
|
rb_define_method(rb_cIO, "check_winsize_changed", console_check_winsize_changed, 0);
|
|
1947
2463
|
rb_define_method(rb_cIO, "getpass", console_getpass, -1);
|
|
1948
2464
|
rb_define_method(rb_cIO, "ttyname", console_ttyname, 0);
|
|
2465
|
+
{
|
|
2466
|
+
/* :nodoc: */
|
|
2467
|
+
VALUE platform = rb_define_module_under(rb_cIO, "platform_tty");
|
|
2468
|
+
{
|
|
2469
|
+
VALUE rb_cIO = platform;
|
|
2470
|
+
rb_define_method(rb_cIO, "tty?", console_platform_tty_p, -1);
|
|
2471
|
+
rb_define_method(rb_cIO, "isatty", console_platform_tty_p, -1);
|
|
2472
|
+
}
|
|
2473
|
+
#ifdef HAVE_RB_PREPEND_MODULE
|
|
2474
|
+
rb_prepend_module(rb_cIO, platform);
|
|
2475
|
+
#else
|
|
2476
|
+
rb_funcall(rb_cIO, rb_intern_const("prepend"), 1, platform);
|
|
2477
|
+
#endif
|
|
2478
|
+
}
|
|
1949
2479
|
rb_define_singleton_method(rb_cIO, "console", console_dev, -1);
|
|
1950
2480
|
{
|
|
1951
|
-
/* :
|
|
2481
|
+
/* :nodoc: */
|
|
1952
2482
|
VALUE mReadable = rb_define_module_under(rb_cIO, "generic_readable");
|
|
1953
|
-
/* :startdoc: */
|
|
1954
2483
|
rb_define_method(mReadable, "getch", io_getch, -1);
|
|
1955
2484
|
rb_define_method(mReadable, "getpass", io_getpass, -1);
|
|
1956
2485
|
}
|
|
1957
2486
|
{
|
|
1958
|
-
/* :
|
|
1959
|
-
|
|
1960
|
-
|
|
2487
|
+
/* :nodoc: */
|
|
2488
|
+
VALUE version = rb_obj_freeze(rb_str_new_cstr(IO_CONSOLE_VERSION));
|
|
2489
|
+
ID cid, deprecate_constant = rb_intern_const("deprecate_constant");
|
|
2490
|
+
rb_define_const(mConsole, "VERSION", version);
|
|
2491
|
+
/* :nodoc: */
|
|
2492
|
+
cConmode = rb_define_class_under(mConsole, "Mode", rb_cObject);
|
|
2493
|
+
|
|
2494
|
+
/* old internal names; do not use */
|
|
2495
|
+
cid = rb_intern_const("ConsoleMode");
|
|
2496
|
+
rb_const_set(rb_cIO, cid, cConmode);
|
|
2497
|
+
rb_funcall(rb_cIO, deprecate_constant, 1, ID2SYM(cid));
|
|
2498
|
+
cid = rb_intern_const("VERSION");
|
|
2499
|
+
rb_const_set(cConmode, cid, version);
|
|
2500
|
+
rb_funcall(cConmode, deprecate_constant, 1, ID2SYM(cid));
|
|
2501
|
+
|
|
1961
2502
|
rb_define_alloc_func(cConmode, conmode_alloc);
|
|
1962
2503
|
rb_undef_method(cConmode, "initialize");
|
|
1963
2504
|
rb_define_method(cConmode, "initialize_copy", conmode_init_copy, 1);
|
|
1964
2505
|
rb_define_method(cConmode, "echo=", conmode_set_echo, 1);
|
|
1965
2506
|
rb_define_method(cConmode, "raw!", conmode_set_raw, -1);
|
|
1966
2507
|
rb_define_method(cConmode, "raw", conmode_raw_new, -1);
|
|
1967
|
-
|
|
2508
|
+
#ifdef _WIN32
|
|
2509
|
+
rb_define_method(cConmode, "virtual_terminal_processing?", conmode_virtual_terminal_processing_p, 0);
|
|
2510
|
+
rb_define_method(cConmode, "virtual_terminal_processing=", conmode_set_virtual_terminal_processing, 1);
|
|
2511
|
+
rb_define_method(cConmode, "wrap_at_eol_output?", conmode_wrap_at_eol_output_p, 0);
|
|
2512
|
+
rb_define_method(cConmode, "wrap_at_eol_output=", conmode_set_wrap_at_eol_output, 1);
|
|
2513
|
+
#endif
|
|
1968
2514
|
}
|
|
1969
2515
|
}
|