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