/* * Grand digital clock for curses compatible terminals * Usage: grdc [-st] [n] -- run for n seconds (default infinity) * grdc -c n -- countdown n seconds * Flags: -c: Countdown timer mode * -s: scroll * -t: output time in 12-hour format * * * modified 10-18-89 for curses (jrl) * 10-18-89 added signal handling * 02-18-02 added countdown timer mode * * modified 03-25-03 for 12 hour option * - Samy Al Bahra */ #include #include #include #include #include #include #define YBASE 10 #define XBASE 10 #define XLENGTH 58 #define YDEPTH 7 static struct timespec now; static struct tm *tm; static struct timespec end; static short disp[11] = { 075557, 011111, 071747, 071717, 055711, 074717, 074757, 071111, 075757, 075717, 002020 }; static long old[6], next[6], new[6], mask; static volatile sig_atomic_t sigtermed; static int hascolor = 0; static void set(int, int); static void standt(int); static void movto(int, int); static void sighndl(int); static void usage(void) __dead2; static void sighndl(int signo) { sigtermed = signo; } int main(int argc, char *argv[]) { struct timespec delay; time_t prev_sec; long t, a; int i, j, s, k; int n; int ch; bool scrol = false, t12 = false, timer = false; int hour, minute, second; while ((ch = getopt(argc, argv, "cst")) != -1) switch (ch) { case 'c': timer = true; break; case 's': scrol = true; break; case 't': t12 = true; break; case '?': default: usage(); /* NOTREACHED */ } argc -= optind; argv += optind; if ((argc > 1) || (argc == 0 && timer)) { usage(); /* NOTREACHED */ } if (argc > 0) { n = atoi(*argv) + 1; if (n < 1) { warnx("number of seconds is out of range"); usage(); /* NOTREACHED */ } } else n = 0; if (timer && n == 0) return(0); initscr(); signal(SIGINT,sighndl); signal(SIGTERM,sighndl); signal(SIGHUP,sighndl); cbreak(); noecho(); curs_set(0); hascolor = has_colors(); if (hascolor) { start_color(); init_pair(1, COLOR_BLACK, COLOR_RED); init_pair(2, COLOR_RED, COLOR_BLACK); init_pair(3, COLOR_WHITE, COLOR_BLACK); attrset(COLOR_PAIR(2)); } clear(); refresh(); if (hascolor) { attrset(COLOR_PAIR(3)); mvaddch(YBASE - 2, XBASE - 3, ACS_ULCORNER); hline(ACS_HLINE, XLENGTH); mvaddch(YBASE - 2, XBASE - 2 + XLENGTH, ACS_URCORNER); mvaddch(YBASE + YDEPTH - 1, XBASE - 3, ACS_LLCORNER); hline(ACS_HLINE, XLENGTH); mvaddch(YBASE + YDEPTH - 1, XBASE - 2 + XLENGTH, ACS_LRCORNER); move(YBASE - 1, XBASE - 3); vline(ACS_VLINE, YDEPTH); move(YBASE - 1, XBASE - 2 + XLENGTH); vline(ACS_VLINE, YDEPTH); attrset(COLOR_PAIR(2)); } clock_gettime(CLOCK_REALTIME_FAST, &now); prev_sec = now.tv_sec; if (timer) { end = now; end.tv_sec += n; } do { mask = 0; if (!timer) { tm = localtime(&now.tv_sec); if (t12) { if (tm->tm_hour < 12) { if (tm->tm_hour == 0) tm->tm_hour = 12; mvaddstr(YBASE + 5, XBASE + 52, "AM"); } else { if (tm->tm_hour > 12) tm->tm_hour -= 12; mvaddstr(YBASE + 5, XBASE + 52, "PM"); } } hour = tm->tm_hour; minute = tm->tm_min; second = tm->tm_sec; } else { n = end.tv_sec - now.tv_sec; if (n <= 0) break; hour = (n / 3600) % 100; minute = (n / 60) % 60; second = n % 60; } set(second % 10, 0); set(second / 10, 4); set(minute % 10, 10); set(minute / 10, 14); set(hour % 10, 20); set(hour / 10, 24); set(10, 7); set(10, 17); for(k=0; k<6; k++) { if(scrol) { for(i=0; i<5; i++) new[i] = (new[i]&~mask) | (new[i+1]&mask); new[5] = (new[5]&~mask) | (next[k]&mask); } else new[k] = (new[k]&~mask) | (next[k]&mask); next[k] = 0; for(s=1; s>=0; s--) { standt(s); for(i=0; i<6; i++) { if((a = (new[i]^old[i])&(s ? new : old)[i]) != 0) { for(j=0,t=1<<26; t; t>>=1,j++) { if(a&t) { if(!(a&(t<<1))) { movto(YBASE + i, XBASE + 2*j); } addstr(" "); } } } if(!s) { old[i] = new[i]; } } if(!s) { refresh(); } } } movto(6, 0); refresh(); clock_gettime(CLOCK_REALTIME_FAST, &now); if (now.tv_sec == prev_sec) { if (delay.tv_nsec > 0) { delay.tv_sec = 0; delay.tv_nsec = 1000000000 - now.tv_nsec; } else { delay.tv_sec = 1; delay.tv_nsec = 0; } nanosleep(&delay, NULL); clock_gettime(CLOCK_REALTIME_FAST, &now); } n -= now.tv_sec - prev_sec; prev_sec = now.tv_sec; if (sigtermed) { standend(); clear(); refresh(); endwin(); errx(1, "terminated by signal %d", (int)sigtermed); } } while (n); standend(); clear(); refresh(); endwin(); return(0); } static void set(int t, int n) { int i, m; m = 7<>(4-i)*3)&07)<