xref: /dragonfly/games/grdc/grdc.c (revision 1de703da)
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 }
236