+ time_t now;
+ struct tm *tm;
+ long t, a;
+ int i, j, s, k;
+ int count = 0;
+ FILE *ofp = stdout;
+ FILE *ifp = stdin;
+ bool smooth = FALSE;
+ bool stages = FALSE;
+ time_t starts = 0;
+
+ setlocale(LC_ALL, "");
+
+ CATCHALL(sighndl);
+
+ while ((k = getopt(argc, argv, "nst:")) != -1) {
+ switch (k) {
+ case 'n':
+ ifp = fopen("/dev/null", "r");
+ redirected = TRUE;
+ break;
+ case 's':
+ smooth = TRUE;
+ break;
+ case 't':
+ starts = parse_time(optarg);
+ break;
+ default:
+ usage();
+ }
+ }
+ if (optind < argc) {
+ count = atoi(argv[optind++]);
+ assert(count >= 0);
+ }
+ if (optind < argc)
+ usage();
+
+ if (redirected) {
+ char *name = getenv("TERM");
+ if (name == 0
+ || newterm(name, ofp, ifp) == 0) {
+ fprintf(stderr, "cannot open terminal\n");
+ ExitProgram(EXIT_FAILURE);
+ }
+
+ } else {
+ initscr();
+ }
+ cbreak();
+ noecho();
+ nodelay(stdscr, 1);
+ curs_set(0);
+
+ hascolor = has_colors();
+
+ if (hascolor) {
+ short bg = COLOR_BLACK;
+ start_color();
+#if HAVE_USE_DEFAULT_COLORS
+ if (use_default_colors() == OK)
+ bg = -1;
+#endif
+ init_pair(PAIR_DIGITS, COLOR_BLACK, COLOR_RED);
+ init_pair(PAIR_OTHERS, COLOR_RED, bg);
+ init_pair(PAIR_FRAMES, COLOR_WHITE, bg);
+ (void) attrset(AttrArg(COLOR_PAIR(PAIR_OTHERS), 0));
+ }
+
+ restart:
+ for (j = 0; j < 5; j++)
+ older[j] = newer[j] = next[j] = 0;
+
+ clear();
+ drawbox(FALSE);
+
+ do {
+ char buf[40];
+
+ if (starts != 0) {
+ now = ++starts;
+ } else {
+ time(&now);
+ }
+ tm = localtime(&now);
+
+ mask = 0;
+ set(tm->tm_sec % 10, 0);
+ set(tm->tm_sec / 10, 4);
+ set(tm->tm_min % 10, 10);
+ set(tm->tm_min / 10, 14);
+ set(tm->tm_hour % 10, 20);
+ set(tm->tm_hour / 10, 24);
+ set(10, 7);
+ set(10, 17);
+
+ for (k = 0; k < 6; k++) {
+ if (smooth) {
+ for (i = 0; i < 5; i++)
+ newer[i] = (newer[i] & ~mask) | (newer[i + 1] & mask);
+ newer[5] = (newer[5] & ~mask) | (next[k] & mask);
+ } else {
+ newer[k] = (newer[k] & ~mask) | (next[k] & mask);
+ }
+ next[k] = 0;
+ for (s = 1; s >= 0; s--) {
+ standt(s);
+ for (i = 0; i < 6; i++) {
+ if ((a = (newer[i] ^ older[i]) & (s ? newer : older)[i])
+ != 0) {
+ for (j = 0, t = 1 << 26; t; t >>= 1, j++) {
+ if (a & t) {
+ if (!(a & (t << 1))) {
+ move(YBASE + i, XBASE + 2 * j);
+ }
+ addstr(" ");
+ }
+ }
+ }
+ if (!s) {
+ older[i] = newer[i];
+ }
+ }
+ if (!s) {
+ if (smooth)
+ drawbox(TRUE);
+ refresh();
+ /*
+ * If we're scrolling, space out the refreshes to fake
+ * movement. That's 7 frames, or 6 intervals, which would
+ * be 166 msec if we spread it out over a second. It looks
+ * better (but will work on a slow terminal, e.g., less
+ * than 9600bd) to squeeze that into a half-second, and use
+ * half of 170 msec to ensure that the program doesn't eat
+ * a lot of time when asking what time it is, at the top of
+ * this loop -T.Dickey
+ */
+ if (smooth)
+ napms(85);
+ if (stages) {
+ stages = FALSE;
+ switch (wgetch(stdscr)) {
+ case 'q':
+ count = 1;
+ break;
+ case 'S':
+ stages = TRUE;
+ /* FALLTHRU */
+ case 's':
+ nodelay(stdscr, FALSE);
+ break;
+ case ' ':
+ nodelay(stdscr, TRUE);
+ break;
+#ifdef KEY_RESIZE
+ case KEY_RESIZE:
+#endif
+ case '?':
+ goto restart;
+ case ERR:
+ check_term();
+ /* FALLTHRU */
+ default:
+ continue;
+ }
+ }
+ }
+ }
+ }
+
+ /* this depends on the detailed format of ctime(3) */
+ _nc_STRNCPY(buf, ctime(&now), (size_t) 30);
+ {
+ char *d2 = buf + 10;
+ char *s2 = buf + 19;
+ while ((*d2++ = *s2++) != '\0') ;
+ }
+ MvAddStr(16, 30, buf);
+
+ move(6, 0);
+ drawbox(FALSE);
+ refresh();
+
+ /*
+ * If we're not smooth-scrolling, wait 1000 msec (1 sec). Use napms()
+ * rather than sleep() because the latter does odd things on some
+ * systems, e.g., suspending output as well.
+ */
+ if (smooth)
+ napms(500);
+ else
+ napms(1000);
+
+ /*
+ * This is a safe way to check if we're interrupted - making the signal
+ * handler set a flag that we can check. Since we're running
+ * nodelay(), the wgetch() call returns immediately, and in particular
+ * will return an error if interrupted. This works only if we can
+ * read from the input, of course.
+ */
+ stages = FALSE;
+ switch (wgetch(stdscr)) {
+ case 'q':
+ count = 1;
+ break;
+ case 'S':
+ stages = TRUE;
+ /* FALLTHRU */
+ case 's':
+ nodelay(stdscr, FALSE);
+ break;
+ case ' ':
+ nodelay(stdscr, TRUE);
+ break;
+#ifdef KEY_RESIZE
+ case KEY_RESIZE:
+#endif
+ case '?':
+ goto restart;
+ case ERR:
+ check_term();
+ /* FALLTHRU */
+ default:
+ continue;
+ }
+ } while (--count);
+ (void) standend();
+ endwin();
+ ExitProgram(EXIT_SUCCESS);