/* * Draw a spinning bar at the top right of the terminal. * * Copyright (C) 2002 Tony Finch * * $dotat: things/spinner.c,v 1.15 2002/03/26 12:33:48 fanf Exp $ */ #include #include #include #include #include #include #include #include static const char copyright[] = "@(#) $Copyright: (C) 2002 Tony Finch (dot@dotat.at) $"; static const char version[] = "@(#) $dotat: things/spinner.c,v 1.15 2002/03/26 12:33:48 fanf Exp $"; static volatile sig_atomic_t winch = 1; static void sigwinch(int s) { s = s; winch = 1; } static char *progname; static void usage(void) { fprintf(stderr, "usage: %s [-n|-t format|-s string]" " [-x offset] [-y offset] [delay]\n", progname); fprintf(stderr, " -n non-intrusive -- just output a NUL character every interval\n" " -s set the sequence of characters to use in the spinner\n" " e.g. ^ or -__-ŻŻ or ··+*0O0*+ or <<{([|])}>>})]|[({\n" " -t display the time in the given format, as for strftime\n" " -x set the horizontal position\n" " -y set the vertical position\n" " positive numbers count from the top/left\n" " negative numbers count from the bottom/right\n" " delay interval between display updates in seconds (may be fractional)\n"); exit(2); } int main(int argc, char *argv[]) { const char *bars = "|/-\\"; const char *bar = ""; const char *fmt = NULL; struct sigaction sa; struct timespec tv; struct winsize ws; char buf1[64], buf2[64]; int len1, len2; int geom_y; int geom_x; int noop; int c, x, y; progname = strrchr(argv[0], '/'); if(!progname) progname = argv[0]; /* defaults */ tv.tv_sec = 60; tv.tv_nsec = 0; geom_x = -1; geom_y = +1; noop = 0; while((c = getopt(argc, argv, "ns:t:x:y:")) != -1) switch(c) { case('n'): noop = 1; continue; case('s'): bars = optarg; continue; case('t'): fmt = optarg; continue; case('x'): geom_x = atoi(optarg); continue; case('y'): geom_y = atoi(optarg); continue; default: usage(); } argc -= optind; argv += optind; if(argc > 1) usage(); if(argc == 1) { tv.tv_sec = atoi(*argv); tv.tv_nsec = (atof(*argv) - tv.tv_sec) * 1000000000; } sa.sa_handler = sigwinch; sa.sa_flags = 0; sigemptyset(&sa.sa_mask); if(sigaction(SIGWINCH, &sa, NULL) < 0) err(1, "sigaction(SIGWINCH)"); for(;;) { if(winch) { winch = 0; if(ioctl(1, TIOCGWINSZ, &ws) < 0) err(1, "ioctl(TIOCGWINSZ)"); } if(noop) { buf2[0] = '\0'; len2 = 1; } else { if(fmt) { time_t t; struct tm tm; time(&t); localtime_r(&t, &tm); len1 = strftime(buf1, sizeof(buf1), fmt, &tm); } else { if(*bar == '\0') bar = bars; buf1[0] = *bar++; buf1[1] = '\0'; len1 = 1; } if(geom_y < 0) y = ws.ws_row + geom_y + 1; else y = geom_y; if(y > ws.ws_row) y = ws.ws_row; if(y < 1) y = 1; if(geom_x < 0) x = ws.ws_col + geom_x + 1; else x = geom_x; if(x + len1 > ws.ws_col) x = ws.ws_col - len1 + 1; if(x < 1) x = 1; len2 = snprintf(buf2, sizeof(buf2), "\0337\033[%d;%dH%s\0338", y, x, buf1); } write(1, buf2, len2); nanosleep(&tv, NULL); } } /* EOF spinner.c */