ncurses 5.1
[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., 59 Temple Place - Suite 330,
19 ** Boston, MA 02111-1307, USA.
20 */
21
22 #include <tack.h>
23
24 MODULE_ID("$Id: color.c,v 1.2 2000/03/04 21:05:54 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 int
88 color_trans(int c)
89 {                               /* translate or load the color */
90         int i;
91
92         for (i = 0; i < pairs_used; i++) {
93                 if (fg_color[i] == c) {
94                         return i;
95                 }
96         }
97         if (!can_change) {
98                 return 0;
99         }
100         if (pairs_used > max_colors || pairs_used >= MAX_PAIR) {
101                 pairs_used = 0;
102                 ptextln("Ran out of colors");
103         }
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));
109         } else {
110                 tc_putp(tparm(initialize_color, pairs_used,
111                         def_colors[c].r, def_colors[c].g, def_colors[c].b));
112         }
113         return pairs_used++;
114 }
115
116 static void
117 new_color(
118         int fg,
119         int bg,
120         int hungry)
121 {                               /* change the color to fg and bg. */
122         int i;
123
124         if (hungry) {
125                 eat_cookie();
126         }
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));
140                                 if (hungry) {
141                                         eat_cookie();
142                                 }
143                                 return;
144                         }
145                 }
146                 if (!can_change) {
147                         /* try to set just the foreground */
148                         for (i = pairs_used - 1; i; i--) {
149                                 if (fg_color[i] == fg)
150                                         break;
151                         }
152                         tc_putp(tparm(set_color_pair, i));
153                         if (hungry) {
154                                 eat_cookie();
155                         }
156                         return;
157                 }
158                 if (pairs_used > max_pairs || pairs_used >= MAX_PAIR) {
159                         pairs_used = 0;
160                         ptextln("Ran out of color pairs");
161                 }
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));
168                 } else {
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));
172                 }
173                 tc_putp(tparm(set_color_pair, pairs_used));
174                 pairs_used++;
175         }
176         if (hungry) {
177                 eat_cookie();
178         }
179 }
180
181
182 static void
183 set_color_step(void)
184 {                               /* set the color_step for the (ccc) display */
185         int i;
186
187         for (i = 2; i < 1000; i++) {
188                 if ((i * i * i) >= max_colors) {
189                         break;
190                 }
191         }
192         color_step = 1000 / (i - 1);
193 }
194
195
196 static void
197 rgb_2_hls(int r, int g, int b, int *h, int *l, int *s)
198 {                               /* convert RGB to HLS system */
199         int min, max, t;
200
201         if ((min = g < r ? g : r) > b) {
202                 min = b;
203         }
204         if ((max = g > r ? g : r) < b) {
205                 max = b;
206         }
207
208         /* calculate lightness */
209         *l = (min + max) / 20;
210
211         if (min == max) {       /* black, white and all shades of gray */
212                 *h = 0;
213                 *s = 0;
214                 return;
215         }
216         /* calculate saturation */
217         if (*l < 50) {
218                 *s = ((max - min) * 100) / (max + min);
219         } else {
220                 *s = ((max - min) * 100) / (2000 - max - min);
221         }
222
223         /* calculate hue */
224         if (r == max) {
225                 t = 120 + ((g - b) * 60) / (max - min);
226         } else if (g == max) {
227                 t = 240 + ((b - r) * 60) / (max - min);
228         } else {
229                 t = 360 + ((r - g) * 60) / (max - min);
230         }
231         *h = t % 360;
232 }
233
234
235 static void
236 send_color(int p, int r, int g, int b)
237 {                               /* send the initialize_color (initc) command */
238         int h, l, s;
239
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));
243         } else {
244                 tc_putp(tparm(initialize_color, p, r, g, b));
245         }
246 }
247
248
249 static void
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;
253
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));
258         } else {
259                 tc_putp(tparm(initialize_pair, p, fr, fg, fb, bb, bg, bb));
260         }
261 }
262
263
264 static int
265 load_palette(int n)
266 {                               /* load the color palette */
267         int rgb;
268
269         for (;;) {
270                 if (pairs_used >= n) {
271                         return FALSE;
272                 }
273                 if (set_a_foreground || set_foreground) {
274                         if (pairs_used >= max_colors) {
275                                 return FALSE;
276                         }
277                         send_color(pairs_used, R, G, B);
278                         rgb = R + G + B;
279                         if (rgb > bright_value) {
280                                 bright_value = rgb;
281                                 a_bright_color = pairs_used;
282                         }
283                 } else {
284                         if (pairs_used >= max_pairs) {
285                                 return FALSE;
286                         }
287                         if (pairs_used == 0) {
288                                 send_pair(pairs_used, 1000, 1000, 1000, R, G, B);
289                         } else {
290                                 send_pair(pairs_used, R, G, B, R, G, B);
291                         }
292                 }
293                 pairs_used++;
294                 if ((B += color_step) > 1000) {
295                         B = 0;
296                         if ((G += color_step) > 1000) {
297                                 G = 0;
298                                 if ((R += color_step) > 1000) {
299                                         return TRUE;
300                                 }
301                         }
302                 }
303         }
304 }
305
306
307 static int
308 rainbow(int n)
309 {                               /* print the programmable color display */
310         int i, c, d, palette_full, initial_pair;
311         static const struct {
312                 const char *name;
313                 char ch;
314         }  splat[] = {
315                 {"Bg normal", ' '},
316                 {"Fg normal", ' '},
317                 {0, 0}
318         };
319
320         if ((set_a_foreground || set_foreground)
321           ? pairs_used >= max_colors
322           : pairs_used >= max_pairs) {
323                 ptext("New palette: ");
324                 (void) wait_here();
325                 initial_pair = pairs_used = 1;
326                 bright_value = 0;
327         } else if (line_count + 3 >= lines) {
328                 ptext("Go: ");
329                 (void) wait_here();
330                 put_clear();
331                 initial_pair = pairs_used = 1;
332                 bright_value = 0;
333                 n++;
334         } else {
335                 initial_pair = pairs_used;
336                 n += initial_pair;
337         }
338         palette_full = load_palette(n);
339         for (d = 0; splat[d].name; d++) {
340                 c = splat[d].ch;
341                 if (d == 1) {
342                         put_mode(enter_reverse_mode);
343                 }
344                 for (i = initial_pair; i < n; i++) {
345                         if (i >= pairs_used) {
346                                 break;
347                         }
348                         if (set_a_foreground) {
349                                 if (i >= max_colors) {
350                                         break;
351                                 }
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) {
356                                         break;
357                                 }
358                                 tc_putp(tparm(set_foreground, i));
359                                 tc_putp(tparm(set_background, i));
360                         } else {
361                                 if (i >= max_pairs) {
362                                         break;
363                                 }
364                                 tc_putp(tparm(set_color_pair, i));
365                         }
366                         putchp(c);
367                 }
368                 if (d == 1) {
369                         put_mode(exit_attribute_mode);
370                 }
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));
377                 } else {
378                         tc_putp(tparm(set_color_pair, 0));
379                 }
380                 put_str("   ");
381                 put_str(splat[d].name);
382                 put_crlf();
383         }
384         return palette_full;
385 }
386
387
388 static void
389 ncv_display(int m)
390 {                               /* print the no_color_video (ncv) test line */
391         putchp('0' + m);
392         putchp(' ');
393         eat_cookie();
394         set_attr(1 << m);
395         sprintf(temp, "%-11s", alt_modes[m].name);
396         put_str(temp);
397
398         new_color(COLOR_BLUE, COLOR_BLACK, TRUE);
399         put_str("blue");
400
401         new_color(COLOR_BLACK, COLOR_GREEN, TRUE);
402         put_str("green");
403
404         new_color(COLOR_WHITE, COLOR_BLACK, TRUE);
405         put_str(alt_modes[m].name);
406         eat_cookie();
407         set_attr(0);
408         put_crlf();
409 }
410
411
412 static void
413 dump_colors(void)
414 {                               /* display the colors in some esthetic
415                                    pattern */
416         static int xmap[8] = {0, 3, 4, 7, 1, 2, 5, 6};
417         int i, j, k, xi, xj, width, p, cs;
418         int found_one;
419
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;
424                 R = i * cs;
425                 if (R <= 1000) {
426                         found_one = FALSE;
427                         for (xj = 0; xj < 32; xj++) {
428                                 j = ((xj & 8) ? xj ^ 15 : xj) & 7;
429                                 k = xmap[((xi >> 1) & 4) + (xj >> 3)];
430                                 G = j * cs;
431                                 B = k * cs;
432                                 if (G <= 1000 && B <= 1000) {
433                                         p = (k * width + j) * width + i;
434                                         if (set_a_background) {
435                                                 if (p >= max_colors) {
436                                                         continue;
437                                                 }
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) {
442                                                         continue;
443                                                 }
444                                                 send_color(p, R, G, B);
445                                                 tc_putp(tparm(set_background, p));
446                                         } else {
447                                                 if (p >= max_pairs) {
448                                                         continue;
449                                                 }
450                                                 send_pair(p, R, G, B, R, G, B);
451                                                 tc_putp(tparm(set_color_pair, p));
452                                         }
453                                         found_one = TRUE;
454                                         putchp(' ');
455                                         putchp(' ');
456                                 }
457                         }
458                         if (found_one) {
459                                 put_crlf();
460                         }
461                 }
462         }
463 }
464
465 /*
466 **      color_check(test_list, status, ch)
467 **
468 **      test (colors) and (pairs)
469 */
470 static void
471 color_check(
472         struct test_list *t,
473         int *state,
474         int *ch)
475 {
476         if (max_colors <= 0 && max_pairs <= 0) {
477                 ptext("This is not a color terminal; (colors) and (pairs) are missing.  ");
478                 *state |= MENU_STOP;
479         } else {
480                 sprintf(temp, "This terminal can display %d colors and %d color pairs.  (colors) (pairs)",
481                         max_colors, max_pairs);
482                 ptextln(temp);
483         }
484         generic_done_message(t, state, ch);
485 }
486
487 /*
488 **      color_setf(test_list, status, ch)
489 **
490 **      test (setf) (setb) and (scp)
491 */
492 static void
493 color_setf(
494         struct test_list *t,
495         int *state,
496         int *ch)
497 {
498         int i, j;
499
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);
503                 *state |= MENU_STOP;
504                 return;
505         }
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");
512                 }
513                 ptext("These must be defined for color testing.  ");
514                 generic_done_message(t, state, ch);
515                 *state |= MENU_STOP;
516                 return;
517         }
518         /* initialize the color palette */
519         pairs_used = max_colors >= 8 ? 8 : max_colors;
520         if (can_change) {
521                 tc_putp(orig_colors);
522         }
523         tc_putp(tparm(orig_pair));
524         new_color(COLOR_WHITE, COLOR_BLACK, FALSE);
525
526         ptextln("(setf) (setb) (scp) The following colors are predefined:");
527         ptextln("\n   Foreground     Background");
528         put_crlf();
529         j = max_colors > 8 ? 8 : max_colors;
530         /*
531            the black on white test is the same as the white on black test.
532         */
533         for (i = 1; i < j; i++) {
534                 putchp('0' + def_colors[i].index);
535                 putchp(' ');
536                 sprintf(temp, " %s ", def_colors[i].name);
537
538                 new_color(def_colors[i].index, COLOR_BLACK, TRUE);
539                 put_str(temp);
540
541                 new_color(COLOR_BLACK, COLOR_BLACK, TRUE);
542                 put_str("  ");
543
544                 new_color(COLOR_BLACK, def_colors[i].index, TRUE);
545                 put_str(temp);
546
547                 new_color(COLOR_WHITE, COLOR_BLACK, FALSE);
548                 put_crlf();
549         }
550         put_crlf();
551         generic_done_message(t, state, ch);
552 }
553
554 /*
555 **      color_matrix(test_list, status, ch)
556 **
557 **      test (pairs) (op)
558 */
559 static void
560 color_matrix(
561         struct test_list *t,
562         int *state,
563         int *ch)
564 {
565         int i, j, matrix_size, matrix_area, brightness;
566
567         matrix_size = max_colors > 8 ? 8 : max_colors;
568
569         sprintf(temp, "(pairs) There are %d color pairs.", max_pairs);
570         ptextln(temp);
571
572         for ( ; matrix_size; matrix_size--) {
573                 if (matrix_size * matrix_size <= max_pairs) {
574                         break;
575                 }
576         }
577         matrix_area = matrix_size * matrix_size;
578         for (brightness = 0; brightness < 2; brightness++) {
579                 put_crlf();
580                 sprintf(temp,
581                         "%dx%d matrix of foreground/background colors, bright *o%s*",
582                         matrix_size, matrix_size, brightness ? "n" : "ff");
583                 put_str(temp);
584
585                 put_str("\n          ");
586                 for (i = 0; i < matrix_size; i++) {
587                         (void) sprintf(temp, "%-8s", def_colors[i].name);
588                         put_str(temp);
589                 }
590                 for (j = 0; j < matrix_area; j++) {
591                         if (j % matrix_size == 0) {
592                                 tc_putp(tparm(orig_pair));
593                                 put_crlf();
594                                 if (brightness) {
595                                         tc_putp(exit_standout_mode);
596                                 }
597                                 (void) sprintf(temp, "%-8s", def_colors[j / matrix_size].name);
598                                 put_str(temp);
599                                 if (brightness) {
600                                         put_mode(enter_bold_mode);
601                                 }
602                         }
603                         new_color(def_colors[j % matrix_size].index,
604                                 def_colors[j / matrix_size].index,
605                                 FALSE);
606                         put_str("  Hello ");
607                 }
608                 tc_putp(tparm(orig_pair));
609                 if (brightness) {
610                         tc_putp(exit_standout_mode);
611                 }
612                 put_crlf();
613         }
614         generic_done_message(t, state, ch);
615 }
616
617 /*
618 **      color_ncv(test_list, status, ch)
619 **
620 **      test (ncv)
621 */
622 static void
623 color_ncv(
624         struct test_list *t,
625         int *state,
626         int *ch)
627 {
628         int i;
629
630         if (no_color_video == -1) {
631                 /* I have no idea what this means */
632                 return;
633         }
634         sprintf(temp, "According to no_color_video (ncv) which is %d, the following attributes should work correctly with color.", no_color_video);
635         ptextln(temp);
636         put_crlf();
637         set_attr(0);
638         ncv_display(0);
639         for (i = 1; i <= 9; i++) {
640                 if (((no_color_video >> (mode_map[i] - 1)) & 1) == 0) {
641                         ncv_display(mode_map[i]);
642                 }
643         }
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]);
649                         }
650                 }
651         }
652         tc_putp(orig_pair);
653         put_crlf();
654         generic_done_message(t, state, ch);
655 }
656
657 /*
658 **      color_bce(test_list, status, ch)
659 **
660 **      test (bce) background color erase
661 */
662 static void
663 color_bce(
664         struct test_list *t,
665         int *state,
666         int *ch)
667 {
668         new_color(COLOR_BLACK, COLOR_WHITE, FALSE);
669         put_clear();
670         put_newlines(2);
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");
674         ptextln(temp);
675         generic_done_message(t, state, ch);
676 }
677
678 /*
679 **      color_ccc(test_list, status, ch)
680 **
681 **      test (ccc) color palette test (oc) (op) (initc) (initp)
682 */
683 static void
684 color_ccc(
685         struct test_list *t,
686         int *state,
687         int *ch)
688 {
689         int i, j;
690
691         if (!can_change) {
692                 ptextln("Terminal can not change colors (ccc)");
693                 generic_done_message(t, state, ch);
694                 return;
695         }
696         tc_putp(orig_colors);
697         pairs_used = 0;
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");
702         ptextln(temp);
703         put_crlf();
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);
709
710                 new_color(i ^ 7, COLOR_BLACK, TRUE);
711                 put_str(temp);
712
713                 new_color(COLOR_BLACK, COLOR_BLACK, TRUE);
714                 put_str("  ");
715
716                 new_color(COLOR_BLACK, i ^ 7, TRUE);
717                 put_str(temp);
718
719                 new_color(COLOR_WHITE, COLOR_BLACK, FALSE);
720                 put_crlf();
721         }
722         generic_done_message(t, state, ch);
723         if (*ch != 0 && *ch != 'n') {
724                 tc_putp(orig_colors);
725                 tc_putp(tparm(orig_pair));
726                 return;
727         }
728
729         pairs_used = 0;
730         cookie_monster = 0;
731         if (magic_cookie_glitch > 0) {
732                 cookie_monster =
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);
738         }
739         set_color_step();
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;
745         }
746         sprintf(temp, "RGB color step %d, cookies %d", color_step,
747                 cookie_monster);
748         ptextln(temp);
749
750         R = G = B = 0;
751         pairs_used = 0;
752         for (;;) {
753                 if (rainbow(colors_per_line)) {
754                         break;
755                 }
756         }
757         generic_done_message(t, state, ch);
758         if (*ch != 0 && *ch != 'n') {
759                 tc_putp(orig_colors);
760                 tc_putp(tparm(orig_pair));
761                 return;
762         }
763         dump_colors();
764         tc_putp(orig_colors);
765         tc_putp(tparm(orig_pair));
766         generic_done_message(t, state, ch);
767 }