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