ncurses 5.6 - patch 20061223
[ncurses.git] / tack / color.c
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.
10 **
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.
15 **
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., 51 Franklin Street, Fifth Floor,
19 ** Boston, MA 02110-1301, USA
20 */
21
22 #include <tack.h>
23
24 MODULE_ID("$Id: color.c,v 1.7 2006/11/26 00:14:25 tom Exp $")
25
26 /*
27  * Color terminal tests.  Has only one entry point: test_color().
28  */
29
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 *);
36
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}
46 };
47
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
58
59 struct color_table {
60         const char *name;
61         int index;
62         int r, g, b;
63         int h, l, s;
64 };
65
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}
75 };
76
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;
86
87 static void reset_colors(void)
88 {
89         tc_putp(orig_colors);
90         tc_putp(TPARM_0(orig_pair));
91 }
92
93 static int
94 color_trans(int c)
95 {                               /* translate or load the color */
96         int i;
97
98         for (i = 0; i < pairs_used; i++) {
99                 if (fg_color[i] == c) {
100                         return i;
101                 }
102         }
103         if (!can_change) {
104                 return 0;
105         }
106         if (pairs_used > max_colors || pairs_used >= MAX_PAIR) {
107                 pairs_used = 0;
108                 ptextln("Ran out of colors");
109         }
110         fg_color[pairs_used] = c;
111         bg_color[pairs_used] = c;
112         if (hue_lightness_saturation) {
113                 tc_putp(TPARM_4(initialize_color, pairs_used,
114                         def_colors[c].h, def_colors[c].l, def_colors[c].s));
115         } else {
116                 tc_putp(TPARM_4(initialize_color, pairs_used,
117                         def_colors[c].r, def_colors[c].g, def_colors[c].b));
118         }
119         return pairs_used++;
120 }
121
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;
129
130         if (hungry) {
131                 eat_cookie();
132         }
133         if (set_a_foreground) {
134                 /* set ANSI color (setaf) (setab) */
135                 tc_putp(TPARM_1(set_a_foreground, fg));
136                 tc_putp(TPARM_1(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_1(set_foreground, color_trans(fg)));
141                 tc_putp(TPARM_1(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_1(set_color_pair, i));
146                                 if (hungry) {
147                                         eat_cookie();
148                                 }
149                                 return;
150                         }
151                 }
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;
157                         }
158                         tc_putp(TPARM_1(set_color_pair, i));
159                         if (hungry) {
160                                 eat_cookie();
161                         }
162                         return;
163                 }
164                 if (pairs_used > max_pairs || pairs_used >= MAX_PAIR) {
165                         pairs_used = 0;
166                         ptextln("Ran out of color pairs");
167                 }
168                 fg_color[pairs_used] = fg;
169                 bg_color[pairs_used] = bg;
170                 if (hue_lightness_saturation) {
171                         tc_putp(TPARM_7(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_7(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));
178                 }
179                 tc_putp(TPARM_1(set_color_pair, pairs_used));
180                 pairs_used++;
181         }
182         if (hungry) {
183                 eat_cookie();
184         }
185 }
186
187
188 static void
189 set_color_step(void)
190 {                               /* set the color_step for the (ccc) display */
191         int i;
192
193         for (i = 2; i < 1000; i++) {
194                 if ((i * i * i) >= max_colors) {
195                         break;
196                 }
197         }
198         color_step = 1000 / (i - 1);
199 }
200
201
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;
206
207         if ((min = g < r ? g : r) > b) {
208                 min = b;
209         }
210         if ((max = g > r ? g : r) < b) {
211                 max = b;
212         }
213
214         /* calculate lightness */
215         *l = (min + max) / 20;
216
217         if (min == max) {       /* black, white and all shades of gray */
218                 *h = 0;
219                 *s = 0;
220                 return;
221         }
222         /* calculate saturation */
223         if (*l < 50) {
224                 *s = ((max - min) * 100) / (max + min);
225         } else {
226                 *s = ((max - min) * 100) / (2000 - max - min);
227         }
228
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);
236         }
237         *h = t % 360;
238 }
239
240
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;
245
246         if (hue_lightness_saturation) {
247                 rgb_2_hls(r, g, b, &h, &l, &s);
248                 tc_putp(TPARM_4(initialize_color, p, h, l, s));
249         } else {
250                 tc_putp(TPARM_4(initialize_color, p, r, g, b));
251         }
252 }
253
254
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;
259
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_7(initialize_pair, p, fh, fl, fs, bh, bl, bs));
264         } else {
265                 tc_putp(TPARM_7(initialize_pair, p, fr, fg, fb, bb, bg, bb));
266         }
267 }
268
269
270 static int
271 load_palette(int n)
272 {                               /* load the color palette */
273         int rgb;
274
275         for (;;) {
276                 if (pairs_used >= n) {
277                         return FALSE;
278                 }
279                 if (set_a_foreground || set_foreground) {
280                         if (pairs_used >= max_colors) {
281                                 return FALSE;
282                         }
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;
288                         }
289                 } else {
290                         if (pairs_used >= max_pairs) {
291                                 return FALSE;
292                         }
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);
297                         }
298                 }
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;
306                                 }
307                         }
308                 }
309         }
310 }
311
312
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}
324         };
325
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;
343         }
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);
349                 }
350                 for (i = initial_pair; i < n; i++) {
351                         if (i >= pairs_used) {
352                                 break;
353                         }
354                         if (set_a_foreground) {
355                                 if (i >= max_colors) {
356                                         break;
357                                 }
358                                 tc_putp(TPARM_1(set_a_foreground, i));
359                                 tc_putp(TPARM_1(set_a_background, i));
360                         } else if (set_foreground) {
361                                 if (i >= max_colors) {
362                                         break;
363                                 }
364                                 tc_putp(TPARM_1(set_foreground, i));
365                                 tc_putp(TPARM_1(set_background, i));
366                         } else {
367                                 if (i >= max_pairs) {
368                                         break;
369                                 }
370                                 tc_putp(TPARM_1(set_color_pair, i));
371                         }
372                         putchp(c);
373                 }
374                 if (d == 1) {
375                         put_mode(exit_attribute_mode);
376                 }
377                 if (set_a_foreground) {
378                         tc_putp(TPARM_1(set_a_foreground, a_bright_color));
379                         tc_putp(TPARM_1(set_a_background, 0));
380                 } else if (set_foreground) {
381                         tc_putp(TPARM_1(set_foreground, a_bright_color));
382                         tc_putp(TPARM_1(set_background, 0));
383                 } else {
384                         tc_putp(TPARM_1(set_color_pair, 0));
385                 }
386                 put_str("   ");
387                 put_str(splat[d].name);
388                 put_crlf();
389         }
390         return palette_full;
391 }
392
393
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);
403
404         new_color(COLOR_BLUE, COLOR_BLACK, TRUE);
405         put_str("blue");
406
407         new_color(COLOR_BLACK, COLOR_GREEN, TRUE);
408         put_str("green");
409
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();
416 }
417
418
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;
426
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;
444                                                 }
445                                                 send_color(p, R, G, B);
446                                                 tc_putp(TPARM_1(set_a_background, p));
447                                         } else if (set_background) {
448                                                 if (p >= max_colors) {
449                                                         continue;
450                                                 }
451                                                 send_color(p, R, G, B);
452                                                 tc_putp(TPARM_1(set_background, p));
453                                         } else {
454                                                 if (p >= max_pairs) {
455                                                         continue;
456                                                 }
457                                                 send_pair(p, R, G, B, R, G, B);
458                                                 tc_putp(TPARM_1(set_color_pair, p));
459                                         }
460                                         found_one = TRUE;
461                                         putchp(' ');
462                                         putchp(' ');
463                                 }
464                         }
465                         if (found_one) {
466                                 put_crlf();
467                         }
468                 }
469         }
470 }
471
472 /*
473 **      color_check(test_list, status, ch)
474 **
475 **      test (colors) and (pairs)
476 */
477 static void
478 color_check(
479         struct test_list *t,
480         int *state,
481         int *ch)
482 {
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);
490         }
491         generic_done_message(t, state, ch);
492 }
493
494 /*
495 **      color_setf(test_list, status, ch)
496 **
497 **      test (setf) (setb) and (scp)
498 */
499 static void
500 color_setf(
501         struct test_list *t,
502         int *state,
503         int *ch)
504 {
505         int i, j;
506
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;
512         }
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");
519                 }
520                 ptext("These must be defined for color testing.  ");
521                 generic_done_message(t, state, ch);
522                 *state |= MENU_STOP;
523                 return;
524         }
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);
529
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;
534         /*
535          * the black on white test is the same as the white on black test.
536          */
537         for (i = 1; i < j; i++) {
538                 putchp('0' + def_colors[i].index);
539                 putchp(' ');
540                 sprintf(temp, " %s ", def_colors[i].name);
541
542                 new_color(def_colors[i].index, COLOR_BLACK, TRUE);
543                 put_str(temp);
544
545                 new_color(COLOR_BLACK, COLOR_BLACK, TRUE);
546                 put_str("  ");
547
548                 new_color(COLOR_BLACK, def_colors[i].index, TRUE);
549                 put_str(temp);
550
551                 new_color(COLOR_WHITE, COLOR_BLACK, FALSE);
552                 put_crlf();
553         }
554         reset_colors();
555         put_crlf();
556         generic_done_message(t, state, ch);
557 }
558
559 /*
560 **      color_matrix(test_list, status, ch)
561 **
562 **      test (pairs) (op)
563 */
564 static void
565 color_matrix(
566         struct test_list *t,
567         int *state,
568         int *ch)
569 {
570         int i, j, matrix_size, matrix_area, brightness;
571
572         matrix_size = max_colors > 8 ? 8 : max_colors;
573
574         sprintf(temp, "(pairs) There are %d color pairs.", max_pairs);
575         ptextln(temp);
576
577         for ( ; matrix_size; matrix_size--) {
578                 if (matrix_size * matrix_size <= max_pairs) {
579                         break;
580                 }
581         }
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);
589
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);
594                 }
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);
601                                 }
602                                 (void) sprintf(temp, "%-8s", def_colors[j / matrix_size].name);
603                                 put_str(temp);
604                                 if (brightness) {
605                                         put_mode(enter_bold_mode);
606                                 }
607                         }
608                         new_color(def_colors[j % matrix_size].index,
609                                 def_colors[j / matrix_size].index,
610                                 FALSE);
611                         put_str("  Hello ");
612                 }
613                 reset_colors();
614                 if (brightness) {
615                         tc_putp(exit_attribute_mode);
616                 }
617                 put_crlf();
618         }
619         generic_done_message(t, state, ch);
620 }
621
622 /*
623 **      color_ncv(test_list, status, ch)
624 **
625 **      test (ncv)
626 */
627 static void
628 color_ncv(
629         struct test_list *t,
630         int *state,
631         int *ch)
632 {
633         int i;
634
635         if (no_color_video == -1) {
636                 /* I have no idea what this means */
637                 return;
638         }
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]);
647                 }
648         }
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]);
654                         }
655                 }
656         }
657         reset_colors();
658         put_crlf();
659         generic_done_message(t, state, ch);
660 }
661
662 /*
663 **      color_bce(test_list, status, ch)
664 **
665 **      test (bce) background color erase
666 */
667 static void
668 color_bce(
669         struct test_list *t,
670         int *state,
671         int *ch)
672 {
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);
681 }
682
683 /*
684 **      color_ccc(test_list, status, ch)
685 **
686 **      test (ccc) color palette test (oc) (op) (initc) (initp)
687 */
688 static void
689 color_ccc(
690         struct test_list *t,
691         int *state,
692         int *ch)
693 {
694         int i, j;
695
696         if (!can_change) {
697                 ptextln("Terminal can not change colors (ccc)");
698                 generic_done_message(t, state, ch);
699                 return;
700         }
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);
714
715                 new_color(i ^ 7, COLOR_BLACK, TRUE);
716                 put_str(temp);
717
718                 new_color(COLOR_BLACK, COLOR_BLACK, TRUE);
719                 put_str("  ");
720
721                 new_color(COLOR_BLACK, i ^ 7, TRUE);
722                 put_str(temp);
723
724                 new_color(COLOR_WHITE, COLOR_BLACK, FALSE);
725                 put_crlf();
726         }
727         generic_done_message(t, state, ch);
728         if (*ch != 0 && *ch != 'n') {
729                 reset_colors();
730                 return;
731         }
732
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);
742         }
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;
749         }
750         sprintf(temp, "RGB color step %d, cookies %d", color_step,
751                 cookie_monster);
752         ptextln(temp);
753
754         R = G = B = 0;
755         pairs_used = 0;
756         for (;;) {
757                 if (rainbow(colors_per_line)) {
758                         break;
759                 }
760         }
761         generic_done_message(t, state, ch);
762         if (*ch != 0 && *ch != 'n') {
763                 reset_colors();
764                 return;
765         }
766         dump_colors();
767         reset_colors();
768         generic_done_message(t, state, ch);
769 }