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