Preview Ruby 4.1 is a preview. It can change before the final release. Switch to Ruby 4.0 →
instance method
IO#winsize=
([ ::Integer, ::Integer ]) -> [ ::Integer, ::Integer ]
([ ::Integer, ::Integer, ::Integer, ::Integer ]) -> [ ::Integer, ::Integer, ::Integer, ::Integer ]
io.winsize = [rows, columns]
ext/io/console/console.c
View on GitHub ↗
static VALUE
console_set_winsize(VALUE io, VALUE size)
{
rb_console_size_t ws;
#if defined _WIN32
HANDLE wh;
int newrow, newcol;
COORD oldsize;
SMALL_RECT oldwindow;
#endif
VALUE row, col, xpixel, ypixel;
const VALUE *sz;
rb_len_t sizelen;
int fd;
size = rb_Array(size);
if ((sizelen = RARRAY_LEN(size)) != 2 && sizelen != 4) {
rb_raise(rb_eArgError, "wrong number of arguments (given %"PRIdLEN", expected 2 or 4)", sizelen);
}
sz = RARRAY_CONST_PTR(size);
row = sz[0], col = sz[1], xpixel = ypixel = Qnil;
if (sizelen == 4) xpixel = sz[2], ypixel = sz[3];
fd = GetWriteFD(io);
#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)) sys_fail(io);
#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");
}
oldsize = ws.dwSize;
oldwindow = ws.srWindow;
if (ws.srWindow.Right + 1 < newcol) {
ws.dwSize.X = newcol;
}
if (ws.dwSize.Y < newrow) {
ws.dwSize.Y = newrow;
}
/* expand screen buffer first if needed */
if (!SetConsoleScreenBufferSize(wh, ws.dwSize)) {
rb_syserr_fail(LAST_ERROR, "SetConsoleScreenBufferInfo");
}
/* refresh ws for new dwMaximumWindowSize */
if (!GetConsoleScreenBufferInfo(wh, &ws)) {
rb_syserr_fail(LAST_ERROR, "GetConsoleScreenBufferInfo");
}
/* check new size before modifying buffer content */
if (newrow <= 0 || newcol <= 0 ||
newrow > ws.dwMaximumWindowSize.Y ||
newcol > ws.dwMaximumWindowSize.X) {
SetConsoleScreenBufferSize(wh, oldsize);
/* remove scrollbar if possible */
SetConsoleWindowInfo(wh, TRUE, &oldwindow);
rb_raise(rb_eArgError, "out of range winsize: [%d, %d]", newrow, newcol);
}
/* shrink screen buffer width */
ws.dwSize.X = newcol;
/* shrink screen buffer height if window height were the same */
if (oldsize.Y == ws.srWindow.Bottom - ws.srWindow.Top + 1) {
ws.dwSize.Y = newrow;
}
ws.srWindow.Left = 0;
ws.srWindow.Right = newcol - 1;
ws.srWindow.Bottom = ws.srWindow.Top + newrow -1;
if (ws.dwCursorPosition.Y > ws.srWindow.Bottom) {
console_scroll(io, ws.dwCursorPosition.Y - ws.srWindow.Bottom);
ws.dwCursorPosition.Y = ws.srWindow.Bottom;
console_goto(io, INT2FIX(ws.dwCursorPosition.Y), INT2FIX(ws.dwCursorPosition.X));
}
if (ws.srWindow.Bottom > ws.dwSize.Y - 1) {
console_scroll(io, ws.srWindow.Bottom - (ws.dwSize.Y - 1));
ws.dwCursorPosition.Y -= ws.srWindow.Bottom - (ws.dwSize.Y - 1);
console_goto(io, INT2FIX(ws.dwCursorPosition.Y), INT2FIX(ws.dwCursorPosition.X));
ws.srWindow.Bottom = ws.dwSize.Y - 1;
}
ws.srWindow.Top = ws.srWindow.Bottom - (newrow - 1);
/* perform changes to winsize */
if (!SetConsoleWindowInfo(wh, TRUE, &ws.srWindow)) {
int last_error = LAST_ERROR;
SetConsoleScreenBufferSize(wh, oldsize);
rb_syserr_fail(last_error, "SetConsoleWindowInfo");
}
/* perform screen buffer shrinking if necessary */
if ((ws.dwSize.Y < oldsize.Y || ws.dwSize.X < oldsize.X) &&
!SetConsoleScreenBufferSize(wh, ws.dwSize)) {
rb_syserr_fail(LAST_ERROR, "SetConsoleScreenBufferInfo");
}
/* remove scrollbar if possible */
if (!SetConsoleWindowInfo(wh, TRUE, &ws.srWindow)) {
rb_syserr_fail(LAST_ERROR, "SetConsoleWindowInfo");
}
#endif
return io;
}
Tries to set console size. The effect depends on the platform and the running environment.
You must require ‘io/console’ to use this method.