Don't fail if the file flags of source and copied symlinks don't match.
[dragonfly.git] / contrib / ncurses-5.4 / tack / color.c
blob17f71f0b4e62ed7c9f7c279504fdfe0bd4934a0c
1 /*
2 ** Copyright (C) 1991, 1997 Free Software Foundation, Inc.
3 **
4 ** This file is part of TACK.
5 **
6 ** TACK is free software; you can redistribute it and/or modify
7 ** it under the terms of the GNU General Public License as published by
8 ** the Free Software Foundation; either version 2, or (at your option)
9 ** any later version.
11 ** TACK is distributed in the hope that it will be useful,
12 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
13 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 ** GNU General Public License for more details.
16 ** You should have received a copy of the GNU General Public License
17 ** along with TACK; see the file COPYING. If not, write to
18 ** the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 ** Boston, MA 02111-1307, USA.
22 #include <tack.h>
24 MODULE_ID("$Id: color.c,v 1.5 2004/01/16 23:14:25 Jochen.Voss Exp $")
27 * Color terminal tests. Has only one entry point: test_color().
30 static void color_check(struct test_list *, int *, int *);
31 static void color_setf(struct test_list *, int *, int *);
32 static void color_matrix(struct test_list *, int *, int *);
33 static void color_ncv(struct test_list *, int *, int *);
34 static void color_ccc(struct test_list *, int *, int *);
35 static void color_bce(struct test_list *, int *, int *);
37 struct test_list color_test_list[] = {
38 {0, 0, 0, 0, "e) edit terminfo", 0, &edit_menu},
39 {MENU_NEXT, 2, "colors) (pairs", 0, 0, color_check, 0},
40 {MENU_NEXT, 12, "setf) (setb) (scp", 0, 0, color_setf, 0},
41 {MENU_NEXT, 24, "op", 0, 0, color_matrix, 0},
42 {MENU_NEXT, 16, "ncv", 0, 0, color_ncv, 0},
43 {MENU_NEXT, 0, "bce", 0, 0, color_bce, 0},
44 {MENU_NEXT | MENU_CLEAR, 0, "ccc) (initc) (initp", "hls op oc", 0, color_ccc, 0},
45 {MENU_LAST, 0, 0, 0, 0, 0, 0}
48 #ifndef COLOR_BLACK
49 #define COLOR_BLACK 0
50 #define COLOR_BLUE 1
51 #define COLOR_GREEN 2
52 #define COLOR_CYAN 3
53 #define COLOR_RED 4
54 #define COLOR_MAGENTA 5
55 #define COLOR_YELLOW 6
56 #define COLOR_WHITE 7
57 #endif
59 struct color_table {
60 const char *name;
61 int index;
62 int r, g, b;
63 int h, l, s;
66 static struct color_table def_colors[8] = {
67 {"black ", COLOR_BLACK, 0, 0, 0, 0, 0, 0},
68 {"blue ", COLOR_BLUE, 0, 0, 1000, 330, 50, 100},
69 {"green ", COLOR_GREEN, 0, 1000, 0, 240, 50, 100},
70 {"cyan ", COLOR_CYAN, 0, 1000, 1000, 300, 50, 100},
71 {"red ", COLOR_RED, 1000, 0, 0, 120, 50, 100},
72 {"magenta", COLOR_MAGENTA, 1000, 0, 1000, 60, 50, 100},
73 {"yellow ", COLOR_YELLOW, 1000, 1000, 0, 180, 50, 100},
74 {"white ", COLOR_WHITE, 1000, 1000, 1000, 0, 100, 0}
77 #define MAX_PAIR 256
78 static int fg_color[MAX_PAIR] = {COLOR_BLACK, COLOR_BLUE, COLOR_GREEN,
79 COLOR_CYAN, COLOR_RED, COLOR_MAGENTA, COLOR_YELLOW, COLOR_WHITE};
80 static int bg_color[MAX_PAIR] = {COLOR_BLACK, COLOR_BLACK, COLOR_BLACK,
81 COLOR_BLACK, COLOR_BLACK, COLOR_BLACK, COLOR_BLACK, COLOR_BLACK};
82 static int pairs_used = 8;
83 static int a_bright_color, bright_value;
84 static int cookie_monster, color_step, colors_per_line;
85 static int R, G, B;
87 static void reset_colors(void)
89 tc_putp(orig_colors);
90 tc_putp(tparm(orig_pair));
93 static int
94 color_trans(int c)
95 { /* translate or load the color */
96 int i;
98 for (i = 0; i < pairs_used; i++) {
99 if (fg_color[i] == c) {
100 return i;
103 if (!can_change) {
104 return 0;
106 if (pairs_used > max_colors || pairs_used >= MAX_PAIR) {
107 pairs_used = 0;
108 ptextln("Ran out of colors");
110 fg_color[pairs_used] = c;
111 bg_color[pairs_used] = c;
112 if (hue_lightness_saturation) {
113 tc_putp(tparm(initialize_color, pairs_used,
114 def_colors[c].h, def_colors[c].l, def_colors[c].s));
115 } else {
116 tc_putp(tparm(initialize_color, pairs_used,
117 def_colors[c].r, def_colors[c].g, def_colors[c].b));
119 return pairs_used++;
122 static void
123 new_color(
124 int fg,
125 int bg,
126 int hungry)
127 { /* change the color to fg and bg. */
128 int i;
130 if (hungry) {
131 eat_cookie();
133 if (set_a_foreground) {
134 /* set ANSI color (setaf) (setab) */
135 tc_putp(tparm(set_a_foreground, fg));
136 tc_putp(tparm(set_a_background, bg));
137 } else if (set_foreground) {
138 /* make sure black is zero */
139 (void) color_trans(COLOR_BLACK);
140 tc_putp(tparm(set_foreground, color_trans(fg)));
141 tc_putp(tparm(set_background, color_trans(bg)));
142 } else { /* set color pair */
143 for (i = 0; i < pairs_used; i++) {
144 if (fg_color[i] == fg && bg_color[i] == bg) {
145 tc_putp(tparm(set_color_pair, i));
146 if (hungry) {
147 eat_cookie();
149 return;
152 if (!can_change) {
153 /* try to set just the foreground */
154 for (i = pairs_used - 1; i; i--) {
155 if (fg_color[i] == fg)
156 break;
158 tc_putp(tparm(set_color_pair, i));
159 if (hungry) {
160 eat_cookie();
162 return;
164 if (pairs_used > max_pairs || pairs_used >= MAX_PAIR) {
165 pairs_used = 0;
166 ptextln("Ran out of color pairs");
168 fg_color[pairs_used] = fg;
169 bg_color[pairs_used] = bg;
170 if (hue_lightness_saturation) {
171 tc_putp(tparm(initialize_pair, pairs_used,
172 def_colors[fg].h, def_colors[fg].l, def_colors[fg].s,
173 def_colors[bg].h, def_colors[bg].l, def_colors[bg].s));
174 } else {
175 tc_putp(tparm(initialize_pair, pairs_used,
176 def_colors[fg].r, def_colors[fg].g, def_colors[fg].b,
177 def_colors[bg].r, def_colors[bg].g, def_colors[bg].b));
179 tc_putp(tparm(set_color_pair, pairs_used));
180 pairs_used++;
182 if (hungry) {
183 eat_cookie();
188 static void
189 set_color_step(void)
190 { /* set the color_step for the (ccc) display */
191 int i;
193 for (i = 2; i < 1000; i++) {
194 if ((i * i * i) >= max_colors) {
195 break;
198 color_step = 1000 / (i - 1);
202 static void
203 rgb_2_hls(int r, int g, int b, int *h, int *l, int *s)
204 { /* convert RGB to HLS system */
205 int min, max, t;
207 if ((min = g < r ? g : r) > b) {
208 min = b;
210 if ((max = g > r ? g : r) < b) {
211 max = b;
214 /* calculate lightness */
215 *l = (min + max) / 20;
217 if (min == max) { /* black, white and all shades of gray */
218 *h = 0;
219 *s = 0;
220 return;
222 /* calculate saturation */
223 if (*l < 50) {
224 *s = ((max - min) * 100) / (max + min);
225 } else {
226 *s = ((max - min) * 100) / (2000 - max - min);
229 /* calculate hue */
230 if (r == max) {
231 t = 120 + ((g - b) * 60) / (max - min);
232 } else if (g == max) {
233 t = 240 + ((b - r) * 60) / (max - min);
234 } else {
235 t = 360 + ((r - g) * 60) / (max - min);
237 *h = t % 360;
241 static void
242 send_color(int p, int r, int g, int b)
243 { /* send the initialize_color (initc) command */
244 int h, l, s;
246 if (hue_lightness_saturation) {
247 rgb_2_hls(r, g, b, &h, &l, &s);
248 tc_putp(tparm(initialize_color, p, h, l, s));
249 } else {
250 tc_putp(tparm(initialize_color, p, r, g, b));
255 static void
256 send_pair(int p, int fr, int fg, int fb, int br, int bg, int bb)
257 { /* send the initialize_pair (initp) command */
258 int fh, fl, fs, bh, bl, bs;
260 if (hue_lightness_saturation) {
261 rgb_2_hls(fr, fg, fb, &fh, &fl, &fs);
262 rgb_2_hls(br, bg, bb, &bh, &bl, &bs);
263 tc_putp(tparm(initialize_pair, p, fh, fl, fs, bh, bl, bs));
264 } else {
265 tc_putp(tparm(initialize_pair, p, fr, fg, fb, bb, bg, bb));
270 static int
271 load_palette(int n)
272 { /* load the color palette */
273 int rgb;
275 for (;;) {
276 if (pairs_used >= n) {
277 return FALSE;
279 if (set_a_foreground || set_foreground) {
280 if (pairs_used >= max_colors) {
281 return FALSE;
283 send_color(pairs_used, R, G, B);
284 rgb = R + G + B;
285 if (rgb > bright_value) {
286 bright_value = rgb;
287 a_bright_color = pairs_used;
289 } else {
290 if (pairs_used >= max_pairs) {
291 return FALSE;
293 if (pairs_used == 0) {
294 send_pair(pairs_used, 1000, 1000, 1000, R, G, B);
295 } else {
296 send_pair(pairs_used, R, G, B, R, G, B);
299 pairs_used++;
300 if ((B += color_step) > 1000) {
301 B = 0;
302 if ((G += color_step) > 1000) {
303 G = 0;
304 if ((R += color_step) > 1000) {
305 return TRUE;
313 static int
314 rainbow(int n)
315 { /* print the programmable color display */
316 int i, c, d, palette_full, initial_pair;
317 static const struct {
318 const char *name;
319 char ch;
320 } splat[] = {
321 {"Bg normal", ' '},
322 {"Fg normal", ' '},
323 {0, 0}
326 if ((set_a_foreground || set_foreground)
327 ? pairs_used >= max_colors
328 : pairs_used >= max_pairs) {
329 ptext("New palette: ");
330 (void) wait_here();
331 initial_pair = pairs_used = 1;
332 bright_value = 0;
333 } else if (line_count + 3 >= lines) {
334 ptext("Go: ");
335 (void) wait_here();
336 put_clear();
337 initial_pair = pairs_used = 1;
338 bright_value = 0;
339 n++;
340 } else {
341 initial_pair = pairs_used;
342 n += initial_pair;
344 palette_full = load_palette(n);
345 for (d = 0; splat[d].name; d++) {
346 c = splat[d].ch;
347 if (d == 1) {
348 put_mode(enter_reverse_mode);
350 for (i = initial_pair; i < n; i++) {
351 if (i >= pairs_used) {
352 break;
354 if (set_a_foreground) {
355 if (i >= max_colors) {
356 break;
358 tc_putp(tparm(set_a_foreground, i));
359 tc_putp(tparm(set_a_background, i));
360 } else if (set_foreground) {
361 if (i >= max_colors) {
362 break;
364 tc_putp(tparm(set_foreground, i));
365 tc_putp(tparm(set_background, i));
366 } else {
367 if (i >= max_pairs) {
368 break;
370 tc_putp(tparm(set_color_pair, i));
372 putchp(c);
374 if (d == 1) {
375 put_mode(exit_attribute_mode);
377 if (set_a_foreground) {
378 tc_putp(tparm(set_a_foreground, a_bright_color));
379 tc_putp(tparm(set_a_background, 0));
380 } else if (set_foreground) {
381 tc_putp(tparm(set_foreground, a_bright_color));
382 tc_putp(tparm(set_background, 0));
383 } else {
384 tc_putp(tparm(set_color_pair, 0));
386 put_str(" ");
387 put_str(splat[d].name);
388 put_crlf();
390 return palette_full;
394 static void
395 ncv_display(int m)
396 { /* print the no_color_video (ncv) test line */
397 putchp('0' + m);
398 putchp(' ');
399 eat_cookie();
400 set_attr(1 << m);
401 sprintf(temp, "%-11s", alt_modes[m].name);
402 put_str(temp);
404 new_color(COLOR_BLUE, COLOR_BLACK, TRUE);
405 put_str("blue");
407 new_color(COLOR_BLACK, COLOR_GREEN, TRUE);
408 put_str("green");
410 new_color(COLOR_WHITE, COLOR_BLACK, TRUE);
411 put_str(alt_modes[m].name);
412 eat_cookie();
413 set_attr(0);
414 reset_colors();
415 put_crlf();
419 static void
420 dump_colors(void)
421 { /* display the colors in some esthetic
422 pattern */
423 static int xmap[8] = {0, 3, 4, 7, 1, 2, 5, 6};
424 int i, j, k, xi, xj, width, p, cs;
425 int found_one;
427 cs = color_step <= 125 ? 125 : color_step;
428 width = (1000 / cs) + 1;
429 for (xi = 0; xi < 16; xi++) {
430 i = (xi & 8) ? xi ^ 15 : xi;
431 R = i * cs;
432 if (R <= 1000) {
433 found_one = FALSE;
434 for (xj = 0; xj < 32; xj++) {
435 j = ((xj & 8) ? xj ^ 15 : xj) & 7;
436 k = xmap[((xi >> 1) & 4) + (xj >> 3)];
437 G = j * cs;
438 B = k * cs;
439 if (G <= 1000 && B <= 1000) {
440 p = (k * width + j) * width + i;
441 if (set_a_background) {
442 if (p >= max_colors) {
443 continue;
445 send_color(p, R, G, B);
446 tc_putp(tparm(set_a_background, p));
447 } else if (set_background) {
448 if (p >= max_colors) {
449 continue;
451 send_color(p, R, G, B);
452 tc_putp(tparm(set_background, p));
453 } else {
454 if (p >= max_pairs) {
455 continue;
457 send_pair(p, R, G, B, R, G, B);
458 tc_putp(tparm(set_color_pair, p));
460 found_one = TRUE;
461 putchp(' ');
462 putchp(' ');
465 if (found_one) {
466 put_crlf();
473 ** color_check(test_list, status, ch)
475 ** test (colors) and (pairs)
477 static void
478 color_check(
479 struct test_list *t,
480 int *state,
481 int *ch)
483 if (max_colors <= 0 && max_pairs <= 0) {
484 ptext("This is not a color terminal; (colors) and (pairs) are missing. ");
485 *state |= MENU_STOP;
486 } else {
487 sprintf(temp, "This terminal can display %d colors and %d color pairs. (colors) (pairs)",
488 max_colors, max_pairs);
489 ptextln(temp);
491 generic_done_message(t, state, ch);
495 ** color_setf(test_list, status, ch)
497 ** test (setf) (setb) and (scp)
499 static void
500 color_setf(
501 struct test_list *t,
502 int *state,
503 int *ch)
505 int i, j;
507 if (max_colors <= 0 && max_pairs <= 0) {
508 ptext("This is not a color terminal; (colors) and (pairs) are missing. ");
509 generic_done_message(t, state, ch);
510 *state |= MENU_STOP;
511 return;
513 if ((set_a_foreground == NULL || set_a_background == NULL)
514 && (set_foreground == NULL || set_background == NULL)
515 && set_color_pair == NULL) {
516 ptextln("Both set foreground (setaf/setf) and set color pair (scp) are not present.");
517 if (!set_a_background || !set_background) {
518 ptextln("(setab/setb) set background not present");
520 ptext("These must be defined for color testing. ");
521 generic_done_message(t, state, ch);
522 *state |= MENU_STOP;
523 return;
525 /* initialize the color palette */
526 pairs_used = max_colors >= 8 ? 8 : max_colors;
527 reset_colors();
528 new_color(COLOR_WHITE, COLOR_BLACK, FALSE);
530 ptextln("(setf) (setb) (scp) The following colors are predefined:");
531 ptextln("\n Foreground Background");
532 put_crlf();
533 j = max_colors > 8 ? 8 : max_colors;
535 * the black on white test is the same as the white on black test.
537 for (i = 1; i < j; i++) {
538 putchp('0' + def_colors[i].index);
539 putchp(' ');
540 sprintf(temp, " %s ", def_colors[i].name);
542 new_color(def_colors[i].index, COLOR_BLACK, TRUE);
543 put_str(temp);
545 new_color(COLOR_BLACK, COLOR_BLACK, TRUE);
546 put_str(" ");
548 new_color(COLOR_BLACK, def_colors[i].index, TRUE);
549 put_str(temp);
551 new_color(COLOR_WHITE, COLOR_BLACK, FALSE);
552 put_crlf();
554 reset_colors();
555 put_crlf();
556 generic_done_message(t, state, ch);
560 ** color_matrix(test_list, status, ch)
562 ** test (pairs) (op)
564 static void
565 color_matrix(
566 struct test_list *t,
567 int *state,
568 int *ch)
570 int i, j, matrix_size, matrix_area, brightness;
572 matrix_size = max_colors > 8 ? 8 : max_colors;
574 sprintf(temp, "(pairs) There are %d color pairs.", max_pairs);
575 ptextln(temp);
577 for ( ; matrix_size; matrix_size--) {
578 if (matrix_size * matrix_size <= max_pairs) {
579 break;
582 matrix_area = matrix_size * matrix_size;
583 for (brightness = 0; brightness < 2; brightness++) {
584 put_crlf();
585 sprintf(temp,
586 "%dx%d matrix of foreground/background colors, bright *o%s*",
587 matrix_size, matrix_size, brightness ? "n" : "ff");
588 put_str(temp);
590 put_str("\n ");
591 for (i = 0; i < matrix_size; i++) {
592 (void) sprintf(temp, "%-8s", def_colors[i].name);
593 put_str(temp);
595 for (j = 0; j < matrix_area; j++) {
596 if (j % matrix_size == 0) {
597 reset_colors();
598 put_crlf();
599 if (brightness) {
600 tc_putp(exit_attribute_mode);
602 (void) sprintf(temp, "%-8s", def_colors[j / matrix_size].name);
603 put_str(temp);
604 if (brightness) {
605 put_mode(enter_bold_mode);
608 new_color(def_colors[j % matrix_size].index,
609 def_colors[j / matrix_size].index,
610 FALSE);
611 put_str(" Hello ");
613 reset_colors();
614 if (brightness) {
615 tc_putp(exit_attribute_mode);
617 put_crlf();
619 generic_done_message(t, state, ch);
623 ** color_ncv(test_list, status, ch)
625 ** test (ncv)
627 static void
628 color_ncv(
629 struct test_list *t,
630 int *state,
631 int *ch)
633 int i;
635 if (no_color_video == -1) {
636 /* I have no idea what this means */
637 return;
639 sprintf(temp, "According to no_color_video (ncv) which is %d, the following attributes should work correctly with color.", no_color_video);
640 ptextln(temp);
641 put_crlf();
642 set_attr(0);
643 ncv_display(0);
644 for (i = 1; i <= 9; i++) {
645 if (((no_color_video >> (mode_map[i] - 1)) & 1) == 0) {
646 ncv_display(mode_map[i]);
649 if (no_color_video & 0x3ff) {
650 ptextln("\nThe following attributes should not work correctly with color. (ncv)\n");
651 for (i = 1; i <= 9; i++) {
652 if ((no_color_video >> (mode_map[i] - 1)) & 1) {
653 ncv_display(mode_map[i]);
657 reset_colors();
658 put_crlf();
659 generic_done_message(t, state, ch);
663 ** color_bce(test_list, status, ch)
665 ** test (bce) background color erase
667 static void
668 color_bce(
669 struct test_list *t,
670 int *state,
671 int *ch)
673 new_color(COLOR_CYAN, COLOR_BLUE, FALSE);
674 put_clear();
675 put_newlines(2);
676 reset_colors();
677 ptextln("If the two lines above are blue then back_color_erase (bce) should be true.");
678 sprintf(temp, "(bce) is %s in the data base.", back_color_erase ? "true" : "false");
679 ptextln(temp);
680 generic_done_message(t, state, ch);
684 ** color_ccc(test_list, status, ch)
686 ** test (ccc) color palette test (oc) (op) (initc) (initp)
688 static void
689 color_ccc(
690 struct test_list *t,
691 int *state,
692 int *ch)
694 int i, j;
696 if (!can_change) {
697 ptextln("Terminal can not change colors (ccc)");
698 generic_done_message(t, state, ch);
699 return;
701 reset_colors();
702 pairs_used = 0;
703 new_color(COLOR_WHITE, COLOR_BLACK, FALSE);
704 sprintf(temp, "Reloading colors (init%c) using %s method",
705 set_foreground ? 'c' : 'p',
706 hue_lightness_saturation ? "HLS" : "RGB");
707 ptextln(temp);
708 put_crlf();
709 j = max_colors > 7 ? 7 : max_colors;
710 /* redisplay the above test with reinitialized colors */
711 /* If these colors don't look right to you... */
712 for (i = 0; i < j; i++) {
713 sprintf(temp, " %s ", def_colors[i ^ 7].name);
715 new_color(i ^ 7, COLOR_BLACK, TRUE);
716 put_str(temp);
718 new_color(COLOR_BLACK, COLOR_BLACK, TRUE);
719 put_str(" ");
721 new_color(COLOR_BLACK, i ^ 7, TRUE);
722 put_str(temp);
724 new_color(COLOR_WHITE, COLOR_BLACK, FALSE);
725 put_crlf();
727 generic_done_message(t, state, ch);
728 if (*ch != 0 && *ch != 'n') {
729 reset_colors();
730 return;
733 pairs_used = 0;
734 cookie_monster = 0;
735 if (magic_cookie_glitch > 0) {
736 cookie_monster =
737 ((set_a_foreground || set_foreground)
738 ? magic_cookie_glitch : 0) +
739 ((set_a_background || set_background)
740 ? magic_cookie_glitch : 0) +
741 (set_color_pair ? magic_cookie_glitch : 0);
743 set_color_step();
744 colors_per_line = max_colors > max_pairs
745 ? max_pairs : max_colors;
746 j = (columns - 14) / (cookie_monster + 1);
747 if (colors_per_line > j) {
748 colors_per_line = (j / i) * i;
750 sprintf(temp, "RGB color step %d, cookies %d", color_step,
751 cookie_monster);
752 ptextln(temp);
754 R = G = B = 0;
755 pairs_used = 0;
756 for (;;) {
757 if (rainbow(colors_per_line)) {
758 break;
761 generic_done_message(t, state, ch);
762 if (*ch != 0 && *ch != 'n') {
763 reset_colors();
764 return;
766 dump_colors();
767 reset_colors();
768 generic_done_message(t, state, ch);