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)) {
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;
114#ifdef RB_SCAN_ARGS_PASS_CALLED_KEYWORDS
123 if (!vopts) vopts =
Qnil;
166set_rawmode(conmode *t,
void *
arg)
170 t->c_lflag &= ~(ECHOE|ECHOK);
171#elif defined HAVE_TERMIOS_H || defined HAVE_TERMIO_H
172 t->c_iflag &= ~(IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK|ISTRIP|INLCR|IGNCR|ICRNL|IXON|IXOFF|IXANY|IMAXBEL);
173 t->c_oflag &= ~OPOST;
174 t->c_lflag &= ~(ECHO|ECHOE|ECHOK|ECHONL|ICANON|ISIG|IEXTEN|XCASE);
175 t->c_cflag &= ~(CSIZE|PARENB);
179#elif defined HAVE_SGTTY_H
180 t->sg_flags &= ~ECHO;
188 if (r->
vmin >= 0) t->c_cc[VMIN] = r->
vmin;
195 t->c_iflag |= BRKINT;
205set_cookedmode(conmode *t,
void *
arg)
207#if defined HAVE_TERMIOS_H || defined HAVE_TERMIO_H
208 t->c_iflag |= (BRKINT|ISTRIP|ICRNL|IXON);
210 t->c_lflag |= (ECHO|ECHOE|ECHOK|ECHONL|ICANON|ISIG|IEXTEN);
211#elif defined HAVE_SGTTY_H
215 *t |= ENABLE_ECHO_INPUT|ENABLE_LINE_INPUT|ENABLE_PROCESSED_INPUT;
220set_noecho(conmode *t,
void *
arg)
222#if defined HAVE_TERMIOS_H || defined HAVE_TERMIO_H
223 t->c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL);
224#elif defined HAVE_SGTTY_H
225 t->sg_flags &= ~ECHO;
227 *t &= ~ENABLE_ECHO_INPUT;
232set_echo(conmode *t,
void *
arg)
234#if defined HAVE_TERMIOS_H || defined HAVE_TERMIO_H
235 t->c_lflag |= (ECHO | ECHOE | ECHOK | ECHONL);
236#elif defined HAVE_SGTTY_H
239 *t |= ENABLE_ECHO_INPUT;
246#if defined HAVE_TERMIOS_H || defined HAVE_TERMIO_H
247 return (t->c_lflag & (ECHO | ECHONL)) != 0;
248#elif defined HAVE_SGTTY_H
249 return (t->sg_flags & ECHO) != 0;
251 return (*t & ENABLE_ECHO_INPUT) != 0;
256set_ttymode(
int fd, conmode *t,
void (*setter)(conmode *,
void *),
void *
arg)
259 if (!getattr(fd, t))
return 0;
262 return setattr(fd, &r);
265#define GetReadFD(fptr) ((fptr)->fd)
268get_write_fd(
const rb_io_t *fptr)
272 if (!wio)
return fptr->
fd;
276#define GetWriteFD(fptr) get_write_fd(fptr)
293 if (set_ttymode(fd[0], t+0, setter,
arg)) {
302 if (fd[1] != -1 && fd[1] != fd[0]) {
303 if (set_ttymode(fd[1], t+1, setter,
arg)) {
315 if (fd[0] != -1 && fd[0] ==
GetReadFD(fptr)) {
316 if (!setattr(fd[0], t+0)) {
321 if (fd[1] != -1 && fd[1] != fd[0] && fd[1] ==
GetWriteFD(fptr)) {
322 if (!setattr(fd[1], t+1)) {
344ttymode_callback(
VALUE args)
357 return ttymode(
io, ttymode_callback, (
VALUE)&cargs, setter,
arg);
414 set_rawmode(&t, optp);
457 set_cookedmode(&t,
NULL);
506 return ttymode(
io, getc_call,
io, set_rawmode, optp);
521 tv.tv_usec = (optp->
vtime % 10) * 100000;
523 if (optp->
vmin != 1) {
532 rb_warning(
"vtime option ignored if intr flag is unset");
569console_noecho(
VALUE io)
597 set_noecho(&t,
NULL);
611console_echo_p(
VALUE io)
629static VALUE cConmode;
671 set_rawmode(t, optp);
682 set_rawmode(&t, optp);
695console_conmode_get(
VALUE io)
705 return conmode_new(cConmode, &t);
732#if defined TIOCGWINSZ
733typedef struct winsize rb_console_size_t;
734#define getwinsize(fd, buf) (ioctl((fd), TIOCGWINSZ, (buf)) == 0)
735#define setwinsize(fd, buf) (ioctl((fd), TIOCSWINSZ, (buf)) == 0)
736#define winsize_row(buf) (buf)->ws_row
737#define winsize_col(buf) (buf)->ws_col
739typedef CONSOLE_SCREEN_BUFFER_INFO rb_console_size_t;
740#define getwinsize(fd, buf) ( \
741 GetConsoleScreenBufferInfo((HANDLE)rb_w32_get_osfhandle(fd), (buf)) || \
743#define winsize_row(buf) ((buf)->srWindow.Bottom - (buf)->srWindow.Top + 1)
744#define winsize_col(buf) (buf)->dwSize.X
747#if defined TIOCGWINSZ || defined _WIN32
748#define USE_CONSOLE_GETSIZE 1
751#ifdef USE_CONSOLE_GETSIZE
761console_winsize(
VALUE io)
765 rb_console_size_t ws;
786 rb_console_size_t ws;
792 VALUE row, col, xpixel, ypixel;
801 "wrong number of arguments (given %ld, expected 2 or 4)",
805 row = sz[0], col = sz[1], xpixel = ypixel =
Qnil;
806 if (sizelen == 4) xpixel = sz[2], ypixel = sz[3];
808#if defined TIOCSWINSZ
809 ws.ws_row = ws.ws_col = ws.ws_xpixel = ws.ws_ypixel = 0;
810#define SET(m) ws.ws_##m = NIL_P(m) ? 0 : (unsigned short)NUM2UINT(m)
819#define SET(m) new##m = NIL_P(m) ? 0 : (unsigned short)NUM2UINT(m)
825 if (!GetConsoleScreenBufferInfo(wh, &ws)) {
828 ws.dwSize.X = newcol;
829 ret = SetConsoleScreenBufferSize(wh, ws.dwSize);
830 ws.srWindow.Left = 0;
832 ws.srWindow.Right = newcol-1;
833 ws.srWindow.Bottom = newrow-1;
834 if (!SetConsoleWindowInfo(wh,
TRUE, &ws.srWindow)) {
838 if (!ret && !SetConsoleScreenBufferSize(wh, ws.dwSize)) {
842 if (!SetConsoleWindowInfo(wh,
TRUE, &ws.srWindow)) {
860 while (GetNumberOfConsoleInputEvents(
h, &num) && num > 0) {
862 if (ReadConsoleInput(
h, &rec, 1, &num)) {
863 if (rec.EventType == WINDOW_BUFFER_SIZE_EVENT) {
871#define console_check_winsize_changed rb_f_notimplement
883console_iflush(
VALUE io)
890#if defined HAVE_TERMIOS_H || defined HAVE_TERMIO_H
906console_oflush(
VALUE io)
913#if defined HAVE_TERMIOS_H || defined HAVE_TERMIO_H
929console_ioflush(
VALUE io)
932#if defined HAVE_TERMIOS_H || defined HAVE_TERMIO_H
937#if defined HAVE_TERMIOS_H || defined HAVE_TERMIO_H
940 if (fd2 != -1 && fd1 != fd2) {
952console_beep(
VALUE io)
963 if (
write(fd,
"\a", 1) < 0)
970mode_in_range(
VALUE val,
int high,
const char *modename)
973 if (
NIL_P(val))
return 0;
978 if ((mode =
NUM2INT(val)) < 0 || mode > high) {
1003console_cursor_pos(
VALUE io)
1007 rb_console_size_t ws;
1018console_move(
VALUE io,
int y,
int x)
1022 rb_console_size_t ws;
1023 COORD *pos = &ws.dwCursorPosition;
1027 if (!GetConsoleScreenBufferInfo(
h, &ws)) {
1032 if (!SetConsoleCursorPosition(
h, *pos)) {
1043 rb_console_size_t ws;
1044 COORD *pos = &ws.dwCursorPosition;
1048 if (!GetConsoleScreenBufferInfo(
h, &ws)) {
1052 if (!SetConsoleCursorPosition(
h, *pos)) {
1059constat_clear(HANDLE handle, WORD attr,
DWORD len, COORD pos)
1063 FillConsoleOutputAttribute(handle, attr,
len, pos, &written);
1064 FillConsoleOutputCharacterW(handle,
L' ',
len, pos, &written);
1072 rb_console_size_t ws;
1073 COORD *pos = &ws.dwCursorPosition;
1075 int mode = mode_in_range(val, 2,
"line erase");
1079 if (!GetConsoleScreenBufferInfo(
h, &ws)) {
1082 w = winsize_col(&ws);
1095 constat_clear(
h, ws.wAttributes, w, *pos);
1104 rb_console_size_t ws;
1105 COORD *pos = &ws.dwCursorPosition;
1107 int mode = mode_in_range(val, 3,
"screen erase");
1111 if (!GetConsoleScreenBufferInfo(
h, &ws)) {
1114 w = winsize_col(&ws);
1117 w = (w * (ws.srWindow.Bottom - pos->Y + 1) - pos->X);
1120 w = (w * (pos->Y - ws.srWindow.Top) + pos->X + 1);
1122 pos->Y = ws.srWindow.Top;
1125 w = (w * winsize_row(&ws));
1127 pos->Y = ws.srWindow.Top;
1130 w = (w * ws.dwSize.Y);
1135 constat_clear(
h, ws.wAttributes, w, *pos);
1140console_scroll(
VALUE io,
int line)
1144 rb_console_size_t ws;
1148 if (!GetConsoleScreenBufferInfo(
h, &ws)) {
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);
1160 destination.Y = line < 0 ? -line : 0;
1161 fill.Char.UnicodeChar =
L' ';
1162 fill.Attributes = ws.wAttributes;
1164 ScrollConsoleScreenBuffer(
h, &scroll,
NULL, destination, &fill);
1169#include "win32_vk.inc"
1180 const struct vktable *t;
1190 if (!t || (vk = (
short)t->vk) == -1) {
1219 if (fptr->
fd == 0 &&
1236 if (!direct_query(io, qargs))
return Qnil;
1248 num = num * 10 + c -
'0';
1250 else if (
opt && c ==
opt) {
1268 VALUE ret = ttymode_with_io(io, read_vt_response, query, set_rawmode, optp);
1273console_cursor_pos(
VALUE io)
1275 static const struct query_args query = {
"\033[6n", 0};
1276 VALUE resp = console_vt_response(0, 0, io, &query);
1301console_move(
VALUE io,
int y,
int x)
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');
1323 int mode = mode_in_range(val, 2,
"line erase");
1331 int mode = mode_in_range(val, 3,
"screen erase");
1337console_scroll(
VALUE io,
int line)
1341 line < 0 ?
'T' :
'S');
1346# define console_key_pressed_p rb_f_notimplement
1360 return console_move(io, -
NUM2INT(val), 0);
1366 return console_move(io, +
NUM2INT(val), 0);
1372 return console_move(io, 0, -
NUM2INT(val));
1378 return console_move(io, 0, +
NUM2INT(val));
1384 return console_scroll(io, +
NUM2INT(val));
1390 return console_scroll(io, -
NUM2INT(val));
1394console_clear_screen(
VALUE io)
1396 console_erase_screen(io,
INT2FIX(2));
1446#if defined HAVE_TERMIOS_H || defined HAVE_TERMIO_H || defined HAVE_SGTTY_H
1447# define CONSOLE_DEVICE "/dev/tty"
1449# define CONSOLE_DEVICE "con$"
1450# define CONSOLE_DEVICE_FOR_READING "conin$"
1451# define CONSOLE_DEVICE_FOR_WRITING "conout$"
1453#ifndef CONSOLE_DEVICE_FOR_READING
1454# define CONSOLE_DEVICE_FOR_READING CONSOLE_DEVICE
1456#ifdef CONSOLE_DEVICE_FOR_WRITING
1462#ifdef CONSOLE_DEVICE_FOR_WRITING
1464 if (fd < 0)
return Qnil;
1472#ifdef CONSOLE_DEVICE_FOR_WRITING
1483#ifdef CONSOLE_DEVICE_FOR_WRITING
1510#if ENABLE_IO_GETPASS
1518getpass_call(
VALUE io)
1561 return str_chomp(
str);
1591#if ENABLE_IO_GETPASS
1599#ifndef HAVE_RB_F_SEND
1639#if ENABLE_IO_GETPASS
1646#if ENABLE_IO_GETPASS
#define console_key_pressed_p
#define CONSOLE_DEVICE_FOR_READING
#define console_check_winsize_changed
void InitVM_console(void)
rb_encoding * rb_default_external_encoding(void)
VALUE rb_str_conv_enc(VALUE str, rb_encoding *from, rb_encoding *to)
char str[HTML_ESCAPE_MAX_LEN+1]
VALUE rb_define_class_under(VALUE, const char *, VALUE)
Defines a class under the namespace of outer.
VALUE rb_define_module_under(VALUE, const char *)
VALUE rb_extract_keywords(VALUE *orighash)
void rb_undef_method(VALUE, const char *)
VALUE rb_cObject
Object class.
void rb_syserr_fail(int e, const char *mesg)
void rb_raise(VALUE exc, const char *fmt,...)
VALUE rb_protect(VALUE(*)(VALUE), VALUE, int *)
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(*)(VALUE), VALUE, VALUE(*)(VALUE), VALUE)
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_sys_fail(const char *mesg)
VALUE rb_convert_type(VALUE, int, const char *, const char *)
Converts an object into another type.
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)
Equivalent to Object#class in Ruby.
VALUE rb_obj_freeze(VALUE)
Make the object unmodifiable.
int rb_wait_for_single_fd(int fd, int events, struct timeval *tv)
#define GetOpenFile(obj, fp)
VALUE rb_io_get_write_io(VALUE io)
#define SET(a, b, c, d, k, s, Ti)
unsigned char buf[MIME_BUF_SIZE]
VALUE rb_data_typed_object_zalloc(VALUE klass, size_t size, const rb_data_type_t *type)
VALUE tied_io_for_writing
VALUE(* func)(VALUE, VALUE)
void * rb_thread_call_without_gvl(void *(*func)(void *), void *data1, rb_unblock_function_t *ubf, void *data2)
SOCKET rb_w32_get_osfhandle(int)