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