• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* $Id: tclock.c,v 1.48 2023/02/25 16:42:22 tom Exp $ */
2 
3 #define NEED_TIME_H
4 #include <test.priv.h>
5 
6 #if HAVE_MATH_H && HAVE_MATH_FUNCS
7 
8 #include <math.h>
9 
10 /*
11   tclock - analog/digital clock for curses.
12   If it gives you joy, then
13   (a) I'm glad
14   (b) you need to get out more :-)
15 
16   This program is copyright Howard Jones, September 1994
17   (ha.jones@ic.ac.uk). It may be freely distributed as
18   long as this copyright message remains intact, and any
19   modifications are clearly marked as such. [In fact, if
20   you modify it, I wouldn't mind the modifications back,
21   especially if they add any nice features. A good one
22   would be a precalc table for the 60 hand positions, so
23   that the floating point stuff can be ditched. As I said,
24   it was a 20 hackup minute job.]
25 
26   COMING SOON: tfishtank. Be the envy of your mac-owning
27   colleagues.
28 */
29 
30 /* To compile: cc -o tclock tclock.c -lcurses -lm */
31 
32 #ifndef PI
33 #define PI 3.141592654
34 #endif
35 
36 #define sign(_x) (_x<0?-1:1)
37 
38 #define ASPECT 2.2
39 #define ROUND(value) ((int)((value) + 0.5))
40 
41 #define A2X(angle,radius) ROUND(ASPECT * radius * sin(angle))
42 #define A2Y(angle,radius) ROUND(radius * cos(angle))
43 
44 /* Plot a point */
45 static void
plot(int x,int y,int col)46 plot(int x, int y, int col)
47 {
48     MvAddCh(y, x, (chtype) col);
49 }
50 
51 /* Draw a diagonal(arbitrary) line using Bresenham's algorithm. */
52 static void
dline(int pair,int from_x,int from_y,int x2,int y2,int ch)53 dline(int pair, int from_x, int from_y, int x2, int y2, int ch)
54 {
55     int dx, dy;
56     int ax, ay;
57     int sx, sy;
58     int x, y;
59     int d;
60 
61     if (has_colors())
62 	(void) attrset(AttrArg(COLOR_PAIR(pair), 0));
63 
64     dx = x2 - from_x;
65     dy = y2 - from_y;
66 
67     ax = abs(dx * 2);
68     ay = abs(dy * 2);
69 
70     sx = sign(dx);
71     sy = sign(dy);
72 
73     x = from_x;
74     y = from_y;
75 
76     if (ax > ay) {
77 	d = ay - (ax / 2);
78 
79 	while (1) {
80 	    plot(x, y, ch);
81 	    if (x == x2)
82 		return;
83 
84 	    if (d >= 0) {
85 		y += sy;
86 		d -= ax;
87 	    }
88 	    x += sx;
89 	    d += ay;
90 	}
91     } else {
92 	d = ax - (ay / 2);
93 
94 	while (1) {
95 	    plot(x, y, ch);
96 	    if (y == y2)
97 		return;
98 
99 	    if (d >= 0) {
100 		x += sx;
101 		d -= ay;
102 	    }
103 	    y += sy;
104 	    d += ax;
105 	}
106     }
107 }
108 
109 static void
usage(int ok)110 usage(int ok)
111 {
112     static const char *msg[] =
113     {
114 	"Usage: tclock [options]"
115 	,""
116 	,USAGE_COMMON
117 	,"Options:"
118 #if HAVE_USE_DEFAULT_COLORS
119 	," -d       invoke use_default_colors"
120 #endif
121     };
122     size_t n;
123 
124     for (n = 0; n < SIZEOF(msg); n++)
125 	fprintf(stderr, "%s\n", msg[n]);
126 
127     ExitProgram(ok ? EXIT_SUCCESS : EXIT_FAILURE);
128 }
129 /* *INDENT-OFF* */
VERSION_COMMON()130 VERSION_COMMON()
131 /* *INDENT-ON* */
132 
133 int
134 main(int argc, char *argv[])
135 {
136     static TimeType initial;
137 
138     int i, cx, cy;
139     double cr, mradius, hradius, mangle, hangle;
140     double sangle, sradius, hours;
141     int hdx, hdy;
142     int mdx, mdy;
143     int sdx, sdy;
144     int ch;
145     int lastbeep = -1;
146     bool odd = FALSE;
147     time_t tim;
148     struct tm *t;
149     char szChar[20];
150     char *text;
151     short my_bg = COLOR_BLACK;
152     TimeType current;
153 #if HAVE_USE_DEFAULT_COLORS
154     bool d_option = FALSE;
155 #endif
156 
157     while ((ch = getopt(argc, argv, OPTS_COMMON "d")) != -1) {
158 	switch (ch) {
159 #if HAVE_USE_DEFAULT_COLORS
160 	case 'd':
161 	    d_option = TRUE;
162 	    break;
163 #endif
164 	case OPTS_VERSION:
165 	    show_version(argv);
166 	    ExitProgram(EXIT_SUCCESS);
167 	default:
168 	    usage(ch == OPTS_USAGE);
169 	    /* NOTREACHED */
170 	}
171     }
172     if (optind < argc)
173 	usage(FALSE);
174 
175     setlocale(LC_ALL, "");
176 
177     initscr();
178     noecho();
179     cbreak();
180     nodelay(stdscr, TRUE);
181     curs_set(0);
182 
183     if (has_colors()) {
184 	start_color();
185 #if HAVE_USE_DEFAULT_COLORS
186 	if (d_option && (use_default_colors() == OK))
187 	    my_bg = -1;
188 #endif
189 	init_pair(1, COLOR_RED, my_bg);
190 	init_pair(2, COLOR_MAGENTA, my_bg);
191 	init_pair(3, COLOR_GREEN, my_bg);
192 	init_pair(4, COLOR_WHITE, COLOR_BLUE);
193     }
194 #ifdef KEY_RESIZE
195     keypad(stdscr, TRUE);
196   restart:
197 #endif
198     cx = (COLS - 1) / 2;	/* 39 */
199     cy = LINES / 2;		/* 12 */
200     if (cx / ASPECT < cy)
201 	cr = cx / ASPECT;
202     else
203 	cr = cy;
204     sradius = (5 * cr) / 6;	/* 10 */
205     mradius = (3 * cr) / 4;	/* 9 */
206     hradius = cr / 2;		/* 6 */
207 
208     for (i = 0; i < 12; i++) {
209 	sangle = (i + 1) * (2.0 * PI) / 12.0;
210 	sdx = A2X(sangle, sradius);
211 	sdy = A2Y(sangle, sradius);
212 	_nc_SPRINTF(szChar, _nc_SLIMIT(sizeof(szChar)) "%d", i + 1);
213 
214 	MvAddStr(cy - sdy, cx + sdx, szChar);
215     }
216 
217     MvAddStr(0, 0, "ASCII Clock by Howard Jones (ha.jones@ic.ac.uk),1994");
218 
219     sradius = (4 * sradius) / 5;
220     for (;;) {
221 	napms(100);
222 
223 	tim = time(0);
224 	t = localtime(&tim);
225 
226 	hours = (t->tm_hour + (t->tm_min / 60.0));
227 	if (hours > 12.0)
228 	    hours -= 12.0;
229 
230 	mangle = ((t->tm_min + (t->tm_sec / 60.0)) * (2 * PI) / 60.0);
231 	mdx = A2X(mangle, mradius);
232 	mdy = A2Y(mangle, mradius);
233 
234 	hangle = ((hours) * (2.0 * PI) / 12.0);
235 	hdx = A2X(hangle, hradius);
236 	hdy = A2Y(hangle, hradius);
237 
238 	GetClockTime(&current);
239 
240 	sangle = (ElapsedSeconds(&initial, &current) * (2.0 * PI) / 60.0);
241 	sdx = A2X(sangle, sradius);
242 	sdy = A2Y(sangle, sradius);
243 
244 	dline(3, cx, cy, cx + mdx, cy - mdy, '#');
245 
246 	(void) attrset(A_REVERSE);
247 	dline(2, cx, cy, cx + hdx, cy - hdy, '.');
248 	attroff(A_REVERSE);
249 
250 	if (has_colors())
251 	    (void) attrset(AttrArg(COLOR_PAIR(1), 0));
252 
253 	dline(1, cx, cy, cx + sdx, cy - sdy, 'O');
254 
255 	if (has_colors())
256 	    (void) attrset(AttrArg(COLOR_PAIR(0), 0));
257 
258 	text = ctime(&tim);
259 	MvPrintw(2, 0, "%.*s", (int) (strlen(text) - 1), text);
260 	refresh();
261 	if ((t->tm_sec % 5) == 0
262 	    && t->tm_sec != lastbeep) {
263 	    lastbeep = t->tm_sec;
264 	    if (has_colors()) {
265 		odd = !odd;
266 		bkgd((chtype) (odd ? COLOR_PAIR(4) : COLOR_PAIR(0)));
267 	    }
268 	    beep();
269 	}
270 
271 	if ((ch = getch()) != ERR) {
272 #ifdef KEY_RESIZE
273 	    if (ch == KEY_RESIZE) {
274 		flash();
275 		erase();
276 		wrefresh(curscr);
277 		goto restart;
278 	    }
279 #endif
280 	    break;
281 	}
282 
283 	dline(0, cx, cy, cx + hdx, cy - hdy, ' ');
284 	dline(0, cx, cy, cx + mdx, cy - mdy, ' ');
285 	dline(0, cx, cy, cx + sdx, cy - sdy, ' ');
286 
287     }
288 
289     stop_curses();
290     ExitProgram(EXIT_SUCCESS);
291 }
292 #else
293 int
main(void)294 main(void)
295 {
296     printf("This program requires the header math.h and trignometric functions\n");
297     ExitProgram(EXIT_FAILURE);
298 }
299 #endif
300