linux textui programming
setup terminal input and output
int ttyfd = open("/dev/tty", O_RDWR);
struct termios termattr;
// get terminal attr from tty
tcgetattr(ttyfd, &termattr);
// set terminal to "raw" mode
cfmakeraw(&termattr);
// turn off input buffer
termattr.c_cc[VMIN] = 1;
termattr.c_cc[VTIME] = 0;
// apply terminal attr to tty
tcsetattr(ttyfd, TCSAFLUSH, &termattr);
move cursor
you can use termcap to control terminal:
// from: busybox editors/vi.c
// VT102 ESC sequences.
// See "Xterm Control Sequences"
// http://invisible-island.net/xterm/ctlseqs/ctlseqs.html
#define ESC "\033"
// Cursor to given coordinate (1,1: top left)
#define ESC_SET_CURSOR_POS ESC"[%u;%uH"
int textui_setcur(int ttyfd, unsigned int col, unsigned int row)
{
char buf[32];
snprintf(buf, 32, ESC_SET_CURSOR_POS, row, col);
return write(ttyfd, buf, strlen(buf));
}
move cursor to 2, 5:
textui_setcur(ttyfd,2,5);
clear screen
// from: busybox editors/vi.c
// Clear-to-end-of-screen.
// (We use default param here.
// Full sequence is "ESC [ <num> J",
// <num> is 0/1/2 = "erase below/above/all".)
#define ESC_CLEAR2EOS ESC"[J"
int textui_clearterm(int ttyfd)
{
int ret;
ret = textui_setcur(ttyfd, 1, 1);
if (ret < 0)
return ret;
char buf[32];
snprintf(buf, 32, ESC_CLEAR2EOS);
return write(ttyfd, buf, strlen(buf));
}
make screen blank:
textui_clearterm(ttyfd);
draw a string
it will draw “Hello World” on 4, 5
char *msg = "Hello World";
textui_setcur(ttyfd,4,5);
write(ttyfd,msg,strlen(msg));
erase a string
erase a string is also simple:
it will clean “Hello World” on 4, 5 (just fill space)
msg = " ";
textui_setcur(ttyfd,4,5);
write(ttyfd,msg,strlen(msg));
get a char from input
after setup terminal, getchar() is like getch();
int c;
while (1) {
c = getchar();
textui_setcur(ttyfd,4,5);
write(ttyfd,&c,1);
if (c == 'q')
break;
}
get terminal size
struct winsize wsz;
ioctl(ttyfd, TIOCGWINSZ, &wsz);
printf("COL: %d, ROW: %d\n", wsz.ws_col, wsz.ws_row);