问题
I want to create an overlay in terminal
This Q&D shows the time in right/bottom
#include <stdio.h>
#include <stdlib.h>
#include <termcap.h>
#include <termios.h>
#include <error.h>
#include <unistd.h>
#include <time.h>
static char termbuf[2048];
int main()
{
char *termtype = getenv("TERM");
time_t timer;
char buffer[26];
struct tm* tm_info;
if (tgetent(termbuf, termtype) < 0) {
error(EXIT_FAILURE, 0, "Could not access the termcap data base.\n");
return 1;
}
int lines = tgetnum("li");
int columns = tgetnum("co");
int pos=1;
while (1) {
time(&timer);
tm_info = localtime(&timer);
strftime(buffer, 26, "%Y-%m-%d %H:%M:%S", tm_info);
printf("\033[s");
fflush(stdout);
printf("\033[%d;%dH%s\n", lines - 2, columns - 20, buffer);
printf("\033[u");
sleep(1);
}
return 0;
}
it is compiled with:
$ gcc time-overlay.c -ltermcap -o time-overlay
And to use it:
$ ./time-overlay &
It will show:
2017-04-29 12:29:15
And keep updating time.
To stop:
$ fg
Ctrl+C
But, is there a better way to do that with some library that abstracts low level calls (like save restore cursor position or print in some line/col)
I want to keep existing terminal output (so curses with initscr() will not work)
回答1:
This is how you would use termcap (or anything provides a termcap interface, e.g., ncurses):
#include <stdio.h>
#include <stdlib.h>
#include <termcap.h>
#include <unistd.h>
#include <string.h>
#include <time.h>
#define MAXTERM 2048
#define EndOf(s) (s) + strlen(s)
int
main(void)
{
char termbuf[MAXTERM];
char workbuf[MAXTERM];
char *working = workbuf;
int lines, columns;
char *save_cursor, *move_cursor, *restore_cursor;
if (tgetent(termbuf, getenv("TERM")) < 0) {
fprintf(stderr, "Could not access the termcap database.\n");
return EXIT_FAILURE;
}
lines = tgetnum("li");
columns = tgetnum("co");
save_cursor = tgetstr("sc", &working);
move_cursor = tgetstr("cm", &working);
restore_cursor = tgetstr("rc", &working);
while (1) {
time_t timer;
char buffer[1024];
struct tm *tm_info;
time(&timer);
tm_info = localtime(&timer);
strcpy(buffer, save_cursor);
sprintf(EndOf(buffer), tgoto(move_cursor, columns - 20, lines - 2));
strftime(EndOf(buffer), 26, "%Y-%m-%d %H:%M:%S", tm_info);
strcat(buffer, restore_cursor);
write(fileno(stderr), buffer, strlen(buffer));
sleep(1);
}
return EXIT_SUCCESS;
}
It could still be improved since the various strings returned from tgetstr
are not guaranteed to be provided by all terminal descriptions, and of course, termcap applications always have buffer-overflow issues to work around.
来源:https://stackoverflow.com/questions/43694525/implement-overlay-in-terminal