1 /*
2  * File: abclib.c
3  * Part of the ABClock package
4  * (c) Peter Kleiweg
5  *
6  * 2000/08/15: version 1.0
7  * 2000/08/06: version 0.9
8  * 2000/08/04: version 0.1
9  *
10  * This is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as
12  * published by the Free Software Foundation; either version 2,
13  * or (at your option) any later version.
14  *
15  */
16 
17 #include <math.h>
18 #include <stdio.h>
19 #include <stdlib.h>
20 
21 #include "abclib.h"
22 
23 int
24     ABC_size,
25     ABC_xsize = 0,
26     ABC_ysize = 0,
27     ABC_hsize,
28     ABC_msize,
29     ABC_mwidth,
30     ABC_mskip,
31     ABC_hpart,
32     ABC_mpart,
33     ABC_border,
34     ABC_bborder,
35     ABC_edge,
36     ABC_a1,
37     ABC_a2,
38     ABC_a3,
39     ABC_z1,
40     ABC_z2,
41     ABC_z3,
42     ABC_m1,
43     ABC_m2,
44     ABC_m3,
45     ABC_block_x,
46     ABC_block_y;
47 
48 void
49     ABC_sizes (int width, int height, int border),
50     ABC_top    (int x, float f),
51     ABC_bottom (int x, float f),
52     ABC_left   (int y, float f),
53     ABC_right  (int y, float f);
54 
55 #define ABC_RECT(x1, y1, x2, y2) (ABC_Rect \
56             (ABC_block_x + x1, ABC_block_y + y1, \
57              ABC_block_x + x2, ABC_block_y + y2))
58 
ABC_sizes(int width,int height,int border)59 void ABC_sizes (int width, int height, int border)
60 {
61     int
62 	tsize;
63 
64     if (width < ABC_MINSIZE || height < ABC_MINSIZE) {
65 	fputs ("ABClib: too small\n", stderr);
66 	exit (1);
67     }
68 
69     if (border > 0 &&
70         (width - 2 * border < ABC_MINSIZE ||
71          height - 2 * border < ABC_MINSIZE)
72     ) {
73 	fputs ("ABClib: border too large for size\n", stderr);
74 	exit (1);
75     }
76 
77     if (width == ABC_xsize &&
78         height == ABC_ysize &&
79         (border == ABC_border || (border < 0 && ABC_border < 0))
80     )
81         return;
82 
83     ABC_xsize = width;
84     ABC_ysize = height;
85     ABC_border = border;
86 
87     ABC_size = (ABC_xsize < ABC_ysize) ? ABC_xsize : ABC_ysize;
88     if (ABC_border < 0) {
89         ABC_bborder = ABC_size / 60;
90         if (ABC_bborder == 0 && ABC_size > ABC_MINSIZE + 1)
91             ABC_bborder = 1;
92     } else
93 	ABC_bborder = ABC_border;
94 
95     tsize = ABC_size - 2 * ABC_bborder;
96     ABC_edge = (tsize + 20) / 30;
97     ABC_mpart = 5 * ((tsize + 9) / 15);
98     ABC_mskip = (ABC_mpart + 5) / 15;
99     ABC_mwidth = ABC_mpart / 5 - ABC_mskip;
100     tsize = ABC_size - 2 * ABC_bborder - ABC_mpart;
101     ABC_hsize = (tsize - 2 * ABC_edge) / 3;
102     ABC_hpart = 3 * ABC_hsize + 2 * ABC_edge;
103     tsize = ABC_hpart + ABC_mpart;
104     ABC_msize = (ABC_hpart - 2 * (ABC_hpart / 5)) / 3;
105     if ((ABC_msize % 2) != (ABC_hpart % 2))
106 	ABC_msize--;
107     while (ABC_msize < (ABC_hpart - 3 * ABC_msize) / 2)
108 	ABC_msize += 2;
109 
110     ABC_a1 = ABC_edge;
111     ABC_z1 = ABC_edge + ABC_hsize - 1;
112     ABC_a2 = ABC_edge + ABC_hsize;
113     ABC_z2 = ABC_edge + 2 * ABC_hsize - 1;
114     ABC_a3 = ABC_edge + 2 * ABC_hsize;
115     ABC_z3 = ABC_edge + 3 * ABC_hsize - 1;
116 
117     ABC_m1 = 0;
118     ABC_m2 = (ABC_hpart - ABC_msize) / 2;
119     ABC_m3 = ABC_hpart - ABC_msize;
120 }
121 
122 /*
123  * put minutes f at (x, top)
124  */
ABC_top(int x,float f)125 void ABC_top (int x, float f)
126 {
127     int
128 	i,
129 	m1,
130 	m,
131 	y;
132 
133     f = fabs (f);
134     f = 5.0 - f;
135     y = 2 * ABC_edge + 3 * ABC_hsize + ABC_mskip;
136     for (i = 0; i < 5; i++) {
137 	if ((m = (int) (ABC_msize * f + .5)) > ABC_msize)
138 	    m = ABC_msize;
139 	if (m < 1)
140 	    return;
141 	m1 = (ABC_msize - m) / 2;
142 	ABC_RECT (x + m1, y, x + m1 + m - 1, y + ABC_mwidth - 1);
143 	f -= 1.0;
144 	y += (ABC_mskip + ABC_mwidth);
145     }
146 }
147 
148 /*
149  * put minutes f at (x, bottom)
150  */
ABC_bottom(int x,float f)151 void ABC_bottom (int x, float f)
152 {
153     int
154 	i,
155 	m,
156 	m1,
157 	y;
158 
159     f = fabs (f);
160     f = 5.0 - f;
161     y = - ABC_mskip - ABC_mwidth;
162     for (i = 0; i < 5; i++) {
163 	if ((m = (int) (ABC_msize * f + .5)) > ABC_msize)
164 	    m = ABC_msize;
165 	if (m < 1)
166 	    return;
167 	m1 = (ABC_msize - m) / 2;
168 	ABC_RECT (x + m1, y, x + m1 + m - 1, y + ABC_mwidth - 1);
169 	f -= 1.0;
170 	y -= (ABC_mskip + ABC_mwidth);
171     }
172 }
173 
174 /*
175  * put minutes at (right, y)
176  */
ABC_right(int y,float f)177 void ABC_right (int y, float f)
178 {
179     int
180 	i,
181 	m,
182 	m1,
183 	x;
184 
185     f = fabs (f);
186     f = 5.0 - f;
187     x = 2 * ABC_edge + 3 * ABC_hsize + ABC_mskip;
188     for (i = 0; i < 5; i++) {
189 	if ((m = (int) (ABC_msize * f + .5)) > ABC_msize)
190 	    m = ABC_msize;
191 	if (m < 1)
192 	    return;
193 	m1 = (ABC_msize - m) / 2;
194 	ABC_RECT (x, y + m1, x + ABC_mwidth - 1, y + m1 + m - 1);
195 	f -= 1.0;
196 	x += (ABC_mskip + ABC_mwidth);
197     }
198 }
199 
200 /*
201  * put minutes at (left, y)
202  */
ABC_left(int y,float f)203 void ABC_left (int y, float f)
204 {
205     int
206 	i,
207 	m,
208 	m1,
209 	x;
210 
211     f = fabs (f);
212     f = 5.0 - f;
213     x = - ABC_mskip - ABC_mwidth;
214     for (i = 0; i < 5; i++) {
215 	if ((m = (int) (ABC_msize * f + .5)) > ABC_msize)
216 	    m = ABC_msize;
217 	if (m < 1)
218 	    return;
219 	m1 = (ABC_msize - m) / 2;
220 	ABC_RECT (x, y + m1, x + ABC_mwidth - 1, y + m1 + m - 1);
221 	f -= 1.0;
222 	x -= (ABC_mskip + ABC_mwidth);
223     }
224 }
225 
ABC_Make(int hour,int min,int sec,int width,int height,int border)226 void ABC_Make (int hour, int min, int sec, int width, int height, int border)
227 {
228     float
229 	f,
230 	x,
231         y,
232 	xm,
233 	ym;
234     int
235 	i;
236 
237     ABC_sizes (width, height, border);
238 
239     if ((hour %= 12) < 0)
240 	hour += 12;
241     if ((min %= 60) < 0)
242 	min += 60;
243     if ((sec %= 60) < 0)
244 	sec += 60;
245 
246     /* set color to background */
247     ABC_SetColor (0);
248 
249     /* clear image */
250     ABC_block_x = ABC_block_y = 0;
251     ABC_RECT (0, 0, ABC_xsize - 1, ABC_ysize - 1);
252 
253     /* determine where to put the square, to leave room for minutes */
254 
255     if ((xm = ABC_hpart + 2 * ABC_mpart + 2 * ABC_bborder - ABC_xsize) < 0)
256         xm = 0;
257     if ((ym = ABC_hpart + 2 * ABC_mpart + 2 * ABC_bborder - ABC_ysize) < 0)
258 	ym = 0;
259 
260     if (min < 5 || min >= 55) {
261         if ((f = min) > 5)
262 	    f -= 60.0;
263 	f += ((float) sec) / 60.0;
264 	x = - f / 5.0 * xm;
265     } else if (min < 25)
266 	x = -xm;
267     else if (min < 35) {
268 	f = ((float) sec) / 60.0 + (float) min;
269 	x = (f - 30.0) / 5.0 * xm;
270     } else
271 	x = xm;
272 
273     if (min < 10 || min >= 50)
274 	y = -ym;
275     else if (min < 20) {
276 	f = ((float) sec) / 60.0 + (float) min;
277 	y = (f - 15.0) / 5.0 * ym;
278     } else if (min < 40)
279 	y = ym;
280     else {
281 	f = ((float) sec) / 60.0 + (float) min;
282 	y = (45.0 - f) / 5.0 * ym;
283     }
284 
285     ABC_block_x = (x + ((float) (ABC_xsize - ABC_hpart))) / 2.0 + .5;
286     ABC_block_y = (y + ((float) (ABC_ysize - ABC_hpart))) / 2.0 + .5;
287 
288     /* set color to square border */
289     ABC_SetColor (2);
290 
291     /* paint square border */
292     ABC_RECT (0,
293 	      0,
294 	      2 * ABC_edge + 3 * ABC_hsize - 1,
295 	      2 * ABC_edge + 3 * ABC_hsize - 1);
296 
297     /* set color to inside square */
298     ABC_SetColor (1);
299 
300     /* paint inside square */
301     ABC_RECT (ABC_edge,
302 	      ABC_edge,
303               ABC_edge + 3 * ABC_hsize - 1,
304 	      ABC_edge + 3 * ABC_hsize - 1);
305 
306     /* set color to hours */
307     ABC_SetColor (3);
308 
309     /* paint hours */
310     f = ((float) hour) + ((float) min) / 60.0 + ((float) sec) / 3600.0;
311     switch (hour) {
312 	case 0:
313 	    i = (int) (f * ((float) ABC_hsize) + .5);
314 	    ABC_RECT (ABC_a2, ABC_a2 + i, ABC_z2, ABC_z3);
315 	    ABC_RECT (ABC_a3, ABC_a3, ABC_z2 + i, ABC_z3);
316 	    break;
317 	case 1:
318 	    i = (int) ((f - 1.0) * ((float) ABC_hsize) + .5);
319 	    ABC_RECT (ABC_a2 + i, ABC_a3, ABC_z3, ABC_z3);
320 	    ABC_RECT (ABC_a3, ABC_a3 - i, ABC_z3, ABC_z2);
321 	    break;
322 	case 2:
323 	    i = (int) ((f - 2.0) * ((float) ABC_hsize) + .5);
324 	    ABC_RECT (ABC_a3, ABC_a2, ABC_z3, ABC_z3 - i);
325 	    ABC_RECT (ABC_a3 - i, ABC_a2, ABC_z2, ABC_z2);
326 	    break;
327 	case 3:
328 	    i = (int) ((f - 3.0) * ((float) ABC_hsize) + .5);
329 	    ABC_RECT (ABC_a2 + i, ABC_a2, ABC_z3, ABC_z2);
330 	    ABC_RECT (ABC_a3, ABC_a2 - i, ABC_z3, ABC_z2);
331 	    break;
332 	case 4:
333 	    i = (int) ((f - 4.0) * ((float) ABC_hsize) + .5);
334 	    ABC_RECT (ABC_a3, ABC_a1, ABC_z3, ABC_z2 - i);
335 	    ABC_RECT (ABC_a3 - i, ABC_a1, ABC_z2, ABC_z1);
336 	    break;
337 	case 5:
338 	    i = (int) ((f - 5.0) * ((float) ABC_hsize) + .5);
339 	    ABC_RECT (ABC_a2, ABC_a1, ABC_z3 - i, ABC_z1);
340 	    ABC_RECT (ABC_a2, ABC_a2, ABC_z2, ABC_z1 + i);
341 	    break;
342 	case 6:
343 	    i = (int) ((f - 6.0) * ((float) ABC_hsize) + .5);
344 	    ABC_RECT (ABC_a2, ABC_a1, ABC_z2, ABC_z2 - i);
345 	    ABC_RECT (ABC_a2 - i, ABC_a1, ABC_z1, ABC_z1);
346 	    break;
347 	case 7:
348 	    i = (int) ((f - 7.0) * ((float) ABC_hsize) + .5);
349 	    ABC_RECT (ABC_a1, ABC_a1, ABC_z2 - i, ABC_z1);
350 	    ABC_RECT (ABC_a1, ABC_a2, ABC_z1, ABC_z1 + i);
351 	    break;
352 	case 8:
353 	    i = (int) ((f - 8.0) * ((float) ABC_hsize) + .5);
354 	    ABC_RECT (ABC_a1, ABC_a1 + i, ABC_z1, ABC_z2);
355 	    ABC_RECT (ABC_a2, ABC_a2, ABC_z1 + i, ABC_z2);
356 	    break;
357 	case 9:
358 	    i = (int) ((f - 9.0) * ((float) ABC_hsize) + .5);
359 	    ABC_RECT (ABC_a1, ABC_a2, ABC_z2 - i, ABC_z2);
360 	    ABC_RECT (ABC_a1, ABC_a3, ABC_z1, ABC_z2 + i);
361 	    break;
362 	case 10:
363 	    i = (int) ((f - 10.0) * ((float) ABC_hsize) + .5);
364 	    ABC_RECT (ABC_a1, ABC_a2 + i, ABC_z1, ABC_z3);
365 	    ABC_RECT (ABC_a2, ABC_a3, ABC_z1 + i, ABC_z3);
366 	    break;
367 	case 11:
368 	    i = (int) ((f - 11.0) * ((float) ABC_hsize) + .5);
369 	    ABC_RECT (ABC_a1 + i, ABC_a3, ABC_z2, ABC_z3);
370 	    ABC_RECT (ABC_a2, ABC_a3 - i, ABC_z2, ABC_z3);
371 	    break;
372     }
373 
374     /* set color to minutes */
375     ABC_SetColor (4);
376 
377     /* paint minutes */
378     f = ((float) min) + ((float) sec) / 60.0;
379     if (min >= 55 || min < 5)
380 	ABC_top (ABC_m2, (min < 5) ? f : (f - 60.0));
381     if (min < 10)
382         ABC_top (ABC_m3, f - 5.0);
383     if (min >= 5 && min < 15)
384 	ABC_right (ABC_m3, f - 10.0);
385     if (min >= 10 && min < 20)
386 	ABC_right (ABC_m2, f - 15.0);
387     if (min >= 15 && min < 25)
388 	ABC_right (ABC_m1, f - 20.0);
389     if (min >= 20 && min < 30)
390 	ABC_bottom (ABC_m3, f - 25.0);
391     if (min >= 25 && min < 35)
392 	ABC_bottom (ABC_m2, f - 30.0);
393     if (min >= 30 && min < 40)
394 	ABC_bottom (ABC_m1, f - 35.0);
395     if (min >= 35 && min < 45)
396 	ABC_left (ABC_m1, f - 40.0);
397     if (min >= 40 && min < 50)
398 	ABC_left (ABC_m2, f - 45.0);
399     if (min >= 45 && min < 55)
400 	ABC_left (ABC_m3, f - 50.0);
401     if (min >= 50)
402 	ABC_top (ABC_m1, f - 55.0);
403 }
404