Eu tenho procurado uma maneira de obter a largura do terminal de dentro do meu programa em C. O que eu continuo chegando é algo nos moldes de:
#include #include int main (void) { struct ttysize ts; ioctl(0, TIOCGSIZE, &ts); printf ("lines %d\n", ts.ts_lines); printf ("columns %d\n", ts.ts_cols); }
Mas toda vez que eu tento, fico
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.)
Esta é a melhor maneira de fazer isso, ou existe uma maneira melhor? Se não como posso fazer isso funcionar?
EDIT: código fixo é
#include #include 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; }
Você já pensou em usar getenv () ? Ele permite que você obtenha as variables de ambiente do sistema que contêm as colunas e linhas dos terminais.
Alternativamente, usando seu método, se você quiser ver o que o kernel vê como o tamanho do terminal (melhor caso o terminal seja redimensionado), você precisaria usar o TIOCGWINSZ, ao contrário do seu TIOCGSIZE, da seguinte forma:
struct winsize w; ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
e o código completo:
#include #include #include 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 exemplo é um pouco longo, mas acredito que seja a forma mais portátil de detectar as dimensões dos terminais. Isso também lida com events de redimensionamento.
Como tim e rlbond sugerem, estou usando ncurses. Ele garante uma grande melhoria na compatibilidade do terminal em comparação com as variables de ambiente de leitura diretamente.
#include #include #include // 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); }
#include #include #include #include static char termbuf[2048]; int main(void) { char *termtype = getenv("TERM"); if (tgetent(termbuf, termtype) < 0) { error(EXIT_FAILURE, 0, "Could not access the termcap data base.\n"); } int lines = tgetnum("li"); int columns = tgetnum("co"); printf("lines = %d; columns = %d.\n", lines, columns); return 0; }
Precisa ser compilado com -ltermcap
. Há muitas outras informações úteis que você pode obter usando o termcap. Verifique o manual termcap usando info termcap
para mais detalhes.
Se você tiver ncurses instaladas e estiver usando, você pode usar getmaxyx()
para encontrar as dimensões do terminal.
Supondo que você esteja no Linux, eu acho que você quer usar a biblioteca ncurses . Tenho certeza que o material ttysize que você tem não está no stdlib.
Aqui estão as chamadas de function para a variável de ambiente já sugerida:
int lines = atoi(getenv("LINES")); int columns = atoi(getenv("COLUMNS"));