]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.bin/grdc/grdc.c
Remove MOVED_LIBS handling from list-old-libs
[FreeBSD/FreeBSD.git] / usr.bin / grdc / grdc.c
1 /*
2  * Grand digital clock for curses compatible terminals
3  * Usage: grdc [-st] [n]   -- run for n seconds (default infinity)
4  * Flags: -s: scroll
5  *        -t: output time in 12-hour format
6  *
7  *
8  * modified 10-18-89 for curses (jrl)
9  * 10-18-89 added signal handling
10  *
11  * modified 03-25-03 for 12 hour option
12  *     - Samy Al Bahra <samy@kerneled.com>
13  */
14
15 #include <err.h>
16 #include <ncurses.h>
17 #include <signal.h>
18 #include <stdlib.h>
19 #include <time.h>
20 #include <unistd.h>
21
22 #define YBASE   10
23 #define XBASE   10
24 #define XLENGTH 58
25 #define YDEPTH  7
26
27 static struct timespec now;
28 static struct tm *tm;
29
30 static short disp[11] = {
31         075557, 011111, 071747, 071717, 055711,
32         074717, 074757, 071111, 075757, 075717, 002020
33 };
34 static long old[6], next[6], new[6], mask;
35
36 static volatile sig_atomic_t sigtermed;
37
38 static int hascolor = 0;
39
40 static void set(int, int);
41 static void standt(int);
42 static void movto(int, int);
43 static void sighndl(int);
44 static void usage(void) __dead2;
45
46 static void
47 sighndl(int signo)
48 {
49
50         sigtermed = signo;
51 }
52
53 int
54 main(int argc, char *argv[])
55 {
56         struct timespec delay;
57         time_t prev_sec;
58         long t, a;
59         int i, j, s, k;
60         int n;
61         int ch;
62         int scrol;
63         int t12;
64
65         t12 = scrol = 0;
66
67         while ((ch = getopt(argc, argv, "ts")) != -1)
68         switch (ch) {
69         case 's':
70                 scrol = 1;
71                 break;
72         case 't':
73                 t12 = 1;
74                 break;
75         case '?':
76         default:
77                 usage();
78                 /* NOTREACHED */
79         }
80         argc -= optind;
81         argv += optind;
82
83         if (argc > 1) {
84                 usage();
85                 /* NOTREACHED */
86         }
87
88         if (argc > 0) {
89                 n = atoi(*argv) + 1;
90                 if (n < 1) {
91                         warnx("number of seconds is out of range");
92                         usage();
93                         /* NOTREACHED */
94                 }
95         } else
96                 n = 0;
97
98         initscr();
99
100         signal(SIGINT,sighndl);
101         signal(SIGTERM,sighndl);
102         signal(SIGHUP,sighndl);
103
104         cbreak();
105         noecho();
106         curs_set(0);
107
108         hascolor = has_colors();
109
110         if(hascolor) {
111                 start_color();
112                 init_pair(1, COLOR_BLACK, COLOR_RED);
113                 init_pair(2, COLOR_RED, COLOR_BLACK);
114                 init_pair(3, COLOR_WHITE, COLOR_BLACK);
115                 attrset(COLOR_PAIR(2));
116         }
117
118         clear();
119         refresh();
120
121         if(hascolor) {
122                 attrset(COLOR_PAIR(3));
123
124                 mvaddch(YBASE - 2,  XBASE - 3, ACS_ULCORNER);
125                 hline(ACS_HLINE, XLENGTH);
126                 mvaddch(YBASE - 2,  XBASE - 2 + XLENGTH, ACS_URCORNER);
127
128                 mvaddch(YBASE + YDEPTH - 1,  XBASE - 3, ACS_LLCORNER);
129                 hline(ACS_HLINE, XLENGTH);
130                 mvaddch(YBASE + YDEPTH - 1,  XBASE - 2 + XLENGTH, ACS_LRCORNER);
131
132                 move(YBASE - 1,  XBASE - 3);
133                 vline(ACS_VLINE, YDEPTH);
134
135                 move(YBASE - 1,  XBASE - 2 + XLENGTH);
136                 vline(ACS_VLINE, YDEPTH);
137
138                 attrset(COLOR_PAIR(2));
139         }
140         clock_gettime(CLOCK_REALTIME_FAST, &now);
141         prev_sec = now.tv_sec;
142         do {
143                 mask = 0;
144                 tm = localtime(&now.tv_sec);
145                 set(tm->tm_sec%10, 0);
146                 set(tm->tm_sec/10, 4);
147                 set(tm->tm_min%10, 10);
148                 set(tm->tm_min/10, 14);
149
150                 if (t12) {
151                         if (tm->tm_hour < 12) {
152                                 if (tm->tm_hour == 0)
153                                         tm->tm_hour = 12;
154                                 mvaddstr(YBASE + 5, XBASE + 52, "AM");
155                         } else {
156                                 if (tm->tm_hour > 12)
157                                         tm->tm_hour -= 12;
158                                 mvaddstr(YBASE + 5, XBASE + 52, "PM");
159                         }
160                 }
161
162                 set(tm->tm_hour%10, 20);
163                 set(tm->tm_hour/10, 24);
164                 set(10, 7);
165                 set(10, 17);
166                 for(k=0; k<6; k++) {
167                         if(scrol) {
168                                 for(i=0; i<5; i++)
169                                         new[i] = (new[i]&~mask) | (new[i+1]&mask);
170                                 new[5] = (new[5]&~mask) | (next[k]&mask);
171                         } else
172                                 new[k] = (new[k]&~mask) | (next[k]&mask);
173                         next[k] = 0;
174                         for(s=1; s>=0; s--) {
175                                 standt(s);
176                                 for(i=0; i<6; i++) {
177                                         if((a = (new[i]^old[i])&(s ? new : old)[i]) != 0) {
178                                                 for(j=0,t=1<<26; t; t>>=1,j++) {
179                                                         if(a&t) {
180                                                                 if(!(a&(t<<1))) {
181                                                                         movto(YBASE + i, XBASE + 2*j);
182                                                                 }
183                                                                 addstr("  ");
184                                                         }
185                                                 }
186                                         }
187                                         if(!s) {
188                                                 old[i] = new[i];
189                                         }
190                                 }
191                                 if(!s) {
192                                         refresh();
193                                 }
194                         }
195                 }
196                 movto(6, 0);
197                 refresh();
198                 clock_gettime(CLOCK_REALTIME_FAST, &now);
199                 if (now.tv_sec == prev_sec) {
200                         if (delay.tv_nsec > 0) {
201                                 delay.tv_sec = 0;
202                                 delay.tv_nsec = 1000000000 - now.tv_nsec;
203                         } else {
204                                 delay.tv_sec = 1;
205                                 delay.tv_nsec = 0;
206                         }
207                         nanosleep(&delay, NULL);
208                         clock_gettime(CLOCK_REALTIME_FAST, &now);
209                 }
210                 n -= now.tv_sec - prev_sec;
211                 prev_sec = now.tv_sec;
212                 if (sigtermed) {
213                         standend();
214                         clear();
215                         refresh();
216                         endwin();
217                         errx(1, "terminated by signal %d", (int)sigtermed);
218                 }
219         } while (n);
220         standend();
221         clear();
222         refresh();
223         endwin();
224         return(0);
225 }
226
227 static void
228 set(int t, int n)
229 {
230         int i, m;
231
232         m = 7<<n;
233         for(i=0; i<5; i++) {
234                 next[i] |= ((disp[t]>>(4-i)*3)&07)<<n;
235                 mask |= (next[i]^old[i])&m;
236         }
237         if(mask&m)
238                 mask |= m;
239 }
240
241 static void
242 standt(int on)
243 {
244         if (on) {
245                 if(hascolor) {
246                         attron(COLOR_PAIR(1));
247                 } else {
248                         attron(A_STANDOUT);
249                 }
250         } else {
251                 if(hascolor) {
252                         attron(COLOR_PAIR(2));
253                 } else {
254                         attroff(A_STANDOUT);
255                 }
256         }
257 }
258
259 static void
260 movto(int line, int col)
261 {
262         move(line, col);
263 }
264
265 static void
266 usage(void)
267 {
268
269         (void)fprintf(stderr, "usage: grdc [-st] [n]\n");
270         exit(1);
271 }