static VALUE ttymode(VALUE io, VALUE (*func)(VALUE), void (*setter)(conmode *, void *), void *arg) { rb_io_t *fptr; int status = -1; int error = 0; int fd[FD_PER_IO]; conmode t[FD_PER_IO]; VALUE result = Qnil; GetOpenFile(io, fptr); fd[0] = GetReadFD(fptr); if (fd[0] != -1) { if (set_ttymode(fd[0], t+0, setter, arg)) { status = 0; } else { error = errno; fd[0] = -1; } } fd[1] = GetWriteFD(fptr); if (fd[1] != -1 && fd[1] != fd[0]) { if (set_ttymode(fd[1], t+1, setter, arg)) { status = 0; } else { error = errno; fd[1] = -1; } } if (status == 0) { result = rb_protect(func, io, &status); } GetOpenFile(io, fptr); if (fd[0] != -1 && fd[0] == GetReadFD(fptr)) { if (!setattr(fd[0], t+0)) { error = errno; status = -1; } } if (fd[1] != -1 && fd[1] != fd[0] && fd[1] == GetWriteFD(fptr)) { if (!setattr(fd[1], t+1)) { error = errno; status = -1; } } if (status) { if (status == -1) { errno = error; rb_sys_fail(0); } rb_jump_tag(status); } return result; }
/* * call-seq: * io.winsize = [rows, columns] * * Tries to set console size. The effect depends on the platform and * the running environment. * * You must require 'io/console' to use this method. */ static VALUE console_set_winsize(VALUE io, VALUE size) { rb_io_t *fptr; rb_console_size_t ws; #if defined _WIN32 HANDLE wh; int newrow, newcol; #endif VALUE row, col, xpixel, ypixel; const VALUE *sz; int fd; GetOpenFile(io, fptr); size = rb_Array(size); rb_check_arity(RARRAY_LENINT(size), 2, 4); sz = RARRAY_CONST_PTR(size); row = sz[0], col = sz[1], xpixel = sz[2], ypixel = sz[3]; fd = GetWriteFD(fptr); #if defined TIOCSWINSZ ws.ws_row = ws.ws_col = ws.ws_xpixel = ws.ws_ypixel = 0; #define SET(m) ws.ws_##m = NIL_P(m) ? 0 : (unsigned short)NUM2UINT(m) SET(row); SET(col); SET(xpixel); SET(ypixel); #undef SET if (!setwinsize(fd, &ws)) rb_sys_fail(0); #elif defined _WIN32 wh = (HANDLE)rb_w32_get_osfhandle(fd); #define SET(m) new##m = NIL_P(m) ? 0 : (unsigned short)NUM2UINT(m) SET(row); SET(col); #undef SET if (!NIL_P(xpixel)) (void)NUM2UINT(xpixel); if (!NIL_P(ypixel)) (void)NUM2UINT(ypixel); if (!GetConsoleScreenBufferInfo(wh, &ws)) { rb_syserr_fail(LAST_ERROR, "GetConsoleScreenBufferInfo"); } if ((ws.dwSize.X < newcol && (ws.dwSize.X = newcol, 1)) || (ws.dwSize.Y < newrow && (ws.dwSize.Y = newrow, 1))) { if (!SetConsoleScreenBufferSize(wh, ws.dwSize)) { rb_syserr_fail(LAST_ERROR, "SetConsoleScreenBufferInfo"); } } ws.srWindow.Left = 0; ws.srWindow.Top = 0; ws.srWindow.Right = newcol; ws.srWindow.Bottom = newrow; if (!SetConsoleWindowInfo(wh, FALSE, &ws.srWindow)) { rb_syserr_fail(LAST_ERROR, "SetConsoleWindowInfo"); } #endif return io; }
/* * call-seq: * io.winsize -> [rows, columns] * * Returns console size. * * You must require 'io/console' to use this method. */ static VALUE console_winsize(VALUE io) { rb_io_t *fptr; int fd; rb_console_size_t ws; GetOpenFile(io, fptr); fd = GetWriteFD(fptr); if (!getwinsize(fd, &ws)) rb_sys_fail(0); return rb_assoc_new(INT2NUM(winsize_row(&ws)), INT2NUM(winsize_col(&ws))); }
/* * call-seq: * io.oflush * * Flushes output buffer in kernel. */ static VALUE console_oflush(VALUE io) { rb_io_t *fptr; int fd; GetOpenFile(io, fptr); fd = GetWriteFD(fptr); #if defined HAVE_TERMIOS_H || defined HAVE_TERMIO_H if (tcflush(fd, TCOFLUSH)) rb_sys_fail(0); #endif return io; }
/* * call-seq: * io.winsize = [rows, columns] * * Tries to set console size. The effect depends on the platform and * the running environment. * * You must require 'io/console' to use this method. */ static VALUE console_set_winsize(VALUE io, VALUE size) { rb_io_t *fptr; rb_console_size_t ws; #if defined _WIN32 HANDLE wh; int newrow, newcol; #endif VALUE row, col, xpixel, ypixel; #if defined TIOCSWINSZ int fd; #endif GetOpenFile(io, fptr); size = rb_Array(size); rb_scan_args((int)RARRAY_LEN(size), RARRAY_PTR(size), "22", &row, &col, &xpixel, &ypixel); #if defined TIOCSWINSZ fd = GetWriteFD(fptr); ws.ws_row = ws.ws_col = ws.ws_xpixel = ws.ws_ypixel = 0; #define SET(m) ws.ws_##m = NIL_P(m) ? 0 : (unsigned short)NUM2UINT(m) SET(row); SET(col); SET(xpixel); SET(ypixel); #undef SET if (!setwinsize(fd, &ws)) rb_sys_fail(0); #elif defined _WIN32 wh = (HANDLE)rb_w32_get_osfhandle(GetReadFD(fptr)); newrow = (SHORT)NUM2UINT(row); newcol = (SHORT)NUM2UINT(col); if (!getwinsize(GetReadFD(fptr), &ws)) { rb_sys_fail("GetConsoleScreenBufferInfo"); } if ((ws.dwSize.X < newcol && (ws.dwSize.X = newcol, 1)) || (ws.dwSize.Y < newrow && (ws.dwSize.Y = newrow, 1))) { if (!(SetConsoleScreenBufferSize(wh, ws.dwSize) || SET_LAST_ERROR)) { rb_sys_fail("SetConsoleScreenBufferInfo"); } } ws.srWindow.Left = 0; ws.srWindow.Top = 0; ws.srWindow.Right = newcol; ws.srWindow.Bottom = newrow; if (!(SetConsoleWindowInfo(wh, FALSE, &ws.srWindow) || SET_LAST_ERROR)) { rb_sys_fail("SetConsoleWindowInfo"); } #endif return io; }
static VALUE console_cursor_pos(VALUE io) { rb_io_t *fptr; int fd; rb_console_size_t ws; GetOpenFile(io, fptr); fd = GetWriteFD(fptr); if (!GetConsoleScreenBufferInfo((HANDLE)rb_w32_get_osfhandle(fd), &ws)) { rb_syserr_fail(LAST_ERROR, 0); } return rb_assoc_new(UINT2NUM(ws.dwCursorPosition.X), UINT2NUM(ws.dwCursorPosition.Y)); }
static VALUE console_goto(VALUE io, VALUE x, VALUE y) { rb_io_t *fptr; int fd; COORD pos; GetOpenFile(io, fptr); fd = GetWriteFD(fptr); pos.X = NUM2UINT(x); pos.Y = NUM2UINT(y); if (!SetConsoleCursorPosition((HANDLE)rb_w32_get_osfhandle(fd), pos)) { rb_syserr_fail(LAST_ERROR, 0); } return io; }
static VALUE console_beep(VALUE io) { rb_io_t *fptr; int fd; GetOpenFile(io, fptr); fd = GetWriteFD(fptr); #ifdef _WIN32 (void)fd; MessageBeep(0); #else if (write(fd, "\a", 1) < 0) rb_sys_fail(0); #endif return io; }
/* * call-seq: * io.ioflush * * Flushes input and output buffers in kernel. * * You must require 'io/console' to use this method. */ static VALUE console_ioflush(VALUE io) { rb_io_t *fptr; #if defined HAVE_TERMIOS_H || defined HAVE_TERMIO_H int fd1, fd2; #endif GetOpenFile(io, fptr); #if defined HAVE_TERMIOS_H || defined HAVE_TERMIO_H fd1 = GetReadFD(fptr); fd2 = GetWriteFD(fptr); if (fd2 != -1 && fd1 != fd2) { if (tcflush(fd1, TCIFLUSH)) rb_sys_fail(0); if (tcflush(fd2, TCOFLUSH)) rb_sys_fail(0); } else { if (tcflush(fd1, TCIOFLUSH)) rb_sys_fail(0); } #endif return io; }
inline bool IsWriteReady() { return GetWriteFD() > 0; }