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.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}
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
;
87 static void reset_colors(void)
90 tc_putp(tparm(orig_pair
));
95 { /* translate or load the color */
98 for (i
= 0; i
< pairs_used
; i
++) {
99 if (fg_color
[i
] == c
) {
106 if (pairs_used
> max_colors
|| pairs_used
>= MAX_PAIR
) {
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
));
116 tc_putp(tparm(initialize_color
, pairs_used
,
117 def_colors
[c
].r
, def_colors
[c
].g
, def_colors
[c
].b
));
127 { /* change the color to fg and bg. */
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
));
153 /* try to set just the foreground */
154 for (i
= pairs_used
- 1; i
; i
--) {
155 if (fg_color
[i
] == fg
)
158 tc_putp(tparm(set_color_pair
, i
));
164 if (pairs_used
> max_pairs
|| pairs_used
>= MAX_PAIR
) {
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
));
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
));
190 { /* set the color_step for the (ccc) display */
193 for (i
= 2; i
< 1000; i
++) {
194 if ((i
* i
* i
) >= max_colors
) {
198 color_step
= 1000 / (i
- 1);
203 rgb_2_hls(int r
, int g
, int b
, int *h
, int *l
, int *s
)
204 { /* convert RGB to HLS system */
207 if ((min
= g
< r
? g
: r
) > b
) {
210 if ((max
= g
> r
? g
: r
) < b
) {
214 /* calculate lightness */
215 *l
= (min
+ max
) / 20;
217 if (min
== max
) { /* black, white and all shades of gray */
222 /* calculate saturation */
224 *s
= ((max
- min
) * 100) / (max
+ min
);
226 *s
= ((max
- min
) * 100) / (2000 - max
- min
);
231 t
= 120 + ((g
- b
) * 60) / (max
- min
);
232 } else if (g
== max
) {
233 t
= 240 + ((b
- r
) * 60) / (max
- min
);
235 t
= 360 + ((r
- g
) * 60) / (max
- min
);
242 send_color(int p
, int r
, int g
, int b
)
243 { /* send the initialize_color (initc) command */
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
));
250 tc_putp(tparm(initialize_color
, p
, r
, g
, b
));
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
));
265 tc_putp(tparm(initialize_pair
, p
, fr
, fg
, fb
, bb
, bg
, bb
));
272 { /* load the color palette */
276 if (pairs_used
>= n
) {
279 if (set_a_foreground
|| set_foreground
) {
280 if (pairs_used
>= max_colors
) {
283 send_color(pairs_used
, R
, G
, B
);
285 if (rgb
> bright_value
) {
287 a_bright_color
= pairs_used
;
290 if (pairs_used
>= max_pairs
) {
293 if (pairs_used
== 0) {
294 send_pair(pairs_used
, 1000, 1000, 1000, R
, G
, B
);
296 send_pair(pairs_used
, R
, G
, B
, R
, G
, B
);
300 if ((B
+= color_step
) > 1000) {
302 if ((G
+= color_step
) > 1000) {
304 if ((R
+= color_step
) > 1000) {
315 { /* print the programmable color display */
316 int i
, c
, d
, palette_full
, initial_pair
;
317 static const struct {
326 if ((set_a_foreground
|| set_foreground
)
327 ? pairs_used
>= max_colors
328 : pairs_used
>= max_pairs
) {
329 ptext("New palette: ");
331 initial_pair
= pairs_used
= 1;
333 } else if (line_count
+ 3 >= lines
) {
337 initial_pair
= pairs_used
= 1;
341 initial_pair
= pairs_used
;
344 palette_full
= load_palette(n
);
345 for (d
= 0; splat
[d
].name
; d
++) {
348 put_mode(enter_reverse_mode
);
350 for (i
= initial_pair
; i
< n
; i
++) {
351 if (i
>= pairs_used
) {
354 if (set_a_foreground
) {
355 if (i
>= max_colors
) {
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
) {
364 tc_putp(tparm(set_foreground
, i
));
365 tc_putp(tparm(set_background
, i
));
367 if (i
>= max_pairs
) {
370 tc_putp(tparm(set_color_pair
, i
));
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));
384 tc_putp(tparm(set_color_pair
, 0));
387 put_str(splat
[d
].name
);
396 { /* print the no_color_video (ncv) test line */
401 sprintf(temp
, "%-11s", alt_modes
[m
].name
);
404 new_color(COLOR_BLUE
, COLOR_BLACK
, TRUE
);
407 new_color(COLOR_BLACK
, COLOR_GREEN
, TRUE
);
410 new_color(COLOR_WHITE
, COLOR_BLACK
, TRUE
);
411 put_str(alt_modes
[m
].name
);
421 { /* display the colors in some esthetic
423 static int xmap
[8] = {0, 3, 4, 7, 1, 2, 5, 6};
424 int i
, j
, k
, xi
, xj
, width
, p
, cs
;
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
;
434 for (xj
= 0; xj
< 32; xj
++) {
435 j
= ((xj
& 8) ? xj
^ 15 : xj
) & 7;
436 k
= xmap
[((xi
>> 1) & 4) + (xj
>> 3)];
439 if (G
<= 1000 && B
<= 1000) {
440 p
= (k
* width
+ j
) * width
+ i
;
441 if (set_a_background
) {
442 if (p
>= max_colors
) {
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
) {
451 send_color(p
, R
, G
, B
);
452 tc_putp(tparm(set_background
, p
));
454 if (p
>= max_pairs
) {
457 send_pair(p
, R
, G
, B
, R
, G
, B
);
458 tc_putp(tparm(set_color_pair
, p
));
473 ** color_check(test_list, status, ch)
475 ** test (colors) and (pairs)
483 if (max_colors
<= 0 && max_pairs
<= 0) {
484 ptext("This is not a color terminal; (colors) and (pairs) are missing. ");
487 sprintf(temp
, "This terminal can display %d colors and %d color pairs. (colors) (pairs)",
488 max_colors
, max_pairs
);
491 generic_done_message(t
, state
, ch
);
495 ** color_setf(test_list, status, ch)
497 ** test (setf) (setb) and (scp)
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
);
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
);
525 /* initialize the color palette */
526 pairs_used
= max_colors
>= 8 ? 8 : max_colors
;
528 new_color(COLOR_WHITE
, COLOR_BLACK
, FALSE
);
530 ptextln("(setf) (setb) (scp) The following colors are predefined:");
531 ptextln("\n Foreground Background");
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
);
540 sprintf(temp
, " %s ", def_colors
[i
].name
);
542 new_color(def_colors
[i
].index
, COLOR_BLACK
, TRUE
);
545 new_color(COLOR_BLACK
, COLOR_BLACK
, TRUE
);
548 new_color(COLOR_BLACK
, def_colors
[i
].index
, TRUE
);
551 new_color(COLOR_WHITE
, COLOR_BLACK
, FALSE
);
556 generic_done_message(t
, state
, ch
);
560 ** color_matrix(test_list, status, 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
);
577 for ( ; matrix_size
; matrix_size
--) {
578 if (matrix_size
* matrix_size
<= max_pairs
) {
582 matrix_area
= matrix_size
* matrix_size
;
583 for (brightness
= 0; brightness
< 2; brightness
++) {
586 "%dx%d matrix of foreground/background colors, bright *o%s*",
587 matrix_size
, matrix_size
, brightness
? "n" : "ff");
591 for (i
= 0; i
< matrix_size
; i
++) {
592 (void) sprintf(temp
, "%-8s", def_colors
[i
].name
);
595 for (j
= 0; j
< matrix_area
; j
++) {
596 if (j
% matrix_size
== 0) {
600 tc_putp(exit_attribute_mode
);
602 (void) sprintf(temp
, "%-8s", def_colors
[j
/ matrix_size
].name
);
605 put_mode(enter_bold_mode
);
608 new_color(def_colors
[j
% matrix_size
].index
,
609 def_colors
[j
/ matrix_size
].index
,
615 tc_putp(exit_attribute_mode
);
619 generic_done_message(t
, state
, ch
);
623 ** color_ncv(test_list, status, ch)
635 if (no_color_video
== -1) {
636 /* I have no idea what this means */
639 sprintf(temp
, "According to no_color_video (ncv) which is %d, the following attributes should work correctly with color.", no_color_video
);
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
]);
659 generic_done_message(t
, state
, ch
);
663 ** color_bce(test_list, status, ch)
665 ** test (bce) background color erase
673 new_color(COLOR_CYAN
, COLOR_BLUE
, FALSE
);
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");
680 generic_done_message(t
, state
, ch
);
684 ** color_ccc(test_list, status, ch)
686 ** test (ccc) color palette test (oc) (op) (initc) (initp)
697 ptextln("Terminal can not change colors (ccc)");
698 generic_done_message(t
, state
, ch
);
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");
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
);
718 new_color(COLOR_BLACK
, COLOR_BLACK
, TRUE
);
721 new_color(COLOR_BLACK
, i
^ 7, TRUE
);
724 new_color(COLOR_WHITE
, COLOR_BLACK
, FALSE
);
727 generic_done_message(t
, state
, ch
);
728 if (*ch
!= 0 && *ch
!= 'n') {
735 if (magic_cookie_glitch
> 0) {
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);
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
,
757 if (rainbow(colors_per_line
)) {
761 generic_done_message(t
, state
, ch
);
762 if (*ch
!= 0 && *ch
!= 'n') {
768 generic_done_message(t
, state
, ch
);