Commit | Line | Data |
---|---|---|
21c4e167 H |
1 | /* |
2 | * Compile with: | |
3 | * gcc -lm aclox.c -o aclox; ./aclox | |
4 | * or | |
5 | * CFLAGS='-lm' make aclox; ./aclox | |
6 | */ | |
7 | ||
8 | #include <stdio.h> | |
9 | #include <stdlib.h> | |
10 | #include <unistd.h> | |
11 | #include <math.h> | |
12 | #include <time.h> | |
13 | ||
14 | #include <termios.h> | |
15 | #include <sys/ioctl.h> | |
16 | ||
17 | //config | |
18 | #define HOUR_NUMBERS 1 | |
2637289c | 19 | #define HOUR_HEXADECIMAL 1 |
21c4e167 H |
20 | #define HI_PRECISION 1 |
21 | #define SHOW_DIGITS 1 | |
2637289c | 22 | #define DIGITS_HEXADECIMAL 1 |
21c4e167 H |
23 | #define MINUTE_DOTS 1 |
24 | #define SMOOTH_MOTION 1 | |
25 | #define zoom 2 | |
26 | ||
27 | //useful macros | |
28 | #define max(a,b) ((a)>=(b)?(a):(b)) | |
29 | #define min(a,b) ((a)<=(b)?(a):(b)) | |
30 | #define PI 3.141592654 | |
31 | #define deg2rad(a) (((a)/180)*PI) | |
32 | //phi = angle, r = length | |
33 | #define polar2x(phi, r) ((r) * cos(deg2rad(phi))) | |
34 | #define polar2y(phi, r) ((r) * sin(deg2rad(phi))) | |
35 | #define cls() printf("\033[2J") | |
36 | #define top() printf("\033[0;0H") | |
37 | ||
38 | int llines = -1, lcols = -1; | |
39 | void render_clock(double h, double m, double s) { | |
40 | //colors | |
41 | char color_empty = ' '; | |
42 | char color_center = '+'; | |
43 | char color_number = '#'; | |
44 | char color_dot = '.'; | |
45 | char color_h = 'H'; | |
46 | char color_m = 'm'; | |
47 | char color_s = '*'; | |
48 | ||
49 | //convert digital time to "analog" time (enables smooth motion) | |
50 | if(SMOOTH_MOTION) { | |
51 | m += s/(double)60; | |
52 | h += m/(double)60; | |
53 | } | |
54 | ||
55 | //get size of terminal | |
56 | int lines = 20; | |
57 | int cols = 20; | |
58 | /*FILE *p; | |
59 | p = popen("stty size", "r"); | |
60 | fscanf(p, "%d %d", &lines, &cols); | |
61 | close((int)p);*/ | |
62 | struct winsize ws; | |
63 | if ((ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) == -1 && | |
64 | ioctl(STDERR_FILENO, TIOCGWINSZ, &ws) == -1 && | |
65 | ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) == -1) || | |
66 | ws.ws_col == 0) { | |
67 | lines = 25; | |
68 | cols = 80; | |
69 | } else { | |
70 | lines = ws.ws_row; | |
71 | cols = ws.ws_col; | |
72 | } | |
73 | ||
74 | //calculate size | |
75 | int size = 40; | |
76 | size = min(lines,cols/zoom); | |
77 | size = ((size%2)==0?size-1:size); //make size odd | |
78 | //printf("%d\n", size); | |
79 | ||
80 | //empty canvas | |
81 | char cifernik[size*zoom][size]; | |
82 | int i, x, y; | |
83 | double phi, r; | |
84 | for(y=0;y<size;y++) for(x=0;x<(size*zoom);x++) cifernik[x][y] = color_empty; | |
85 | ||
86 | //draw minute dots | |
87 | if(MINUTE_DOTS && size > 40) for(i=1;i<=60;i++) { | |
88 | phi = -90+(i*(360/60)); | |
89 | r = size/2; | |
90 | x = round((r+polar2x(phi,r))*zoom); | |
91 | y = round(r+polar2y(phi,r)); | |
92 | cifernik[x][y] = color_dot; | |
93 | } | |
94 | ||
95 | //draw numbers | |
96 | for(i=1;i<=12;i++) { | |
97 | phi = -90+(i*(360/12)); | |
98 | r = size/2; | |
99 | x = round((r+polar2x(phi,r))*zoom); | |
100 | y = round(r+polar2y(phi,r)); | |
101 | if(HOUR_NUMBERS) { | |
102 | cifernik[x][y] = '0'+(i%10); | |
2637289c H |
103 | if(HOUR_HEXADECIMAL) { |
104 | sprintf(&cifernik[x][y],"%X",i); | |
105 | } else { | |
106 | if(i>9) cifernik[x-1][y] = '0'+(i/10); | |
107 | } | |
21c4e167 H |
108 | } else { |
109 | cifernik[x][y] = color_number; | |
110 | } | |
111 | } | |
112 | ||
113 | //draw minute hand | |
114 | phi = -90+(m*(360/60)); | |
115 | for(r=0;r<(size/2);r++) { | |
116 | x = round((size/2+polar2x(phi,r))*zoom); | |
117 | y = round(size/2+polar2y(phi,r)); | |
118 | cifernik[x][y] = color_m; | |
119 | } | |
120 | ||
121 | //draw hour hand | |
122 | phi = -90+(h*(double)(360/12)); | |
123 | for(r=0;r<(size/3);r++) { | |
124 | x = round((size/2+polar2x(phi,r))*zoom); | |
125 | y = round(size/2+polar2y(phi,r)); | |
126 | cifernik[x][y] = color_h; | |
127 | } | |
128 | ||
129 | //draw seconds hand | |
130 | phi = -90+(s*(360/60)); | |
131 | for(r=0;r<(size/2);r++) { | |
132 | x = round((size/2+polar2x(phi,r))*zoom); | |
133 | y = round(size/2+polar2y(phi,r)); | |
134 | cifernik[x][y] = color_s; | |
135 | } | |
136 | ||
137 | //draw center dot | |
138 | cifernik[(size/2)*zoom][size/2] = color_center; | |
139 | ||
140 | //cls when terminal size changes | |
141 | if(lines != llines || cols != lcols) { | |
142 | cls(); | |
143 | llines=lines; | |
144 | lcols=cols; | |
145 | } | |
146 | ||
147 | //print to terminal | |
148 | for(y=0;y<size;y++) { | |
149 | for(r=0;r<=((cols-(size*zoom))/2);r++) putchar(' '); | |
150 | for(x=0;x<((size*zoom)-(zoom-1));x++) { | |
151 | putchar(cifernik[x][y]); | |
152 | } | |
153 | if(y!=(size-1)) putchar('\n'); | |
154 | } | |
155 | } | |
156 | ||
157 | int main(void) { | |
158 | int s = -1; | |
159 | time_t cast; | |
160 | struct tm *cas; | |
161 | ||
162 | while(1) { | |
163 | cast = time(NULL); | |
164 | cas = localtime(&cast); | |
165 | ||
166 | if(cas->tm_sec != s){ | |
167 | s = cas->tm_sec; | |
168 | top(); | |
169 | render_clock(cas->tm_hour,cas->tm_min,cas->tm_sec); //analog | |
2637289c H |
170 | if(SHOW_DIGITS || DIGITS_HEXADECIMAL) putchar('\r'); |
171 | if(SHOW_DIGITS) printf("DEC:[%.2d:%.2d:%.2d]",cas->tm_hour,cas->tm_min,cas->tm_sec); //digital | |
172 | if(SHOW_DIGITS || DIGITS_HEXADECIMAL) putchar(' '); | |
173 | if(DIGITS_HEXADECIMAL) printf("HEX:[%.2x:%.2x:%.2x]",cas->tm_hour,cas->tm_min,cas->tm_sec); //digital hexadec | |
21c4e167 H |
174 | } |
175 | if(HI_PRECISION) { usleep(100000); } | |
176 | else { sleep(1); } | |
177 | } | |
178 | } |