2 * Grand digital clock for curses compatible terminals
3 * Usage: gdc [-s] [n] -- run for n seconds (default infinity)
6 * modified 10-18-89 for curses (jrl)
7 * 10-18-89 added signal handling
9 * $Id: gdc.c,v 1.23 2002/08/10 19:20:14 tom Exp $
14 #include <test.priv.h>
21 static short disp
[11] =
23 075557, 011111, 071747, 071717, 055711,
24 074717, 074757, 071111, 075757, 075717, 002020
26 static long older
[6], next
[6], newer
[6], mask
;
28 static int sigtermed
= 0;
29 static bool redirected
= FALSE
;
30 static bool hascolor
= FALSE
;
35 signal(signo
, sighndl
);
39 ExitProgram(EXIT_FAILURE
);
46 chtype bottom
[XLENGTH
+ 1];
50 attrset(COLOR_PAIR(3));
52 mvaddch(YBASE
- 1, XBASE
- 1, ACS_ULCORNER
);
53 hline(ACS_HLINE
, XLENGTH
);
54 mvaddch(YBASE
- 1, XBASE
+ XLENGTH
, ACS_URCORNER
);
56 mvaddch(YBASE
+ YDEPTH
, XBASE
- 1, ACS_LLCORNER
);
57 mvinchnstr(YBASE
+ YDEPTH
, XBASE
, bottom
, XLENGTH
);
58 for (n
= 0; n
< XLENGTH
; n
++)
59 bottom
[n
] = ACS_HLINE
| (bottom
[n
] & (A_ATTRIBUTES
| A_COLOR
));
60 mvaddchnstr(YBASE
+ YDEPTH
, XBASE
, bottom
, XLENGTH
);
61 mvaddch(YBASE
+ YDEPTH
, XBASE
+ XLENGTH
, ACS_LRCORNER
);
63 move(YBASE
, XBASE
- 1);
64 vline(ACS_VLINE
, YDEPTH
);
66 move(YBASE
, XBASE
+ XLENGTH
);
67 vline(ACS_VLINE
, YDEPTH
);
70 attrset(COLOR_PAIR(2));
78 attron(COLOR_PAIR(1));
84 attron(COLOR_PAIR(2));
97 for (i
= 0; i
< 5; i
++) {
98 next
[i
] |= ((disp
[t
] >> ((4 - i
) * 3)) & 07) << n
;
99 mask
|= (next
[i
] ^ older
[i
]) & m
;
108 static const char *msg
[] =
110 "Usage: gdc [options] [count]"
113 ," -n redirect input to /dev/null"
114 ," -s scroll each number into place, rather than flipping"
116 ,"If you specify a count, gdc runs for that number of seconds"
119 for (j
= 0; j
< SIZEOF(msg
); j
++)
120 fprintf(stderr
, "%s\n", msg
[j
]);
121 ExitProgram(EXIT_FAILURE
);
125 main(int argc
, char *argv
[])
136 setlocale(LC_ALL
, "");
138 signal(SIGINT
, sighndl
);
139 signal(SIGTERM
, sighndl
);
141 while ((k
= getopt(argc
, argv
, "sn")) != EOF
) {
147 ifp
= fopen("/dev/null", "r");
155 count
= atoi(argv
[optind
++]);
161 char *name
= getenv("TERM");
163 || newterm(name
, ofp
, ifp
) == 0) {
164 fprintf(stderr
, "cannot open terminal\n");
165 ExitProgram(EXIT_FAILURE
);
176 hascolor
= has_colors();
179 int bg
= COLOR_BLACK
;
181 #if HAVE_USE_DEFAULT_COLORS
182 if (use_default_colors() == OK
)
185 init_pair(1, COLOR_BLACK
, COLOR_RED
);
186 init_pair(2, COLOR_RED
, bg
);
187 init_pair(3, COLOR_WHITE
, bg
);
188 attrset(COLOR_PAIR(2));
192 for (j
= 0; j
< 5; j
++)
193 older
[j
] = newer
[j
] = next
[j
] = 0;
202 tm
= localtime(&now
);
205 set(tm
->tm_sec
% 10, 0);
206 set(tm
->tm_sec
/ 10, 4);
207 set(tm
->tm_min
% 10, 10);
208 set(tm
->tm_min
/ 10, 14);
209 set(tm
->tm_hour
% 10, 20);
210 set(tm
->tm_hour
/ 10, 24);
214 for (k
= 0; k
< 6; k
++) {
216 for (i
= 0; i
< 5; i
++)
217 newer
[i
] = (newer
[i
] & ~mask
) | (newer
[i
+ 1] & mask
);
218 newer
[5] = (newer
[5] & ~mask
) | (next
[k
] & mask
);
220 newer
[k
] = (newer
[k
] & ~mask
) | (next
[k
] & mask
);
222 for (s
= 1; s
>= 0; s
--) {
224 for (i
= 0; i
< 6; i
++) {
225 if ((a
= (newer
[i
] ^ older
[i
]) & (s
? newer
: older
)[i
])
227 for (j
= 0, t
= 1 << 26; t
; t
>>= 1, j
++) {
229 if (!(a
& (t
<< 1))) {
230 move(YBASE
+ i
, XBASE
+ 2 * j
);
245 * If we're scrolling, space out the refreshes to fake
246 * movement. That's 7 frames, or 6 intervals, which would
247 * be 166 msec if we spread it out over a second. It looks
248 * better (but will well on a slow terminal, e.g., less
249 * than 9600bd) to squeeze that into a half-second, and use
250 * half of 170 msec to ensure that the program doesn't eat
251 * a lot of time when asking what time it is, at the top of
260 /* this depends on the detailed format of ctime(3) */
261 (void) strcpy(buf
, ctime(&now
));
262 (void) strcpy(buf
+ 10, buf
+ 19);
263 mvaddstr(16, 30, buf
);
270 * If we're not scrolling, wait 1000 msec (1 sec). Use napms() rather
271 * than sleep() because the latter does odd things on some systems,
272 * e.g., suspending output as well.
280 * This is a safe way to check if we're interrupted - making the signal
281 * handler set a flag that we can check. Since we're running
282 * nodelay(), the wgetch() call returns immediately, and in particular
283 * will return an error if interrupted. This works only if we can
284 * read from the input, of course.
286 switch (wgetch(stdscr
)) {
291 nodelay(stdscr
, FALSE
);
294 nodelay(stdscr
, TRUE
);
305 fprintf(stderr
, "gdc terminated by signal %d\n", sigtermed
);
306 ExitProgram(EXIT_FAILURE
);
315 ExitProgram(EXIT_SUCCESS
);