¿Obteniendo el ancho del terminal en C?
He estado buscando una manera de obtener el ancho del terminal desde mi programa C. Lo que sigo pensando es algo como:
#include <sys/ioctl.h>
#include <stdio.h>
int main (void)
{
struct ttysize ts;
ioctl(0, TIOCGSIZE, &ts);
printf ("lines %d\n", ts.ts_lines);
printf ("columns %d\n", ts.ts_cols);
}
Pero cada vez que lo intento lo consigo
austin@:~$ gcc test.c -o test
test.c: In function ‘main’:
test.c:6: error: storage size of ‘ts’ isn’t known
test.c:7: error: ‘TIOCGSIZE’ undeclared (first use in this function)
test.c:7: error: (Each undeclared identifier is reported only once
test.c:7: error: for each function it appears in.)
¿Es esta la mejor manera de hacerlo o existe una mejor manera? Si no, ¿cómo puedo hacer que esto funcione?
EDITAR: el código fijo es
#include <sys/ioctl.h>
#include <stdio.h>
int main (void)
{
struct winsize w;
ioctl(0, TIOCGWINSZ, &w);
printf ("lines %d\n", w.ws_row);
printf ("columns %d\n", w.ws_col);
return 0;
}
¿Has considerado usar getenv() ? Le permite obtener las variables de entorno del sistema que contienen las columnas y líneas de los terminales.
Alternativamente, usando su método, si desea ver lo que el kernel ve como el tamaño del terminal (mejor en caso de que se cambie el tamaño del terminal), necesitará usar TIOCGWINSZ, a diferencia de su TIOCGSIZE, así:
struct winsize w;
ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
y el código completo:
#include <sys/ioctl.h>
#include <stdio.h>
#include <unistd.h>
int main (int argc, char **argv)
{
struct winsize w;
ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
printf ("lines %d\n", w.ws_row);
printf ("columns %d\n", w.ws_col);
return 0; // make sure your main returns int
}
Este ejemplo es un poco largo, pero creo que es la forma más portátil de detectar las dimensiones del terminal. Esto también maneja eventos de cambio de tamaño.
Como sugieren tim y rlbond, estoy usando ncurses. Garantiza una gran mejora en la compatibilidad del terminal en comparación con la lectura directa de variables de entorno.
#include <ncurses.h>
#include <string.h>
#include <signal.h>
// SIGWINCH is called when the window is resized.
void handle_winch(int sig){
signal(SIGWINCH, SIG_IGN);
// Reinitialize the window to update data structures.
endwin();
initscr();
refresh();
clear();
char tmp[128];
sprintf(tmp, "%dx%d", COLS, LINES);
// Approximate the center
int x = COLS / 2 - strlen(tmp) / 2;
int y = LINES / 2 - 1;
mvaddstr(y, x, tmp);
refresh();
signal(SIGWINCH, handle_winch);
}
int main(int argc, char *argv[]){
initscr();
// COLS/LINES are now set
signal(SIGWINCH, handle_winch);
while(getch() != 27){
/* Nada */
}
endwin();
return(0);
}