/**
* scroll v0.1.0
*
* $ cc scroll.c -o scroll -lcurses
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <curses.h>
const char *help_text = (
"Display a string as a scrolling banner.\n"
"\n"
"usage: scroll [-h|-v]\n"
" scroll [-l] [-m ms] [-s] string\n"
"\n"
"options:\n"
" -h display this text and exit\n"
" -v display version info and exit\n"
" -l do loop forever\n"
" -m ms milliseconds per tick (default: 100)\n"
" -s string string to display\n"
);
const char *version_text = (
"scroll v0.1.0\n"
);
#define min(x, y) ((x) < (y) ? (x) : (y))
int main(int argc, char *argv[]) {
/* string info */
char *string = NULL;
size_t len = 0;
/* terminal size */
int width = 0;
int height = 0;
/* user options */
int ms = 100; /* -m, scroll speed */
bool loop = false; /* -l, loop forever? */
/* standard flag parsing */
int opt;
while ((opt = getopt(argc, argv, "hvlm:s:")) != -1) {
switch (opt) {
case 'h':
puts(help_text);
return 0;
case 'v':
puts(version_text);
return 0;
case 'l':
loop = true;
break;
case 'm':
ms = atoi(optarg);
break;
case 's':
len = strlen(optarg);
string = malloc(len + 1);
strcpy(string, optarg);
break;
default:
return 1;
}
}
/* -s flag is optional */
if (!string && argc > optind) {
len = strlen(argv[optind]);
string = malloc(len + 1);
strcpy(string, argv[optind]);
}
/* try to read from stdin? */
if (!string) {
/* getline will allocate buffer for string */
if (getline(&string, &len, stdin) == -1) {
return 3;
}
/* len may be longer than the string */
len = strlen(string);
string[len - 1] = '\0';
}
/* no string provided */
if (!string) {
puts(help_text);
return 1;
}
initscr();
curs_set(0); /* disable cursor */
getmaxyx(stdscr, height, width);
int y = height / 2;
do {
char *p = string;
int n, x;
/* scroll in from right */
x = width;
while (x --> 0) { /* as x goes to zero */
n = min(width - x, (int)len);
clear();
mvaddnstr(y, x, p, n);
refresh();
usleep(ms * 1000);
}
/* scroll off to left */
x = len;
while (x --> 0) {
n = min(x, width);
clear();
mvaddnstr(y, 0, ++p, n);
refresh();
usleep(ms * 1000);
}
} while (loop);
endwin();
return 0;
}