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