testpat.c revision 1.3 1 /* $NetBSD: testpat.c,v 1.3 2021/01/02 12:12:26 jmcneill Exp $ */
2
3 /*-
4 * Copyright (c) 2016 Nathanial Sloss <nathanialsloss (at) yahoo.com.au>
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #include <curses.h>
30 #include <err.h>
31 #include <errno.h>
32 #include <math.h>
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <time.h>
37 #include <sys/time.h>
38 #include <sys/types.h>
39
40 int main(int argc, char *argv[]) {
41 int i, col, colour, line, x_limit, y_limit, colourOK, spacing;
42 int xpos, ypos, spacing_residual, spacing_start, spacing_end;
43 int grid_x, grid_y;
44 float grid_unit;
45
46 char title[255] = "NetBSD";
47 int numcolours = 6;
48
49 int colour_list[6] = {
50 COLOR_YELLOW,
51 COLOR_CYAN,
52 COLOR_GREEN,
53 COLOR_MAGENTA,
54 COLOR_RED,
55 COLOR_BLUE,
56 };
57
58 float coord_x, circle_int;
59 float a_axis, b_axis;
60
61 if (!(initscr())) {
62 printf("\nUnknown terminal type.");
63 printf("\n");
64 return EXIT_FAILURE;
65 }
66 curs_set(0);
67
68 if (argc > 2) {
69 endwin();
70 errx(EINVAL, "usage: testpat [title]");
71 }
72
73 if (argc == 2 && strlen(argv[1]) < (size_t)COLS)
74 snprintf(title, sizeof(title), "%s", argv[1]);
75 else if (argc == 2 && (int)strlen(argv[1]) > COLS) {
76 endwin();
77 errx(EINVAL, "title string must be less than display columns");
78 }
79
80 colourOK = has_colors();
81
82 if (COLS < 13 || LINES < 13) {
83 endwin();
84 printf("\nTerminal size must be at least 72x25.");
85 printf("\n");
86 return EXIT_FAILURE;
87 }
88
89 if (colourOK) {
90 start_color();
91
92 init_pair( 0, COLOR_WHITE, COLOR_BLACK );
93 init_pair( 1, COLOR_WHITE, COLOR_RED );
94 init_pair( 2, COLOR_WHITE, COLOR_GREEN );
95 init_pair( 3, COLOR_WHITE, COLOR_YELLOW );
96 init_pair( 4, COLOR_WHITE, COLOR_BLUE );
97 init_pair( 5, COLOR_WHITE, COLOR_MAGENTA );
98 init_pair( 6, COLOR_WHITE, COLOR_CYAN );
99 init_pair( 7, COLOR_BLACK, COLOR_WHITE );
100
101 attrset(COLOR_PAIR(0));
102 }
103
104 x_limit = (COLS - 1) / 2;
105 x_limit = x_limit * 2;
106 y_limit = (LINES - 2) / 2;
107 y_limit = y_limit * 2;
108 spacing = 2 * y_limit / numcolours;
109 spacing_residual = ((2 * y_limit) % numcolours) / 2;
110 a_axis = y_limit / 2;
111 b_axis = y_limit;
112 grid_unit = b_axis / 13;
113 grid_y = grid_unit;
114 grid_x = grid_unit * 2;
115
116 int circle_pos[y_limit][2];
117 memset(circle_pos, -1, sizeof(circle_pos));
118
119 for (i = 0; i < y_limit; i++) {
120 /* Draw an elipse (looks more circular.) */
121 circle_int = (i - a_axis) / a_axis;
122 circle_int = 1 - powf(circle_int, 2);
123 circle_int = circle_int * powf(b_axis, 2);
124 #if 0
125 /* Draw a circle, commented out as elipse looks better.*/
126 circle_int = powf(a_axis, 2) - powf(i - a_axis, 2);
127 #endif
128 coord_x = sqrtf(circle_int);
129 circle_pos[i][0] = (-coord_x + ((float)x_limit / 2));
130 circle_pos[i][1] = (coord_x + ((float)x_limit / 2));
131 }
132
133 clear();
134
135 attron(A_ALTCHARSET);
136 move(0, 0);
137
138 /* Draw a grid. */
139 for (line = 1; line < y_limit; line += grid_y) {
140 for (col = 1; col < x_limit; col = col + grid_x) {
141 xpos = col;
142 while ((xpos < col + grid_x - 1) && (xpos <
143 x_limit)) {
144 mvaddch(line + grid_y - 1, xpos, 113 |
145 A_ALTCHARSET);
146 xpos++;
147 }
148 if (xpos < x_limit)
149 mvaddch(line + grid_y - 1, xpos, 110 |
150 A_ALTCHARSET);
151 }
152 ypos = line;
153 while (ypos < line + grid_y - 1) {
154 for (col = grid_x - 1; col < x_limit; col += grid_x) {
155 mvaddch(ypos, col + 1, 120 | A_ALTCHARSET);
156 }
157 ypos++;
158 }
159 }
160
161 for (line = 1; line < y_limit; line += grid_y) {
162 mvaddch(line + grid_y - 1, 0, 116 | A_ALTCHARSET);
163 mvaddch(line + grid_y - 1, x_limit, 117 | A_ALTCHARSET);
164
165 ypos = line;
166 while (ypos < line + grid_y - 1) {
167 mvaddch(ypos, 0, 120 | A_ALTCHARSET);
168 mvaddch(ypos, x_limit, 120 | A_ALTCHARSET);
169 ypos++;
170 }
171 }
172
173 for (col = 1; col < x_limit; col += grid_x) {
174 mvaddch(0, col + grid_x - 1, 119 | A_ALTCHARSET);
175 mvaddch(y_limit, col + grid_x - 1, 118 | A_ALTCHARSET);
176
177 xpos = col;
178 while ((xpos < col + grid_x - 1) && (xpos < x_limit)) {
179 mvaddch(0, xpos, 113 | A_ALTCHARSET);
180 mvaddch(y_limit, xpos, 113 | A_ALTCHARSET);
181 xpos++;
182 }
183 }
184
185 mvaddch(0, 0, 108 | A_ALTCHARSET);
186 mvaddch(0, x_limit, 107 | A_ALTCHARSET);
187 mvaddch(y_limit, 0, 109 | A_ALTCHARSET);
188 mvaddch(y_limit, x_limit, 106 | A_ALTCHARSET);
189
190 /* Draw a white circle. */
191 for (i = 1; i < y_limit; i++) {
192 for (col = circle_pos[i][0]; col <= circle_pos[i][1]; col++) {
193 mvaddch(i, col, 32 | A_REVERSE);
194 }
195 }
196
197 /* Add title segment. */
198 for (i = roundf(1 * grid_unit); i < roundf(2 * grid_unit); i++) {
199 if (colourOK)
200 attrset(COLOR_PAIR(COLOR_BLACK));
201
202 for (col = roundf((4 * grid_unit * 2) +
203 circle_pos[y_limit /2][0]); col <= roundf((9 * grid_unit
204 * 2) + circle_pos[y_limit /2][0]); col++)
205 mvaddch(i, col, ' ');
206 }
207
208 i = roundf(1.4 * grid_unit);
209
210 col = y_limit - (strlen(title) / 2) + circle_pos[y_limit / 2][0];
211 mvprintw(i, col, "%s", title);
212
213 /* Add black segments at top. */
214 for (line = roundf(2 * grid_unit); line < 4 * grid_unit; line++) {
215 if (colourOK)
216 attrset(COLOR_PAIR(COLOR_BLACK));
217
218 for (col = 0; col <= roundf((3.5 * grid_unit * 2)); col++) {
219 xpos = col + circle_pos[y_limit / 2][0];
220 if (xpos >= circle_pos[line][0] &&
221 xpos <= circle_pos[line][1])
222 mvaddch(line, xpos, ' ');
223 }
224
225 for (col = roundf((9.5 * grid_unit * 2)); col <
226 roundf((13 * grid_unit * 2)); col++) {
227 xpos = col + circle_pos[y_limit / 2][0];
228 if (xpos >= circle_pos[line][0] &&
229 xpos <= circle_pos[line][1])
230 mvaddch(line, xpos, ' ');
231 }
232 }
233
234 /* Add black and white squares close to top. */
235 int gap = (circle_pos[(int)(5 * grid_unit)][1] -
236 circle_pos[(int)(5 * grid_unit)][0]) / 13;
237
238 for (i = roundf(3 * grid_unit); i < roundf(4 * grid_unit); i++) {
239 for (xpos = 0; xpos <= x_limit; xpos += 2 * gap) {
240 if (colourOK)
241 attrset(COLOR_PAIR(COLOR_BLACK));
242
243 for (col = xpos; col < xpos + gap; col++) {
244 if (col >= circle_pos[i][0] &&
245 col <= circle_pos[i][1])
246 mvaddch(i, col, ' ');
247 }
248
249 if (colourOK)
250 attrset(COLOR_PAIR(COLOR_WHITE));
251
252 for (col = xpos + gap ; col < xpos + (2 * gap);
253 col++) {
254 if (col >= circle_pos[i][0] &&
255 col <= circle_pos[i][1])
256 mvaddch(i, col, ' ');
257 }
258 }
259 }
260
261 /* Add colour bars. */
262 for (i = 0; i < numcolours; i++) {
263 colour = colour_list[i];
264 if (colourOK)
265 attrset(COLOR_PAIR(colour));
266
267 if (i == 0)
268 spacing_start = 0;
269 else
270 spacing_start = (spacing * i) + spacing_residual;
271
272 if (i == numcolours - 1)
273 spacing_end = circle_pos[y_limit / 2][1];
274 else
275 spacing_end = (spacing * (i + 1)) + spacing_residual;
276
277 for (line = roundf(4 * grid_unit); line < (y_limit / 2);
278 line++) {
279 for (col = spacing_start; col < spacing_end; col++) {
280 xpos = col + circle_pos[y_limit / 2][0];
281 if (xpos >= circle_pos[line][0] &&
282 xpos <= circle_pos[line][1])
283 mvprintw(line, xpos, " ");
284 }
285 }
286 }
287
288 /* Add black segment under centre line. */
289 for (line = y_limit / 2; line < (9.5 * grid_unit); line++) {
290 if (colourOK)
291 attrset(COLOR_PAIR(COLOR_BLACK));
292
293 for (col = circle_pos[line][0]; col <= circle_pos[line][1];
294 col++)
295 mvaddch(line, col, ' ');
296
297 for (col = roundf((1.5 * grid_unit * 2)); col <
298 roundf((4.3 * grid_unit * 2)); col++) {
299 xpos = col + circle_pos[y_limit / 2][0];
300 if (xpos >= circle_pos[line][0] &&
301 xpos < circle_pos[line][1])
302 mvaddch(line, xpos, 120 | A_ALTCHARSET);
303 }
304
305 for (col = roundf((4.3 * grid_unit * 2)); col <
306 roundf((7.6 * grid_unit * 2)); col++) {
307 xpos = col + circle_pos[y_limit / 2][0];
308 if (xpos >= circle_pos[line][0] &&
309 xpos < circle_pos[line][1])
310 mvaddch(line, xpos, '|');
311 }
312
313 for (col = roundf((7.6 * grid_unit * 2)); col <
314 roundf((11.5 * grid_unit * 2)); col++) {
315 xpos = col + circle_pos[y_limit / 2][0];
316 if (xpos >= circle_pos[line][0] &&
317 xpos < circle_pos[line][1])
318 mvaddch(line, xpos, 97 | A_ALTCHARSET);
319 }
320 }
321
322 /* Add black segment close to bottom. */
323 for (line = roundf(9.5 * grid_unit); line <= (10.5 * grid_unit);
324 line++) {
325 if (colourOK)
326 attrset(COLOR_PAIR(COLOR_BLACK));
327
328 for (col = roundf((0 * grid_unit * 2)); col <
329 roundf((4 * grid_unit * 2)); col++) {
330 xpos = col + circle_pos[y_limit / 2][0];
331 if (xpos >= circle_pos[line][0] &&
332 xpos < circle_pos[line][1])
333 mvaddch(line, xpos, ' ');
334 }
335
336 for (col = roundf((4 * grid_unit * 2)); col <
337 roundf((6.5 * grid_unit * 2)); col++) {
338 xpos = col + circle_pos[y_limit / 2][0];
339 if (xpos >= circle_pos[line][0] &&
340 xpos < circle_pos[line][1])
341 mvaddch(line, xpos, 97 | A_ALTCHARSET);
342 }
343
344 if (colourOK)
345 attrset(COLOR_PAIR(COLOR_WHITE));
346
347 for (col = roundf((6.5 * grid_unit * 2)); col <
348 roundf((9 * grid_unit * 2)); col++) {
349 xpos = col + circle_pos[y_limit / 2][0];
350 if (xpos >= circle_pos[line][0] &&
351 xpos < circle_pos[line][1])
352 mvaddch(line, xpos, 97 | A_ALTCHARSET);
353 }
354
355 for (col = roundf((9 * grid_unit * 2)); col <
356 roundf((13 * grid_unit * 2)); col++) {
357 xpos = col + circle_pos[y_limit / 2][0];
358 if (xpos >= circle_pos[line][0] &&
359 xpos < circle_pos[line][1])
360 mvaddch(line, xpos, ' ');
361 }
362 }
363
364 /* Add name segment close to bottom. */
365 for (line = roundf(10.5 * grid_unit); line < (12 * grid_unit);
366 line++) {
367 if (colourOK)
368 attrset(COLOR_PAIR(COLOR_BLACK));
369
370 for (col = roundf(3.5 * grid_unit * 2); col <= roundf(9.5 *
371 grid_unit * 2); col++) {
372 xpos = col + circle_pos[y_limit / 2][0];
373 if (xpos >= circle_pos[line][0] &&
374 xpos < circle_pos[line][1])
375 mvaddch(line, xpos, ' ');
376 }
377
378 if (colourOK)
379 attrset(COLOR_PAIR(COLOR_WHITE));
380
381 for (col = roundf(0 * grid_unit * 2); col <= roundf(3.5 *
382 grid_unit * 2); col++) {
383 xpos = col + circle_pos[y_limit / 2][0];
384 if (xpos >= circle_pos[line][0] &&
385 xpos < circle_pos[line][1])
386 mvaddch(line, xpos, ' ');
387 }
388
389 for (col = roundf(9.5 * grid_unit * 2); col <= roundf(13 *
390 grid_unit * 2); col++) {
391 xpos = col + circle_pos[y_limit / 2][0];
392 if (xpos >= circle_pos[line][0] &&
393 xpos < circle_pos[line][1])
394 mvaddch(line, xpos, ' ');
395 }
396 }
397
398 /* Add yellow segment at bottom. */
399 for (line = 12 * grid_unit; line < y_limit; line++) {
400 if (colourOK)
401 attrset(COLOR_PAIR(COLOR_YELLOW));
402
403 for (col = circle_pos[line][0]; col <= circle_pos[line][1];
404 col++)
405 mvaddch(line, col, ' ');
406
407 if (colourOK)
408 attrset(COLOR_PAIR(COLOR_RED));
409
410 for (col = roundf((6 * grid_unit * 2)); col <
411 roundf((7 * grid_unit * 2)); col++) {
412 xpos = col + circle_pos[y_limit / 2][0];
413 if (xpos >= circle_pos[line][0] &&
414 xpos < circle_pos[line][1])
415 mvaddch(line, xpos, ' ');
416 }
417 }
418
419 if (colourOK)
420 attrset(COLOR_PAIR(COLOR_BLACK));
421
422 for (line = 6 * grid_unit; line <= (7 * grid_unit) + 1; line++) {
423 if (colourOK)
424 attrset(COLOR_PAIR(COLOR_BLACK));
425
426 col = x_limit / 2;
427 if (line != a_axis) {
428 mvaddch(line, col - 1, ' ');
429 mvaddch(line, col, 120 | A_ALTCHARSET);
430 mvaddch(line, col + 1, ' ');
431 }
432 }
433
434 line = y_limit / 2;
435 for (col = 1; col < x_limit; col = col + grid_x) {
436 xpos = col;
437 while (xpos < col + grid_x - 1) {
438 if (xpos >= circle_pos[line][0] && xpos < circle_pos[line][1])
439 mvaddch(line, xpos, 113 | A_ALTCHARSET);
440 xpos++;
441 }
442 if (xpos >= circle_pos[line][0] && xpos < circle_pos[line][1])
443 mvaddch(line, xpos, 110 | A_ALTCHARSET);
444 }
445
446 line = y_limit / 2;
447 col = x_limit / 2;
448 mvaddch(line, col, 110 | A_ALTCHARSET);
449 mvaddch(line, col - 1, 113 | A_ALTCHARSET);
450 mvaddch(line, col + 1, 113 | A_ALTCHARSET);
451
452 refresh();
453
454 getch();
455
456 endwin();
457
458 return EXIT_SUCCESS;
459 }
460
461