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