-1

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)

melpomene
  • 84,125
  • 8
  • 85
  • 148
albfan
  • 12,542
  • 4
  • 61
  • 80

1 Answers1

0

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.

Thomas Dickey
  • 51,086
  • 7
  • 70
  • 105