From 8ac5057a32d3241ca2ca4a353b1cb650c09e3eb0 Mon Sep 17 00:00:00 2001 From: dkf Date: Fri, 29 Mar 2019 14:22:23 +0000 Subject: Support -winsize read-only option --- doc/open.n | 16 ++++++++++++++-- unix/tclUnixChan.c | 28 +++++++++++++++++++++++++++- win/tclWinConsole.c | 31 +++++++++++++++++++++++++++++-- 3 files changed, 70 insertions(+), 5 deletions(-) diff --git a/doc/open.n b/doc/open.n index f6aca52..d128512 100644 --- a/doc/open.n +++ b/doc/open.n @@ -311,6 +311,12 @@ Note that setting this option (technically, anything that changes the terminal state from its initial value \fIvia this option\fR) will cause the channel to turn on an automatic reset of the terminal when the channel is closed. .RE +.TP +\fB\-winsize\fR +. +(Unix only; Windows has the equivalent option on console channels). This +option is query only. It retrieves a two-element list with the the current +width and height of the terminal. .VE "8.7, TIP 160" .TP \fB\-pollinterval\fR \fImsec\fR @@ -475,7 +481,7 @@ applications on the various platforms .SH "CONSOLE CHANNELS" .VS "8.7, TIP 160" On Windows only, console channels (usually \fBstdin\fR or \fBstdout\fR) -support the following option: +support the following options: .TP \fB\-inputmode\fR \fIinputMode\fR . @@ -510,8 +516,14 @@ Note that setting this option (technically, anything that changes the console state from its default \fIvia this option\fR) will cause the channel to turn on an automatic reset of the console when the channel is closed. .RE +.TP +\fB\-winsize\fR +. +This option is query only. +It retrieves a two-element list with the the current width and height of the +console that this channel is talking to. .PP -Note that the equivalent option exists on Unix, but is on the serial channel +Note that the equivalent options exist on Unix, but are on the serial channel type. .VE "8.7, TIP 160" .SH "EXAMPLES" diff --git a/unix/tclUnixChan.c b/unix/tclUnixChan.c index 152de88..ffeb0a7 100644 --- a/unix/tclUnixChan.c +++ b/unix/tclUnixChan.c @@ -1119,11 +1119,37 @@ TtyGetOptionProc( } #endif /* TIOCMGET */ +#if defined(TIOCGWINSZ) + /* + * Get option -winsize + * Option is readonly and returned by [fconfigure chan -winsize] but not + * returned by [fconfigure chan] without explicit option name. + */ + + if ((len > 1) && (strncmp(optionName, "-winsize", len) == 0)) { + struct winsize ws; + + valid = 1; + if (ioctl(fsPtr->fileState.fd, TIOCGWINSZ, &ws) < 0) { + if (interp != NULL) { + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "couldn't read terminal size: %s", + Tcl_PosixError(interp))); + } + return TCL_ERROR; + } + sprintf(buf, "%d", ws.ws_col); + Tcl_DStringAppendElement(dsPtr, buf); + sprintf(buf, "%d", ws.ws_row); + Tcl_DStringAppendElement(dsPtr, buf); + } +#endif /* TIOCGWINSZ */ + if (valid) { return TCL_OK; } return Tcl_BadChannelOption(interp, optionName, - "closemode inputmode mode queue ttystatus xchar"); + "closemode inputmode mode queue ttystatus winsize xchar"); } static const struct {int baud; speed_t speed;} speeds[] = { diff --git a/win/tclWinConsole.c b/win/tclWinConsole.c index de2723b..d07bd3a 100644 --- a/win/tclWinConsole.c +++ b/win/tclWinConsole.c @@ -1530,7 +1530,7 @@ ConsoleSetOptionProc( if (infoPtr->flags & CONSOLE_READ_OPS) { return Tcl_BadChannelOption(interp, optionName, "inputmode"); } else { - return Tcl_BadChannelOption(interp, optionName, "inputmode"); + return Tcl_BadChannelOption(interp, optionName, ""); } } @@ -1605,11 +1605,38 @@ ConsoleGetOptionProc( } } + /* + * Get option -winsize + * Option is readonly and returned by [fconfigure chan -winsize] but not + * returned by [fconfigure chan] without explicit option name. + */ + + if ((len > 1) && (strncmp(optionName, "-winsize", len) == 0)) { + CONSOLE_SCREEN_BUFFER_INFO consoleInfo; + + valid = 1; + if (!GetConsoleScreenBufferInfo(infoPtr->handle, &consoleInfo)) { + TclWinConvertError(GetLastError()); + if (interp != NULL) { + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "couldn't read console size: %s", + Tcl_PosixError(interp))); + } + return TCL_ERROR; + } + sprintf(buf, "%d", + consoleInfo.srWindow.Right - consoleInfo.srWindow.Left + 1); + Tcl_DStringAppendElement(dsPtr, buf); + sprintf(buf, "%d", + consoleInfo.srWindow.Bottom - consoleInfo.srWindow.Top + 1); + Tcl_DStringAppendElement(dsPtr, buf); + } + if (valid) { return TCL_OK; } if (infoPtr->flags & CONSOLE_READ_OPS) { - return Tcl_BadChannelOption(interp, optionName, "inputmode"); + return Tcl_BadChannelOption(interp, optionName, "inputmode winsize"); } else { return Tcl_BadChannelOption(interp, optionName, ""); } -- cgit v0.12