1 /* $OpenBSD: grdc.c,v 1.15 2008/03/17 09:17:56 sobrado Exp $ */ 2 /* 3 * 4 * Copyright 2002 Amos Shapir. Public domain. 5 * 6 * Grand digital clock for curses compatible terminals 7 * Usage: grdc [-s] [n] -- run for n seconds (default infinity) 8 * Flags: -s: scroll 9 * 10 * modified 10-18-89 for curses (jrl) 11 * 10-18-89 added signal handling 12 */ 13 14 #include <sys/types.h> 15 #include <curses.h> 16 #include <limits.h> 17 #include <signal.h> 18 #include <stdlib.h> 19 #include <stdio.h> 20 #include <time.h> 21 #include <unistd.h> 22 23 #define YBASE 10 24 #define XBASE 10 25 #define XLENGTH 58 26 #define YDEPTH 7 27 28 struct timespec now; 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 char scrol; 37 38 volatile sig_atomic_t sigtermed = 0; 39 40 int hascolor = 0; 41 42 void set(int, int); 43 void standt(int); 44 void movto(int, int); 45 void usage(void); 46 47 void 48 sighndl(int signo) 49 { 50 sigtermed=signo; 51 } 52 53 int 54 main(int argc, char *argv[]) 55 { 56 long t, a; 57 int i, j, s, k; 58 int n = 0; 59 struct timeval nowtv; 60 struct timespec delay; 61 char *ep; 62 63 scrol = 0; 64 while ((i = getopt(argc, argv, "sh")) != -1) 65 switch (i) { 66 case 's': 67 scrol = 1; 68 break; 69 case 'h': 70 case '?': 71 default: 72 usage(); 73 } 74 argv += optind; 75 argc -= optind; 76 77 if (argc > 1) 78 usage(); 79 if (argc == 1) { 80 t = strtol(*argv, &ep, 10); 81 if ((*argv)[0] == '\0' || *ep != '\0') 82 usage(); 83 if (t < 1 || t >= INT_MAX) { 84 fprintf(stderr, "number of seconds is out of range"); 85 usage(); 86 } 87 n = t; 88 } 89 90 initscr(); 91 92 signal(SIGINT,sighndl); 93 signal(SIGTERM,sighndl); 94 signal(SIGHUP,sighndl); 95 96 cbreak(); 97 noecho(); 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 curs_set(0); 110 clear(); 111 refresh(); 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 gettimeofday(&nowtv, NULL); 132 TIMEVAL_TO_TIMESPEC(&nowtv, &now); 133 do { 134 mask = 0; 135 tm = localtime(&now.tv_sec); 136 set(tm->tm_sec%10, 0); 137 set(tm->tm_sec/10, 4); 138 set(tm->tm_min%10, 10); 139 set(tm->tm_min/10, 14); 140 set(tm->tm_hour%10, 20); 141 set(tm->tm_hour/10, 24); 142 set(10, 7); 143 set(10, 17); 144 for(k=0; k<6; k++) { 145 if(scrol) { 146 for(i=0; i<5; i++) 147 new[i] = (new[i]&~mask) | (new[i+1]&mask); 148 new[5] = (new[5]&~mask) | (next[k]&mask); 149 } else 150 new[k] = (new[k]&~mask) | (next[k]&mask); 151 next[k] = 0; 152 for(s=1; s>=0; s--) { 153 standt(s); 154 for(i=0; i<6; i++) { 155 if((a = (new[i]^old[i])&(s ? new : old)[i]) != 0) { 156 for(j=0,t=1<<26; t; t>>=1,j++) { 157 if(a&t) { 158 if(!(a&(t<<1))) { 159 movto(YBASE + i, XBASE + 2*j); 160 } 161 addstr(" "); 162 } 163 } 164 } 165 if(!s) { 166 old[i] = new[i]; 167 } 168 } 169 if(!s) { 170 refresh(); 171 } 172 } 173 } 174 movto(6, 0); 175 refresh(); 176 gettimeofday(&nowtv, NULL); 177 TIMEVAL_TO_TIMESPEC(&nowtv, &now); 178 delay.tv_sec = 0; 179 delay.tv_nsec = (1000000000 - now.tv_nsec); 180 nanosleep(&delay, NULL); 181 now.tv_sec++; 182 183 if (sigtermed) { 184 standend(); 185 clear(); 186 refresh(); 187 endwin(); 188 fprintf(stderr, "grdc terminated by signal %d\n", sigtermed); 189 exit(1); 190 } 191 } while(--n); 192 standend(); 193 clear(); 194 refresh(); 195 endwin(); 196 return(0); 197 } 198 199 void 200 set(int t, int n) 201 { 202 int i, m; 203 204 m = 7<<n; 205 for(i=0; i<5; i++) { 206 next[i] |= ((disp[t]>>(4-i)*3)&07)<<n; 207 mask |= (next[i]^old[i])&m; 208 } 209 if(mask&m) 210 mask |= m; 211 } 212 213 void 214 standt(int on) 215 { 216 if (on) { 217 if(hascolor) { 218 attron(COLOR_PAIR(1)); 219 } else { 220 attron(A_STANDOUT); 221 } 222 } else { 223 if(hascolor) { 224 attron(COLOR_PAIR(2)); 225 } else { 226 attroff(A_STANDOUT); 227 } 228 } 229 } 230 231 void 232 movto(int line, int col) 233 { 234 move(line, col); 235 } 236 237 void 238 usage(void) 239 { 240 (void)fprintf(stderr, "usage: grdc [-s] [number]\n"); 241 exit(1); 242 } 243