Terminal control/Dimensions

From Rosetta Code
Revision as of 19:42, 14 July 2011 by rosettacode>Markhobley ({{omit from|GUISS}})
Task
Terminal control/Dimensions
You are encouraged to solve this task according to the task description, using any language you may know.

Determine the height and width of the terminal, and store this information into variables for subsequent use.


C

C provides no standard way to find the size of a terminal.

Library: BSD libc

BSD systems (and some other Unix clones) have TIOCGWINSZ. This ioctl(2) call gets the "window size" of a tty(4) device.

Almost all terminal devices can do NAWS (Negotiate About Window Size). A terminal emulator like xterm(1) should set the size. A network server like sshd(1) should copy the size from its client. Other devices, such as plain serial ports, might not know the window size.

Works with: OpenBSD version 4.9

<lang c>#include <sys/ioctl.h> /* ioctl, TIOCGWINSZ */

  1. include <err.h> /* err */
  2. include <fcntl.h> /* open */
  3. include <stdio.h> /* printf */
  4. include <unistd.h> /* close */

int main() { struct winsize ws; int fd;

/* Open the controlling terminal. */ fd = open("/dev/tty", O_RDWR); if (fd < 0) err(1, "/dev/tty");

/* Get window size of terminal. */ if (ioctl(fd, TIOCGWINSZ, &ws) < 0) err(1, "/dev/tty");

printf("%d rows by %d columns\n", ws.ws_row, ws.ws_col); printf("(%d by %d pixels)\n", ws.ws_xpixel, ws.ws_ypixel);

close(fd); return 0; }</lang>

Windows

Grab a console screen handle, then call GetConsoleScreenBufferInfo() to get the information. Most consoles have a scroll bar and hold hundreds of lines, but the window shows only 25 or 50 lines. Use the window coordinates to calculate the window size.

Works with: MinGW

<lang c>#include <windows.h>

  1. include <wchar.h>

int main() { HANDLE console; CONSOLE_SCREEN_BUFFER_INFO info; short rows; short columns;

/* Create a handle to the console screen. */ console = CreateFileW(L"CONOUT$", GENERIC_READ | GENERIC_WRITE, 0, 0, 0, 0, NULL); if (console == INVALID_HANDLE_VALUE) return 1;

/* Calculate the size of the console window. */ if (GetConsoleScreenBufferInfo(console, &info) == 0) return 1; CloseHandle(console); columns = info.srWindow.Right - info.srWindow.Left + 1; rows = info.srWindow.Bottom - info.srWindow.Top + 1;

wprintf(L"%d columns by %d rows\n", columns, rows);

return 0; }</lang>

Euphoria

<lang Euphoria>include graphics.e

sequence vc integer term_height, term_width

vc = video_config()

term_height = vc[VC_LINES] term_width = vc[VC_COLUMNS]

printf(1,"Terminal height is %d\n",term_height) printf(1,"Terminal width is %d\n",term_width)</lang>

Forth

Works with: GNU Forth

<lang forth>variable term-width variable term-height

form ( width height ) term-height ! term-width !</lang>

J

This is not well supported in J, but since the terminal window can be resized at any time and can have its font changed and so on, good design generally dictates that this kind of information be ignored.

Nevertheless, assuming J version 6 in its usual environment, to determine its width and height, in pixels, you can use:

<lang j>_2 {.qsmsize_jijs_</lang>

Note also that this will typically include 37 extra pixels horizontally and 79 extra pixels vertically, which are not available to display text. In other words, if the result was 700 500 you would really have 663 pixels of width and 421 pixels of height.

PicoLisp

<lang PicoLisp>(setq

  Width (in '(tput cols) (read))
  Height (in '(tput lines) (read)) )</lang>

PureBasic

PureBasic does not have native functions for reading the size of this window, but supports API-functions that allows this.

This code is for Windows only. <lang PureBasic>Macro ConsoleHandle()

 GetStdHandle_( #STD_OUTPUT_HANDLE )

EndMacro

Procedure ConsoleWidth()

 Protected CBI.CONSOLE_SCREEN_BUFFER_INFO
 Protected hConsole = ConsoleHandle()
 GetConsoleScreenBufferInfo_( hConsole, @CBI )
 ProcedureReturn CBI\srWindow\right - CBI\srWindow\left + 1

EndProcedure

Procedure ConsoleHeight()

 Protected CBI.CONSOLE_SCREEN_BUFFER_INFO
 Protected hConsole = ConsoleHandle()
 GetConsoleScreenBufferInfo_( hConsole, @CBI )
 ProcedureReturn CBI\srWindow\bottom - CBI\srWindow\top + 1

EndProcedure

If OpenConsole()

 x$=Str(ConsoleWidth())
 y$=Str(ConsoleHeight())
 PrintN("This window is "+x$+"x"+y$+ " chars.")
 ;
 Print(#CRLF$+"Press ENTER to exit"):Input()

EndIf</lang>

Python

Works with: Python version 2.6
Library: ctypes

This uses the ctypes library in order to get the console dimensions on Windows. This code is a slight refactoring of an ActiveState Recipe. For Linux, the tput utility is used.

<lang python>import os

def get_windows_terminal():

   from ctypes import windll, create_string_buffer
   h = windll.kernel32.GetStdHandle(-12)
   csbi = create_string_buffer(22)
   res = windll.kernel32.GetConsoleScreenBufferInfo(h, csbi)
   #return default size if actual size can't be determined
   if not res: return 80, 25 
   import struct
   (bufx, bufy, curx, cury, wattr, left, top, right, bottom, maxx, maxy)\
   = struct.unpack("hhhhHhhhhhh", csbi.raw)
   width = right - left + 1
   height = bottom - top + 1
   return width, height

def get_linux_terminal():

   width = os.popen('tput cols', 'r').readline()
   height = os.popen('tput lines', 'r').readline()
   return int(width), int(height)

print get_linux_terminal() if os.name == 'posix' else get_windows_terminal() </lang>

Retro

This information is provided by Retro in the ch (height) and cw (width) variables. You can manually obtain it using the io ports.

<lang Retro>-3 5 out wait 5 in !cw -4 5 out wait 5 in !ch</lang>

REXX

Works with: brexx
Works with: regina
Works with: rexximc

Some Rexx interpreters don't provide basic terminal control as part of the language.
However, it's possible to determine the size of the terminal window by using external system commands: <lang rexx> width = 'tput'( 'cols' ) height = 'tput'( 'lines' )

say 'The terminal is' width 'characters wide' say 'and has' height 'lines' </lang> Older REXX interpretors (such as all the IBM mainframe REXX interpretors, PC/REXX), and R4 support the
LINESIZE built-in function which returns the screen's width.
It's syntax is: <lang rexx> width=linesize() </lang>

Tcl

Translation of: UNIX Shell

<lang tcl>set width [exec tput cols] set height [exec tput lines] puts "The terminal is $width characters wide and has $height lines"</lang>

UNIX Shell

Works with: Bourne Shell
Works with: bash

<lang sh>#!/bin/sh WIDTH=`tput cols` HEIGHT=`tput lines` echo "The terminal is $WIDTH characters wide and has $HEIGHT lines"</lang>