einpoklum
einpoklum

Reputation: 132108

Is there a (more) reasonable way to determine the width of a terminal targeted by an ostream?

I have a function which prints some text to an ostream& it receives. I would like to make it adapt to the terminal width, if the ostream targets a terminal, and otherwise default to some value.

What I do right now is the following:

  1. Get an ofstream from the ostream.
  2. Get a FILE* from the ofstream.
  3. Get an integer file descriptor from the FILE*.
  4. Do ioctl(file_descriptor, TIOCGWINSZ, &my_struct_winsize);

with steps 1 and 2 bring due to this SO answer:

Getting a FILE* from a std::fstream

but they are non-portable and GCC-specific (and I'm not sure they'll work for ostreams other than cout/cerr/cin). Can I do better than this?

Upvotes: 2

Views: 110

Answers (1)

Thomas Dickey
Thomas Dickey

Reputation: 54583

None of that is gcc-specific. For the rest, TIOCGWINSZ is widely implemented and used with POSIX termios (terminal I/O), although it and the corresponding SIGWINCH are oddly enough not in POSIX. Other methods of getting terminal width (still for POSIX platforms, not generally applicable to Windows):

  • testing environment variables COLUMNS and LINES (many terminal applications, including those using curses do this, e.g., see use_env, provided by any X/Open curses implementation such as ncurses).
  • using ECMA-48 cursor position report as done by the resize program.

For Windows, none of that applies. You would get the information from one of the Console API calls such as GetConsoleScreenBufferInfo. Cygwin is a special case, because it runs (more or less) POSIX-like applications which work with the ioctl as well as POSIX terminal I/O. MinGW is lower-level, and does not provide any real extension to the Console API in this area.

Further reading:

Upvotes: 1

Related Questions