15#ifdef HAVE_SYS_IOCTL_H
19#if defined HAVE_TERMIOS_H
21typedef struct termios conmode;
24setattr(
int fd, conmode *
t)
26 while (tcsetattr(fd, TCSANOW,
t)) {
27 if (errno != EINTR)
return 0;
31# define getattr(fd, t) (tcgetattr(fd, t) == 0)
32#elif defined HAVE_TERMIO_H
34typedef struct termio conmode;
35# define setattr(fd, t) (ioctl(fd, TCSETAF, t) == 0)
36# define getattr(fd, t) (ioctl(fd, TCGETA, t) == 0)
37#elif defined HAVE_SGTTY_H
39typedef struct sgttyb conmode;
41# define setattr(fd, t) (stty(fd, t) == 0)
43# define setattr(fd, t) (ioctl((fd), TIOCSETP, (t)) == 0)
46# define getattr(fd, t) (gtty(fd, t) == 0)
48# define getattr(fd, t) (ioctl((fd), TIOCGETP, (t)) == 0)
55#define LAST_ERROR rb_w32_map_errno(GetLastError())
56#define SET_LAST_ERROR (errno = LAST_ERROR, 0)
59setattr(
int fd, conmode *
t)
62 if (!x) errno = LAST_ERROR;
67getattr(
int fd, conmode *
t)
70 if (!x) errno = LAST_ERROR;
75#define SET_LAST_ERROR (0)
78static ID id_getc, id_console, id_close,
id_min, id_time, id_intr;
80static ID id_gets, id_chomp_bang;
83#ifdef HAVE_RB_SCHEDULER_TIMEOUT
87#define sys_fail_fptr(fptr) rb_sys_fail_str((fptr)->pathv)
120#ifdef RB_SCAN_ARGS_PASS_CALLED_KEYWORDS
123 if (
argc > min_argc) {
129 if (!vopts) vopts =
Qnil;
172set_rawmode(conmode *
t,
void *arg)
176 t->c_lflag &= ~(ECHOE|ECHOK);
177#elif defined HAVE_TERMIOS_H || defined HAVE_TERMIO_H
178 t->c_iflag &= ~(IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK|ISTRIP|INLCR|IGNCR|ICRNL|IXON|IXOFF|IXANY|IMAXBEL);
179 t->c_oflag &= ~OPOST;
180 t->c_lflag &= ~(ECHO|ECHOE|ECHOK|ECHONL|ICANON|ISIG|IEXTEN|XCASE);
181 t->c_cflag &= ~(CSIZE|PARENB);
185#elif defined HAVE_SGTTY_H
186 t->sg_flags &= ~ECHO;
194 if (r->
vmin >= 0)
t->c_cc[VMIN] = r->
vmin;
201 t->c_iflag |= BRKINT;
211set_cookedmode(conmode *
t,
void *arg)
213#if defined HAVE_TERMIOS_H || defined HAVE_TERMIO_H
214 t->c_iflag |= (BRKINT|ISTRIP|ICRNL|IXON);
216 t->c_lflag |= (ECHO|ECHOE|ECHOK|ECHONL|ICANON|ISIG|IEXTEN);
217#elif defined HAVE_SGTTY_H
221 *
t |= ENABLE_ECHO_INPUT|ENABLE_LINE_INPUT|ENABLE_PROCESSED_INPUT;
226set_noecho(conmode *
t,
void *arg)
228#if defined HAVE_TERMIOS_H || defined HAVE_TERMIO_H
229 t->c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL);
230#elif defined HAVE_SGTTY_H
231 t->sg_flags &= ~ECHO;
233 *
t &= ~ENABLE_ECHO_INPUT;
238set_echo(conmode *
t,
void *arg)
240#if defined HAVE_TERMIOS_H || defined HAVE_TERMIO_H
241 t->c_lflag |= (ECHO | ECHOE | ECHOK | ECHONL);
242#elif defined HAVE_SGTTY_H
245 *
t |= ENABLE_ECHO_INPUT;
252#if defined HAVE_TERMIOS_H || defined HAVE_TERMIO_H
253 return (
t->c_lflag & (ECHO | ECHONL)) != 0;
254#elif defined HAVE_SGTTY_H
255 return (
t->sg_flags & ECHO) != 0;
257 return (*
t & ENABLE_ECHO_INPUT) != 0;
262set_ttymode(
int fd, conmode *
t,
void (*setter)(conmode *,
void *),
void *arg)
265 if (!getattr(fd,
t))
return 0;
268 return setattr(fd, &r);
271#define GetReadFD(fptr) ((fptr)->fd)
274get_write_fd(
const rb_io_t *fptr)
278 if (!wio)
return fptr->
fd;
282#define GetWriteFD(fptr) get_write_fd(fptr)
287ttymode(
VALUE io,
VALUE (*func)(
VALUE),
VALUE farg,
void (*setter)(conmode *,
void *),
void *arg)
299 if (set_ttymode(fd[0],
t+0, setter, arg)) {
308 if (fd[1] != -1 && fd[1] != fd[0]) {
309 if (set_ttymode(fd[1],
t+1, setter, arg)) {
321 if (fd[0] != -1 && fd[0] ==
GetReadFD(fptr)) {
322 if (!setattr(fd[0],
t+0)) {
327 if (fd[1] != -1 && fd[1] != fd[0] && fd[1] ==
GetWriteFD(fptr)) {
328 if (!setattr(fd[1],
t+1)) {
350ttymode_callback(
VALUE args)
363 return ttymode(
io, ttymode_callback, (
VALUE)&cargs, setter, arg);
420 set_rawmode(&
t, optp);
463 set_cookedmode(&
t,
NULL);
479 wint_t *
buf = p, c = _getwch();
512 return ttymode(
io, getc_call,
io, set_rawmode, optp);
520# ifndef HAVE_RB_IO_WAIT
529# ifndef HAVE_RB_IO_WAIT
535 tv.tv_usec = (optp->
vtime % 10) * 100000;
536# ifdef HAVE_RB_IO_WAIT
540 switch (optp->
vmin) {
544 if (optp->
vtime)
break;
547 rb_warning(
"min option larger than 1 ignored");
550# ifndef HAVE_RB_IO_WAIT
559 else if (optp->
vtime) {
560 rb_warning(
"Non-zero vtime option ignored if intr flag is unset");
568 buf[0] = (char)wbuf[0];
572 buf[
len++] = (
unsigned char)c;
597console_noecho(
VALUE io)
625 set_noecho(&
t,
NULL);
639console_echo_p(
VALUE io)
657static VALUE cConmode;
660conmode_alloc(
VALUE klass)
666conmode_new(
VALUE klass,
const conmode *
t)
668 VALUE obj = conmode_alloc(klass);
699 set_rawmode(
t, optp);
710 set_rawmode(&
t, optp);
723console_conmode_get(
VALUE io)
733 return conmode_new(cConmode, &
t);
760#if defined TIOCGWINSZ
761typedef struct winsize rb_console_size_t;
762#define getwinsize(fd, buf) (ioctl((fd), TIOCGWINSZ, (buf)) == 0)
763#define setwinsize(fd, buf) (ioctl((fd), TIOCSWINSZ, (buf)) == 0)
764#define winsize_row(buf) (buf)->ws_row
765#define winsize_col(buf) (buf)->ws_col
767typedef CONSOLE_SCREEN_BUFFER_INFO rb_console_size_t;
768#define getwinsize(fd, buf) ( \
769 GetConsoleScreenBufferInfo((HANDLE)rb_w32_get_osfhandle(fd), (buf)) || \
771#define winsize_row(buf) ((buf)->srWindow.Bottom - (buf)->srWindow.Top + 1)
772#define winsize_col(buf) (buf)->dwSize.X
775#if defined TIOCGWINSZ || defined _WIN32
776#define USE_CONSOLE_GETSIZE 1
779#ifdef USE_CONSOLE_GETSIZE
789console_winsize(
VALUE io)
793 rb_console_size_t ws;
814 rb_console_size_t ws;
820 VALUE row, col, xpixel, ypixel;
829 "wrong number of arguments (given %ld, expected 2 or 4)",
833 row = sz[0], col = sz[1], xpixel = ypixel =
Qnil;
834 if (sizelen == 4) xpixel = sz[2], ypixel = sz[3];
836#if defined TIOCSWINSZ
837 ws.ws_row = ws.ws_col = ws.ws_xpixel = ws.ws_ypixel = 0;
838#define SET(m) ws.ws_##m = NIL_P(m) ? 0 : (unsigned short)NUM2UINT(m)
847#define SET(m) new##m = NIL_P(m) ? 0 : (unsigned short)NUM2UINT(m)
853 if (!GetConsoleScreenBufferInfo(wh, &ws)) {
856 ws.dwSize.X = newcol;
857 ret = SetConsoleScreenBufferSize(wh, ws.dwSize);
858 ws.srWindow.Left = 0;
860 ws.srWindow.Right = newcol-1;
861 ws.srWindow.Bottom = newrow-1;
862 if (!SetConsoleWindowInfo(wh,
TRUE, &ws.srWindow)) {
866 if (!ret && !SetConsoleScreenBufferSize(wh, ws.dwSize)) {
870 if (!SetConsoleWindowInfo(wh,
TRUE, &ws.srWindow)) {
888 while (GetNumberOfConsoleInputEvents(h, &
num) &&
num > 0) {
890 if (ReadConsoleInput(h, &rec, 1, &
num)) {
891 if (rec.EventType == WINDOW_BUFFER_SIZE_EVENT) {
899#define console_check_winsize_changed rb_f_notimplement
911console_iflush(
VALUE io)
918#if defined HAVE_TERMIOS_H || defined HAVE_TERMIO_H
934console_oflush(
VALUE io)
941#if defined HAVE_TERMIOS_H || defined HAVE_TERMIO_H
957console_ioflush(
VALUE io)
960#if defined HAVE_TERMIOS_H || defined HAVE_TERMIO_H
965#if defined HAVE_TERMIOS_H || defined HAVE_TERMIO_H
968 if (fd2 != -1 && fd1 != fd2) {
980console_beep(
VALUE io)
991 if (
write(fd,
"\a", 1) < 0)
998mode_in_range(
VALUE val,
int high,
const char *modename)
1001 if (
NIL_P(val))
return 0;
1031console_cursor_pos(
VALUE io)
1035 rb_console_size_t ws;
1046console_move(
VALUE io,
int y,
int x)
1050 rb_console_size_t ws;
1051 COORD *pos = &ws.dwCursorPosition;
1055 if (!GetConsoleScreenBufferInfo(h, &ws)) {
1060 if (!SetConsoleCursorPosition(h, *pos)) {
1071 rb_console_size_t ws;
1072 COORD *pos = &ws.dwCursorPosition;
1076 if (!GetConsoleScreenBufferInfo(h, &ws)) {
1080 if (!SetConsoleCursorPosition(h, *pos)) {
1087constat_clear(HANDLE handle, WORD attr,
DWORD len, COORD pos)
1091 FillConsoleOutputAttribute(handle, attr,
len, pos, &written);
1092 FillConsoleOutputCharacterW(handle,
L' ',
len, pos, &written);
1100 rb_console_size_t ws;
1101 COORD *pos = &ws.dwCursorPosition;
1103 int mode = mode_in_range(val, 2,
"line erase");
1107 if (!GetConsoleScreenBufferInfo(h, &ws)) {
1110 w = winsize_col(&ws);
1123 constat_clear(h, ws.wAttributes, w, *pos);
1132 rb_console_size_t ws;
1133 COORD *pos = &ws.dwCursorPosition;
1135 int mode = mode_in_range(val, 3,
"screen erase");
1139 if (!GetConsoleScreenBufferInfo(h, &ws)) {
1142 w = winsize_col(&ws);
1145 w = (w * (ws.srWindow.Bottom - pos->Y + 1) - pos->X);
1148 w = (w * (pos->Y - ws.srWindow.Top) + pos->X + 1);
1150 pos->Y = ws.srWindow.Top;
1153 w = (w * winsize_row(&ws));
1155 pos->Y = ws.srWindow.Top;
1158 w = (w * ws.dwSize.Y);
1163 constat_clear(h, ws.wAttributes, w, *pos);
1168console_scroll(
VALUE io,
int line)
1172 rb_console_size_t ws;
1176 if (!GetConsoleScreenBufferInfo(h, &ws)) {
1184 scroll.Top = line > 0 ? line : 0;
1185 scroll.Right = winsize_col(&ws) - 1;
1186 scroll.Bottom = winsize_row(&ws) - 1 + (line < 0 ? line : 0);
1188 destination.Y = line < 0 ? -line : 0;
1189 fill.Char.UnicodeChar =
L' ';
1190 fill.Attributes = ws.wAttributes;
1192 ScrollConsoleScreenBuffer(h, &scroll,
NULL, destination, &fill);
1197#include "win32_vk.inc"
1208 const struct vktable *
t;
1218 if (!
t || (vk = (
short)
t->vk) == -1) {
1233 if (RB_TYPE_P(io,
T_FILE)) {
1247 if (fptr->
fd == 0 &&
1264 if (!direct_query(io, qargs))
return Qnil;
1276 num =
num * 10 + c -
'0';
1278 else if (
opt && c ==
opt) {
1282 char last = (char)c;
1296 VALUE ret = ttymode_with_io(io, read_vt_response, query, set_rawmode, optp);
1301console_cursor_pos(
VALUE io)
1303 static const struct query_args query = {
"\033[6n", 0};
1304 VALUE resp = console_vt_response(0, 0, io, &query);
1316 RARRAY_ASET(resp, 0,
INT2NUM(r));
1317 RARRAY_ASET(resp, 1,
INT2NUM(c));
1329console_move(
VALUE io,
int y,
int x)
1333 if (y)
rb_str_catf(s,
"\x1b[%d%c", y < 0 ? -y : y, y < 0 ?
'A' :
'B');
1334 if (x)
rb_str_catf(s,
"\x1b[%d%c", x < 0 ? -x : x, x < 0 ?
'D' :
'C');
1351 int mode = mode_in_range(val, 2,
"line erase");
1359 int mode = mode_in_range(val, 3,
"screen erase");
1365console_scroll(
VALUE io,
int line)
1369 line < 0 ?
'T' :
'S');
1374# define console_key_pressed_p rb_f_notimplement
1388 return console_move(io, -
NUM2INT(val), 0);
1394 return console_move(io, +
NUM2INT(val), 0);
1400 return console_move(io, 0, -
NUM2INT(val));
1406 return console_move(io, 0, +
NUM2INT(val));
1412 return console_scroll(io, +
NUM2INT(val));
1418 return console_scroll(io, -
NUM2INT(val));
1422console_clear_screen(
VALUE io)
1424 console_erase_screen(io,
INT2FIX(2));
1456 if (!RB_TYPE_P(con,
T_FILE) ||
1474#if defined HAVE_TERMIOS_H || defined HAVE_TERMIO_H || defined HAVE_SGTTY_H
1475# define CONSOLE_DEVICE "/dev/tty"
1477# define CONSOLE_DEVICE "con$"
1478# define CONSOLE_DEVICE_FOR_READING "conin$"
1479# define CONSOLE_DEVICE_FOR_WRITING "conout$"
1481#ifndef CONSOLE_DEVICE_FOR_READING
1482# define CONSOLE_DEVICE_FOR_READING CONSOLE_DEVICE
1484#ifdef CONSOLE_DEVICE_FOR_WRITING
1490#ifdef CONSOLE_DEVICE_FOR_WRITING
1492 if (fd < 0)
return Qnil;
1500#ifdef CONSOLE_DEVICE_FOR_WRITING
1511#ifdef CONSOLE_DEVICE_FOR_WRITING
1538#if ENABLE_IO_GETPASS
1546getpass_call(
VALUE io)
1593 return str_chomp(
str);
1623#if ENABLE_IO_GETPASS
1632#ifndef HAVE_RB_F_SEND
1672#if ENABLE_IO_GETPASS
1679#if ENABLE_IO_GETPASS
VALUE rb_ary_push(VALUE ary, VALUE item)
VALUE rb_ary_resize(VALUE ary, long len)
expands or shrinks ary to len elements.
VALUE rb_assoc_new(VALUE car, VALUE cdr)
#define console_key_pressed_p
#define sys_fail_fptr(fptr)
#define CONSOLE_DEVICE_FOR_READING
#define console_check_winsize_changed
void InitVM_console(void)
#define rb_define_method(klass, mid, func, arity)
Defines klass#mid.
#define rb_define_singleton_method(klass, mid, func, arity)
Defines klass.mid.
rb_encoding * rb_default_external_encoding(void)
char str[HTML_ESCAPE_MAX_LEN+1]
#define RSTRING_LEN(string)
#define RSTRING_PTR(string)
VALUE rb_data_typed_object_zalloc(VALUE klass, size_t size, const rb_data_type_t *type)
VALUE rb_define_class_under(VALUE outer, const char *name, VALUE super)
Defines a class under the namespace of outer.
VALUE rb_define_module_under(VALUE outer, const char *name)
VALUE rb_extract_keywords(VALUE *orighash)
void rb_undef_method(VALUE klass, const char *name)
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
void rb_syserr_fail(int e, const char *mesg)
void rb_raise(VALUE exc, const char *fmt,...)
VALUE rb_protect(VALUE(*proc)(VALUE), VALUE data, int *pstate)
Protects a function call from potential global escapes from the function.
void * rb_check_typeddata(VALUE obj, const rb_data_type_t *data_type)
VALUE rb_ensure(VALUE(*b_proc)(VALUE), VALUE data1, VALUE(*e_proc)(VALUE), VALUE data2)
An equivalent to ensure clause.
void rb_jump_tag(int tag)
Continues the exception caught by rb_protect() and rb_eval_string_protect().
void rb_warning(const char *fmt,...)
VALUE rb_convert_type(VALUE, int, const char *, const char *)
Converts an object into another type.
VALUE rb_cObject
Object class.
VALUE rb_class_new_instance(int, const VALUE *, VALUE)
Allocates and initializes an instance of klass.
VALUE rb_Array(VALUE)
Equivalent to Kernel#Array in Ruby.
VALUE rb_obj_class(VALUE)
VALUE rb_obj_freeze(VALUE)
Make the object unmodifiable.
VALUE rb_check_hash_type(VALUE hash)
VALUE rb_hash_aref(VALUE hash, VALUE key)
VALUE rb_str_conv_enc(VALUE str, rb_encoding *from, rb_encoding *to)
int rb_uv_to_utf8(char[6], unsigned long)
#define UNLIMITED_ARGUMENTS
VALUE rb_io_getbyte(VALUE)
VALUE rb_io_write(VALUE, VALUE)
void rb_update_max_fd(int fd)
int rb_cloexec_open(const char *pathname, int flags, mode_t mode)
#define rb_str_new(str, len)
#define rb_utf8_str_new(str, len)
#define rb_str_new_cstr(str)
VALUE rb_const_get(VALUE, ID)
void rb_const_set(VALUE, ID, VALUE)
VALUE rb_const_remove(VALUE, ID)
int rb_const_defined(VALUE, ID)
void rb_define_alloc_func(VALUE, rb_alloc_func_t)
ID rb_intern(const char *)
ID rb_check_id(volatile VALUE *)
Returns ID for the given name if it is interned already, or 0.
int rb_wait_for_single_fd(int fd, int events, struct timeval *tv)
VALUE rb_io_get_write_io(VALUE io)
VALUE rb_io_wait(VALUE io, VALUE events, VALUE timeout)
void * rb_thread_call_without_gvl(void *(*func)(void *), void *data1, rb_unblock_function_t *ubf, void *data2)
typedef int(ZCALLBACK *close_file_func) OF((voidpf opaque
#define SET(a, b, c, d, k, s, Ti)
#define RARRAY_CONST_PTR(s)
#define RARRAY_AREF(a, i)
#define StringValuePtr(v)
#define StringValueCStr(v)
#define RUBY_TYPED_DEFAULT_FREE
#define TypedData_Get_Struct(obj, type, data_type, sval)
@ RUBY_TYPED_FREE_IMMEDIATELY
@ RUBY_TYPED_WB_PROTECTED
#define RB_INTEGER_TYPE_P(obj)
VALUE rb_scheduler_timeout(struct timeval *timeout)
VALUE rb_str_catf(VALUE, const char *,...)
VALUE rb_sprintf(const char *,...)
size_t strlen(const char *)
VALUE tied_io_for_writing
VALUE(* func)(VALUE, VALUE)
void error(const char *msg)
SOCKET rb_w32_get_osfhandle(int)
int write(ozstream &zs, const T *x, Items items)