]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - games/grdc/grdc.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / games / grdc / grdc.c
1 /*
2  * Grand digital clock for curses compatible terminals
3  * Usage: grdc [-st] [n]   -- run for n seconds (default infinity)
4  * Flags: -s: scroll
5  *        -t: output time in 12-hour format
6  *
7  *
8  * modified 10-18-89 for curses (jrl)
9  * 10-18-89 added signal handling
10  *
11  * modified 03-25-03 for 12 hour option
12  *     - Samy Al Bahra <samy@kerneled.com>
13  *
14  * $FreeBSD$
15  */
16
17 #include <err.h>
18 #include <ncurses.h>
19 #include <signal.h>
20 #include <stdlib.h>
21 #include <time.h>
22 #include <unistd.h>
23
24 #define YBASE   10
25 #define XBASE   10
26 #define XLENGTH 58
27 #define YDEPTH  7
28
29 static struct timespec now;
30 static struct tm *tm;
31
32 static short disp[11] = {
33         075557, 011111, 071747, 071717, 055711,
34         074717, 074757, 071111, 075757, 075717, 002020
35 };
36 static long old[6], next[6], new[6], mask;
37
38 static volatile sig_atomic_t sigtermed;
39
40 static int hascolor = 0;
41
42 static void set(int, int);
43 static void standt(int);
44 static void movto(int, int);
45 static void sighndl(int);
46 static void usage(void);
47
48 static void
49 sighndl(int signo)
50 {
51
52         sigtermed = signo;
53 }
54
55 int
56 main(int argc, char *argv[])
57 {
58         struct timespec delay;
59         time_t prev_sec;
60         long t, a;
61         int i, j, s, k;
62         int n;
63         int ch;
64         int scrol;
65         int t12;
66
67         t12 = scrol = 0;
68
69         while ((ch = getopt(argc, argv, "ts")) != -1)
70         switch (ch) {
71         case 's':
72                 scrol = 1;
73                 break;
74         case 't':
75                 t12 = 1;
76                 break;
77         case '?':
78         default:
79                 usage();
80                 /* NOTREACHED */
81         }
82         argc -= optind;
83         argv += optind;
84
85         if (argc > 1) {
86                 usage();
87                 /* NOTREACHED */
88         }
89
90         if (argc > 0) {
91                 n = atoi(*argv) + 1;
92                 if (n < 1) {
93                         warnx("number of seconds is out of range");
94                         usage();
95                         /* NOTREACHED */
96                 }
97         } else
98                 n = 0;
99
100         initscr();
101
102         signal(SIGINT,sighndl);
103         signal(SIGTERM,sighndl);
104         signal(SIGHUP,sighndl);
105
106         cbreak();
107         noecho();
108         curs_set(0);
109
110         hascolor = has_colors();
111
112         if(hascolor) {
113                 start_color();
114                 init_pair(1, COLOR_BLACK, COLOR_RED);
115                 init_pair(2, COLOR_RED, COLOR_BLACK);
116                 init_pair(3, COLOR_WHITE, COLOR_BLACK);
117                 attrset(COLOR_PAIR(2));
118         }
119
120         clear();
121         refresh();
122
123         if(hascolor) {
124                 attrset(COLOR_PAIR(3));
125
126                 mvaddch(YBASE - 2,  XBASE - 3, ACS_ULCORNER);
127                 hline(ACS_HLINE, XLENGTH);
128                 mvaddch(YBASE - 2,  XBASE - 2 + XLENGTH, ACS_URCORNER);
129
130                 mvaddch(YBASE + YDEPTH - 1,  XBASE - 3, ACS_LLCORNER);
131                 hline(ACS_HLINE, XLENGTH);
132                 mvaddch(YBASE + YDEPTH - 1,  XBASE - 2 + XLENGTH, ACS_LRCORNER);
133
134                 move(YBASE - 1,  XBASE - 3);
135                 vline(ACS_VLINE, YDEPTH);
136
137                 move(YBASE - 1,  XBASE - 2 + XLENGTH);
138                 vline(ACS_VLINE, YDEPTH);
139
140                 attrset(COLOR_PAIR(2));
141         }
142         clock_gettime(CLOCK_REALTIME_FAST, &now);
143         prev_sec = now.tv_sec;
144         do {
145                 mask = 0;
146                 tm = localtime(&now.tv_sec);
147                 set(tm->tm_sec%10, 0);
148                 set(tm->tm_sec/10, 4);
149                 set(tm->tm_min%10, 10);
150                 set(tm->tm_min/10, 14);
151
152                 if (t12) {
153                         if (tm->tm_hour > 12) {
154                                 tm->tm_hour -= 12;
155                                 mvaddstr(YBASE + 5, XBASE + 52, "PM");
156                         } else {
157                                 if (tm->tm_hour == 0)
158                                         tm->tm_hour = 12;
159
160                                 mvaddstr(YBASE + 5, XBASE + 52, "AM");
161                         }
162                 }
163
164                 set(tm->tm_hour%10, 20);
165                 set(tm->tm_hour/10, 24);
166                 set(10, 7);
167                 set(10, 17);
168                 for(k=0; k<6; k++) {
169                         if(scrol) {
170                                 for(i=0; i<5; i++)
171                                         new[i] = (new[i]&~mask) | (new[i+1]&mask);
172                                 new[5] = (new[5]&~mask) | (next[k]&mask);
173                         } else
174                                 new[k] = (new[k]&~mask) | (next[k]&mask);
175                         next[k] = 0;
176                         for(s=1; s>=0; s--) {
177                                 standt(s);
178                                 for(i=0; i<6; i++) {
179                                         if((a = (new[i]^old[i])&(s ? new : old)[i]) != 0) {
180                                                 for(j=0,t=1<<26; t; t>>=1,j++) {
181                                                         if(a&t) {
182                                                                 if(!(a&(t<<1))) {
183                                                                         movto(YBASE + i, XBASE + 2*j);
184                                                                 }
185                                                                 addstr("  ");
186                                                         }
187                                                 }
188                                         }
189                                         if(!s) {
190                                                 old[i] = new[i];
191                                         }
192                                 }
193                                 if(!s) {
194                                         refresh();
195                                 }
196                         }
197                 }
198                 movto(6, 0);
199                 refresh();
200                 clock_gettime(CLOCK_REALTIME_FAST, &now);
201                 if (now.tv_sec == prev_sec) {
202                         if (delay.tv_nsec > 0) {
203                                 delay.tv_sec = 0;
204                                 delay.tv_nsec = 1000000000 - now.tv_nsec;
205                         } else {
206                                 delay.tv_sec = 1;
207                                 delay.tv_nsec = 0;
208                         }
209                         nanosleep(&delay, NULL);
210                         clock_gettime(CLOCK_REALTIME_FAST, &now);
211                 }
212                 n -= now.tv_sec - prev_sec;
213                 prev_sec = now.tv_sec;
214                 if (sigtermed) {
215                         standend();
216                         clear();
217                         refresh();
218                         endwin();
219                         errx(1, "terminated by signal %d", (int)sigtermed);
220                 }
221         } while (n);
222         standend();
223         clear();
224         refresh();
225         endwin();
226         return(0);
227 }
228
229 static void
230 set(int t, int n)
231 {
232         int i, m;
233
234         m = 7<<n;
235         for(i=0; i<5; i++) {
236                 next[i] |= ((disp[t]>>(4-i)*3)&07)<<n;
237                 mask |= (next[i]^old[i])&m;
238         }
239         if(mask&m)
240                 mask |= m;
241 }
242
243 static void
244 standt(int on)
245 {
246         if (on) {
247                 if(hascolor) {
248                         attron(COLOR_PAIR(1));
249                 } else {
250                         attron(A_STANDOUT);
251                 }
252         } else {
253                 if(hascolor) {
254                         attron(COLOR_PAIR(2));
255                 } else {
256                         attroff(A_STANDOUT);
257                 }
258         }
259 }
260
261 static void
262 movto(int line, int col)
263 {
264         move(line, col);
265 }
266
267 static void
268 usage(void)
269 {
270
271         (void)fprintf(stderr, "usage: grdc [-st] [n]\n");
272         exit(1);
273 }