2 ** Copyright (C) 1991, 1997 Free Software Foundation, Inc.
4 ** This file is part of TACK.
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)
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.
24 MODULE_ID("$Id: color.c,v 1.1 1999/04/18 01:24:45 tom 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}
54 #define COLOR_MAGENTA 5
55 #define COLOR_YELLOW 6
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}
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;
89 { /* translate or load the color */
92 for (i = 0; i < pairs_used; i++) {
93 if (fg_color[i] == c) {
100 if (pairs_used > max_colors || pairs_used >= MAX_PAIR) {
102 ptextln("Ran out of colors");
104 fg_color[pairs_used] = c;
105 bg_color[pairs_used] = c;
106 if (hue_lightness_saturation) {
107 tc_putp(tparm(initialize_color, pairs_used,
108 def_colors[c].h, def_colors[c].l, def_colors[c].s));
110 tc_putp(tparm(initialize_color, pairs_used,
111 def_colors[c].r, def_colors[c].g, def_colors[c].b));
121 { /* change the color to fg and bg. */
127 if (set_a_foreground) {
128 /* set ANSI color (setaf) (setab) */
129 tc_putp(tparm(set_a_foreground, fg));
130 tc_putp(tparm(set_a_background, bg));
131 } else if (set_foreground) {
132 /* make sure black is zero */
133 (void) color_trans(COLOR_BLACK);
134 tc_putp(tparm(set_foreground, color_trans(fg)));
135 tc_putp(tparm(set_background, color_trans(bg)));
136 } else { /* set color pair */
137 for (i = 0; i < pairs_used; i++) {
138 if (fg_color[i] == fg && bg_color[i] == bg) {
139 tc_putp(tparm(set_color_pair, i));
147 /* try to set just the foreground */
148 for (i = pairs_used - 1; i; i--) {
149 if (fg_color[i] == fg)
152 tc_putp(tparm(set_color_pair, i));
158 if (pairs_used > max_pairs || pairs_used >= MAX_PAIR) {
160 ptextln("Ran out of color pairs");
162 fg_color[pairs_used] = fg;
163 bg_color[pairs_used] = bg;
164 if (hue_lightness_saturation) {
165 tc_putp(tparm(initialize_pair, pairs_used,
166 def_colors[fg].h, def_colors[fg].l, def_colors[fg].s,
167 def_colors[bg].h, def_colors[bg].l, def_colors[bg].s));
169 tc_putp(tparm(initialize_pair, pairs_used,
170 def_colors[fg].r, def_colors[fg].g, def_colors[fg].b,
171 def_colors[bg].r, def_colors[bg].g, def_colors[bg].b));
173 tc_putp(tparm(set_color_pair, pairs_used));
184 { /* set the color_step for the (ccc) display */
187 for (i = 2; i < 1000; i++) {
188 if ((i * i * i) >= max_colors) {
192 color_step = 1000 / (i - 1);
197 rgb_2_hls(int r, int g, int b, int *h, int *l, int *s)
198 { /* convert RGB to HLS system */
201 if ((min = g < r ? g : r) > b) {
204 if ((max = g > r ? g : r) < b) {
208 /* calculate lightness */
209 *l = (min + max) / 20;
211 if (min == max) { /* black, white and all shades of gray */
216 /* calculate saturation */
218 *s = ((max - min) * 100) / (max + min);
220 *s = ((max - min) * 100) / (2000 - max - min);
225 t = 120 + ((g - b) * 60) / (max - min);
226 } else if (g == max) {
227 t = 240 + ((b - r) * 60) / (max - min);
229 t = 360 + ((r - g) * 60) / (max - min);
236 send_color(int p, int r, int g, int b)
237 { /* send the initialize_color (initc) command */
240 if (hue_lightness_saturation) {
241 rgb_2_hls(r, g, b, &h, &l, &s);
242 tc_putp(tparm(initialize_color, p, h, l, s));
244 tc_putp(tparm(initialize_color, p, r, g, b));
250 send_pair(int p, int fr, int fg, int fb, int br, int bg, int bb)
251 { /* send the initialize_pair (initp) command */
252 int fh, fl, fs, bh, bl, bs;
254 if (hue_lightness_saturation) {
255 rgb_2_hls(fr, fg, fb, &fh, &fl, &fs);
256 rgb_2_hls(br, bg, bb, &bh, &bl, &bs);
257 tc_putp(tparm(initialize_pair, p, fh, fl, fs, bh, bl, bs));
259 tc_putp(tparm(initialize_pair, p, fr, fg, fb, bb, bg, bb));
266 { /* load the color palette */
270 if (pairs_used >= n) {
273 if (set_a_foreground || set_foreground) {
274 if (pairs_used >= max_colors) {
277 send_color(pairs_used, R, G, B);
279 if (rgb > bright_value) {
281 a_bright_color = pairs_used;
284 if (pairs_used >= max_pairs) {
287 if (pairs_used == 0) {
288 send_pair(pairs_used, 1000, 1000, 1000, R, G, B);
290 send_pair(pairs_used, R, G, B, R, G, B);
294 if ((B += color_step) > 1000) {
296 if ((G += color_step) > 1000) {
298 if ((R += color_step) > 1000) {
309 { /* print the programable color display */
310 int i, c, d, palette_full, initial_pair;
311 static const struct {
320 if ((set_a_foreground || set_foreground)
321 ? pairs_used >= max_colors
322 : pairs_used >= max_pairs) {
323 ptext("New palette: ");
325 initial_pair = pairs_used = 1;
327 } else if (line_count + 3 >= lines) {
331 initial_pair = pairs_used = 1;
335 initial_pair = pairs_used;
338 palette_full = load_palette(n);
339 for (d = 0; splat[d].name; d++) {
342 put_mode(enter_reverse_mode);
344 for (i = initial_pair; i < n; i++) {
345 if (i >= pairs_used) {
348 if (set_a_foreground) {
349 if (i >= max_colors) {
352 tc_putp(tparm(set_a_foreground, i));
353 tc_putp(tparm(set_a_background, i));
354 } else if (set_foreground) {
355 if (i >= max_colors) {
358 tc_putp(tparm(set_foreground, i));
359 tc_putp(tparm(set_background, i));
361 if (i >= max_pairs) {
364 tc_putp(tparm(set_color_pair, i));
369 put_mode(exit_attribute_mode);
371 if (set_a_foreground) {
372 tc_putp(tparm(set_a_foreground, a_bright_color));
373 tc_putp(tparm(set_a_background, 0));
374 } else if (set_foreground) {
375 tc_putp(tparm(set_foreground, a_bright_color));
376 tc_putp(tparm(set_background, 0));
378 tc_putp(tparm(set_color_pair, 0));
381 put_str(splat[d].name);
390 { /* print the no_color_video (ncv) test line */
395 sprintf(temp, "%-11s", alt_modes[m].name);
398 new_color(COLOR_BLUE, COLOR_BLACK, TRUE);
401 new_color(COLOR_BLACK, COLOR_GREEN, TRUE);
404 new_color(COLOR_WHITE, COLOR_BLACK, TRUE);
405 put_str(alt_modes[m].name);
414 { /* display the colors in some esthetic
416 static int xmap[8] = {0, 3, 4, 7, 1, 2, 5, 6};
417 int i, j, k, xi, xj, width, p, cs;
420 cs = color_step <= 125 ? 125 : color_step;
421 width = (1000 / cs) + 1;
422 for (xi = 0; xi < 16; xi++) {
423 i = (xi & 8) ? xi ^ 15 : xi;
427 for (xj = 0; xj < 32; xj++) {
428 j = ((xj & 8) ? xj ^ 15 : xj) & 7;
429 k = xmap[((xi >> 1) & 4) + (xj >> 3)];
432 if (G <= 1000 && B <= 1000) {
433 p = (k * width + j) * width + i;
434 if (set_a_background) {
435 if (p >= max_colors) {
438 send_color(p, R, G, B);
439 tc_putp(tparm(set_a_background, p));
440 } else if (set_background) {
441 if (p >= max_colors) {
444 send_color(p, R, G, B);
445 tc_putp(tparm(set_background, p));
447 if (p >= max_pairs) {
450 send_pair(p, R, G, B, R, G, B);
451 tc_putp(tparm(set_color_pair, p));
466 ** color_check(test_list, status, ch)
468 ** test (colors) and (pairs)
476 if (max_colors <= 0 && max_pairs <= 0) {
477 ptext("This is not a color terminal; (colors) and (pairs) are missing. ");
480 sprintf(temp, "This terminal can display %d colors and %d color pairs. (colors) (pairs)",
481 max_colors, max_pairs);
484 generic_done_message(t, state, ch);
488 ** color_setf(test_list, status, ch)
490 ** test (setf) (setb) and (scp)
500 if (max_colors <= 0 && max_pairs <= 0) {
501 ptext("This is not a color terminal; (colors) and (pairs) are missing. ");
502 generic_done_message(t, state, ch);
506 if ((set_a_foreground == NULL || set_a_background == NULL)
507 && (set_foreground == NULL || set_background == NULL)
508 && set_color_pair == NULL) {
509 ptextln("Both set foreground (setaf/setf) and set color pair (scp) are not present.");
510 if (!set_a_background || !set_background) {
511 ptextln("(setab/setb) set background not present");
513 ptext("These must be defined for color testing. ");
514 generic_done_message(t, state, ch);
518 /* initialize the color palette */
519 pairs_used = max_colors >= 8 ? 8 : max_colors;
521 tc_putp(orig_colors);
523 tc_putp(tparm(orig_pair));
524 new_color(COLOR_WHITE, COLOR_BLACK, FALSE);
526 ptextln("(setf) (setb) (scp) The following colors are predefined:");
527 ptextln("\n Foreground Background");
529 j = max_colors > 8 ? 8 : max_colors;
531 the black on white test is the same as the white on black test.
533 for (i = 1; i < j; i++) {
534 putchp('0' + def_colors[i].index);
536 sprintf(temp, " %s ", def_colors[i].name);
538 new_color(def_colors[i].index, COLOR_BLACK, TRUE);
541 new_color(COLOR_BLACK, COLOR_BLACK, TRUE);
544 new_color(COLOR_BLACK, def_colors[i].index, TRUE);
547 new_color(COLOR_WHITE, COLOR_BLACK, FALSE);
551 generic_done_message(t, state, ch);
555 ** color_matrix(test_list, status, ch)
565 int i, j, matrix_size, matrix_area, brightness;
567 matrix_size = max_colors > 8 ? 8 : max_colors;
569 sprintf(temp, "(pairs) There are %d color pairs.", max_pairs);
572 for ( ; matrix_size; matrix_size--) {
573 if (matrix_size * matrix_size <= max_pairs) {
577 matrix_area = matrix_size * matrix_size;
578 for (brightness = 0; brightness < 2; brightness++) {
581 "%dx%d matrix of foreground/background colors, bright *o%s*",
582 matrix_size, matrix_size, brightness ? "n" : "ff");
586 for (i = 0; i < matrix_size; i++) {
587 (void) sprintf(temp, "%-8s", def_colors[i].name);
590 for (j = 0; j < matrix_area; j++) {
591 if (j % matrix_size == 0) {
592 tc_putp(tparm(orig_pair));
595 tc_putp(exit_standout_mode);
597 (void) sprintf(temp, "%-8s", def_colors[j / matrix_size].name);
600 put_mode(enter_bold_mode);
603 new_color(def_colors[j % matrix_size].index,
604 def_colors[j / matrix_size].index,
608 tc_putp(tparm(orig_pair));
610 tc_putp(exit_standout_mode);
614 generic_done_message(t, state, ch);
618 ** color_ncv(test_list, status, ch)
630 if (no_color_video == -1) {
631 /* I have no idea what this means */
634 sprintf(temp, "According to no_color_video (ncv) which is %d, the following attributes should work correctly with color.", no_color_video);
639 for (i = 1; i <= 9; i++) {
640 if (((no_color_video >> (mode_map[i] - 1)) & 1) == 0) {
641 ncv_display(mode_map[i]);
644 if (no_color_video & 0x3ff) {
645 ptextln("\nThe following attributes should not work correctly with color. (ncv)\n");
646 for (i = 1; i <= 9; i++) {
647 if ((no_color_video >> (mode_map[i] - 1)) & 1) {
648 ncv_display(mode_map[i]);
654 generic_done_message(t, state, ch);
658 ** color_bce(test_list, status, ch)
660 ** test (bce) background color erase
668 new_color(COLOR_BLACK, COLOR_WHITE, FALSE);
671 new_color(COLOR_WHITE, COLOR_BLACK, FALSE);
672 ptextln("If the two lines above are black then back_color_erase (bce) should be false.");
673 sprintf(temp, "(bce) is %s in the data base.", back_color_erase ? "true" : "false");
675 generic_done_message(t, state, ch);
679 ** color_ccc(test_list, status, ch)
681 ** test (ccc) color palette test (oc) (op) (initc) (initp)
692 ptextln("Terminal can not change colors (ccc)");
693 generic_done_message(t, state, ch);
696 tc_putp(orig_colors);
698 new_color(COLOR_WHITE, COLOR_BLACK, FALSE);
699 sprintf(temp, "Reloading colors (init%c) using %s method",
700 set_foreground ? 'c' : 'p',
701 hue_lightness_saturation ? "HLS" : "RGB");
704 j = max_colors > 7 ? 7 : max_colors;
705 /* redisplay the above test with reinitialized colors */
706 /* If these colors don't look right to you... */
707 for (i = 0; i < j; i++) {
708 sprintf(temp, " %s ", def_colors[i ^ 7].name);
710 new_color(i ^ 7, COLOR_BLACK, TRUE);
713 new_color(COLOR_BLACK, COLOR_BLACK, TRUE);
716 new_color(COLOR_BLACK, i ^ 7, TRUE);
719 new_color(COLOR_WHITE, COLOR_BLACK, FALSE);
722 generic_done_message(t, state, ch);
723 if (*ch != 0 && *ch != 'n') {
724 tc_putp(orig_colors);
725 tc_putp(tparm(orig_pair));
731 if (magic_cookie_glitch > 0) {
733 ((set_a_foreground || set_foreground)
734 ? magic_cookie_glitch : 0) +
735 ((set_a_background || set_background)
736 ? magic_cookie_glitch : 0) +
737 (set_color_pair ? magic_cookie_glitch : 0);
740 colors_per_line = max_colors > max_pairs
741 ? max_pairs : max_colors;
742 j = (columns - 14) / (cookie_monster + 1);
743 if (colors_per_line > j) {
744 colors_per_line = (j / i) * i;
746 sprintf(temp, "RGB color step %d, cookies %d", color_step,
753 if (rainbow(colors_per_line)) {
757 generic_done_message(t, state, ch);
758 if (*ch != 0 && *ch != 'n') {
759 tc_putp(orig_colors);
760 tc_putp(tparm(orig_pair));
764 tc_putp(orig_colors);
765 tc_putp(tparm(orig_pair));
766 generic_done_message(t, state, ch);