find: Correct ls(1) equivalent command for -ls primary
[freebsd/src.git] / usr.bin / grdc / grdc.c
blob07d12f5a7fb07824428fbe2b8c68d57e80cc8c78
1 /*
2 * Grand digital clock for curses compatible terminals
3 * Usage: grdc [-st] [n] -- run for n seconds (default infinity)
4 * grdc -c n -- countdown n seconds
5 * Flags: -c: Countdown timer mode
6 * -s: scroll
7 * -t: output time in 12-hour format
10 * modified 10-18-89 for curses (jrl)
11 * 10-18-89 added signal handling
12 * 02-18-02 added countdown timer mode
14 * modified 03-25-03 for 12 hour option
15 * - Samy Al Bahra <samy@kerneled.com>
18 #include <err.h>
19 #include <ncurses.h>
20 #include <signal.h>
21 #include <stdlib.h>
22 #include <time.h>
23 #include <unistd.h>
25 #define YBASE 10
26 #define XBASE 10
27 #define XLENGTH 58
28 #define YDEPTH 7
30 static struct timespec now;
31 static struct tm *tm;
32 static struct timespec end;
34 static short disp[11] = {
35 075557, 011111, 071747, 071717, 055711,
36 074717, 074757, 071111, 075757, 075717, 002020
38 static long old[6], next[6], new[6], mask;
40 static volatile sig_atomic_t sigtermed;
42 static int hascolor = 0;
44 static void set(int, int);
45 static void standt(int);
46 static void movto(int, int);
47 static void sighndl(int);
48 static void usage(void) __dead2;
50 static void
51 sighndl(int signo)
54 sigtermed = signo;
57 int
58 main(int argc, char *argv[])
60 struct timespec delay;
61 time_t prev_sec;
62 long t, a;
63 int i, j, s, k;
64 int n;
65 int ch;
66 bool scrol = false, t12 = false, timer = false;
67 int hour, minute, second;
69 while ((ch = getopt(argc, argv, "cst")) != -1)
70 switch (ch) {
71 case 'c':
72 timer = true;
73 break;
74 case 's':
75 scrol = true;
76 break;
77 case 't':
78 t12 = true;
79 break;
80 case '?':
81 default:
82 usage();
83 /* NOTREACHED */
85 argc -= optind;
86 argv += optind;
88 if ((argc > 1) || (argc == 0 && timer)) {
89 usage();
90 /* NOTREACHED */
93 if (argc > 0) {
94 n = atoi(*argv) + 1;
95 if (n < 1) {
96 warnx("number of seconds is out of range");
97 usage();
98 /* NOTREACHED */
100 } else
101 n = 0;
103 if (timer && n == 0)
104 return(0);
106 initscr();
108 signal(SIGINT,sighndl);
109 signal(SIGTERM,sighndl);
110 signal(SIGHUP,sighndl);
112 cbreak();
113 noecho();
114 curs_set(0);
116 hascolor = has_colors();
118 if (hascolor) {
119 start_color();
120 init_pair(1, COLOR_BLACK, COLOR_RED);
121 init_pair(2, COLOR_RED, COLOR_BLACK);
122 init_pair(3, COLOR_WHITE, COLOR_BLACK);
123 attrset(COLOR_PAIR(2));
126 clear();
127 refresh();
129 if (hascolor) {
130 attrset(COLOR_PAIR(3));
132 mvaddch(YBASE - 2, XBASE - 3, ACS_ULCORNER);
133 hline(ACS_HLINE, XLENGTH);
134 mvaddch(YBASE - 2, XBASE - 2 + XLENGTH, ACS_URCORNER);
136 mvaddch(YBASE + YDEPTH - 1, XBASE - 3, ACS_LLCORNER);
137 hline(ACS_HLINE, XLENGTH);
138 mvaddch(YBASE + YDEPTH - 1, XBASE - 2 + XLENGTH, ACS_LRCORNER);
140 move(YBASE - 1, XBASE - 3);
141 vline(ACS_VLINE, YDEPTH);
143 move(YBASE - 1, XBASE - 2 + XLENGTH);
144 vline(ACS_VLINE, YDEPTH);
146 attrset(COLOR_PAIR(2));
148 clock_gettime(CLOCK_REALTIME_FAST, &now);
149 prev_sec = now.tv_sec;
150 if (timer) {
151 end = now;
152 end.tv_sec += n;
154 do {
155 mask = 0;
156 if (!timer) {
157 tm = localtime(&now.tv_sec);
158 if (t12) {
159 if (tm->tm_hour < 12) {
160 if (tm->tm_hour == 0)
161 tm->tm_hour = 12;
162 mvaddstr(YBASE + 5, XBASE + 52, "AM");
163 } else {
164 if (tm->tm_hour > 12)
165 tm->tm_hour -= 12;
166 mvaddstr(YBASE + 5, XBASE + 52, "PM");
169 hour = tm->tm_hour;
170 minute = tm->tm_min;
171 second = tm->tm_sec;
172 } else {
173 n = end.tv_sec - now.tv_sec;
174 if (n <= 0)
175 break;
176 hour = (n / 3600) % 100;
177 minute = (n / 60) % 60;
178 second = n % 60;
180 set(second % 10, 0);
181 set(second / 10, 4);
182 set(minute % 10, 10);
183 set(minute / 10, 14);
184 set(hour % 10, 20);
185 set(hour / 10, 24);
186 set(10, 7);
187 set(10, 17);
188 for(k=0; k<6; k++) {
189 if(scrol) {
190 for(i=0; i<5; i++)
191 new[i] = (new[i]&~mask) | (new[i+1]&mask);
192 new[5] = (new[5]&~mask) | (next[k]&mask);
193 } else
194 new[k] = (new[k]&~mask) | (next[k]&mask);
195 next[k] = 0;
196 for(s=1; s>=0; s--) {
197 standt(s);
198 for(i=0; i<6; i++) {
199 if((a = (new[i]^old[i])&(s ? new : old)[i]) != 0) {
200 for(j=0,t=1<<26; t; t>>=1,j++) {
201 if(a&t) {
202 if(!(a&(t<<1))) {
203 movto(YBASE + i, XBASE + 2*j);
205 addstr(" ");
209 if(!s) {
210 old[i] = new[i];
213 if(!s) {
214 refresh();
218 movto(6, 0);
219 refresh();
220 clock_gettime(CLOCK_REALTIME_FAST, &now);
221 if (now.tv_sec == prev_sec) {
222 if (delay.tv_nsec > 0) {
223 delay.tv_sec = 0;
224 delay.tv_nsec = 1000000000 - now.tv_nsec;
225 } else {
226 delay.tv_sec = 1;
227 delay.tv_nsec = 0;
229 nanosleep(&delay, NULL);
230 clock_gettime(CLOCK_REALTIME_FAST, &now);
232 n -= now.tv_sec - prev_sec;
233 prev_sec = now.tv_sec;
234 if (sigtermed) {
235 standend();
236 clear();
237 refresh();
238 endwin();
239 errx(1, "terminated by signal %d", (int)sigtermed);
241 } while (n);
242 standend();
243 clear();
244 refresh();
245 endwin();
246 return(0);
249 static void
250 set(int t, int n)
252 int i, m;
254 m = 7<<n;
255 for(i=0; i<5; i++) {
256 next[i] |= ((disp[t]>>(4-i)*3)&07)<<n;
257 mask |= (next[i]^old[i])&m;
259 if(mask&m)
260 mask |= m;
263 static void
264 standt(int on)
266 if (on) {
267 if(hascolor) {
268 attron(COLOR_PAIR(1));
269 } else {
270 attron(A_STANDOUT);
272 } else {
273 if(hascolor) {
274 attron(COLOR_PAIR(2));
275 } else {
276 attroff(A_STANDOUT);
281 static void
282 movto(int line, int col)
284 move(line, col);
287 static void
288 usage(void)
291 (void)fprintf(stderr, "usage: grdc [-st] [n]\n"
292 " grdc -c n\n");
293 exit(1);