1 /* $Id: colors.c,v 5.1 2001/05/08 11:35:29 bertg Exp $
2 *
3 * XPilot, a multiplayer gravity war game. Copyright (C) 1991-2001 by
4 *
5 * Bj�rn Stabell <bjoern@xpilot.org>
6 * Ken Ronny Schouten <ken@xpilot.org>
7 * Bert Gijsbers <bert@xpilot.org>
8 * Dick Balaska <dick@xpilot.org>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 */
24
25 #include <stdlib.h>
26 #include <stdio.h>
27 #include <ctype.h>
28 #include <string.h>
29 #include <errno.h>
30 #include <sys/types.h>
31
32 #ifndef _WINDOWS
33 # include <unistd.h>
34 # include <X11/Xlib.h>
35 # include <X11/Xos.h>
36 # include <X11/Xutil.h>
37 #endif
38
39 #ifdef _WINDOWS
40 # include "NT/winX.h"
41 #endif
42
43 #include "version.h"
44 #include "config.h"
45 #include "const.h"
46 #include "types.h"
47 #include "paint.h"
48 #include "xinit.h"
49 #include "error.h"
50 #include "dbuff.h"
51 #include "protoclient.h"
52
53
54 char colors_version[] = VERSION;
55
56
57 /* Kludge for visuals under C++ */
58 #if defined(__cplusplus)
59 #define class c_class
60 #endif
61
62
63 /*
64 * The number of X11 visuals.
65 */
66 #define MAX_VISUAL_CLASS 6
67
68
69 /*
70 * Default colors.
71 */
72 char color_names[MAX_COLORS][MAX_COLOR_LEN];
73 static const char *color_defaults[MAX_COLORS] = {
74 "#000000", "#FFFFFF", "#4E7CFF", "#FF3A27",
75 "#33BB44", "#992200", "#BB7700", "#EE9900",
76 "#770000", "#CC4400", "#DD8800", "#FFBB11",
77 "#9f9f9f", "#5f5f5f", "#dfdfdf", "#202020"
78 };
79 static const char *gray_defaults[MAX_COLORS] = {
80 "#000000", "#FFFFFF", "#AAAAAA", "#CCCCCC",
81 "#BBBBBB", "#888888", "#AAAAAA", "#CCCCCC",
82 "#777777", "#999999", "#BBBBBB", "#DDDDDD",
83 "#9f9f9f", "#5f5f5f", "#dfdfdf", "#202020"
84 };
85
86 char visualName[MAX_VISUAL_NAME];
87 Visual *visual;
88 int dispDepth;
89 bool mono;
90 bool colorSwitch;
91 bool multibuffer;
92 bool blockBitmaps; /* Whether to draw everything as bitmaps. */
93
94 #ifndef _WINDOWS
95
96 /*
97 * Dimensions of color cubes in decreasing
98 * total number of colors used.
99 */
100 static struct rgb_cube_size {
101 unsigned char r, g, b;
102 } rgb_cube_sizes[] = {
103 { 6, 6, 5 }, /* 180 */
104 { 5, 6, 5 }, /* 150 */
105 { 6, 6, 4 }, /* 144 */
106 { 5, 5, 5 }, /* 125 */
107 { 5, 6, 4 }, /* 120 */
108 { 6, 6, 3 }, /* 108 */
109 { 5, 5, 4 }, /* 100 */
110 { 5, 6, 3 }, /* 90 */
111 { 4, 5, 4 }, /* 80 */
112 { 5, 5, 3 }, /* 75 */
113 { 4, 4, 4 }, /* 64 */
114 { 4, 5, 3 }, /* 60 */
115 { 4, 4, 3 }, /* 48 */
116 };
117
118 unsigned long (*RGB)(u_byte r, u_byte g, u_byte b);
119 static unsigned long RGB_PC(u_byte r, u_byte g, u_byte b);
120 static unsigned long RGB_TC(u_byte r, u_byte g, u_byte b);
121
122 /*
123 * Visual names.
124 */
125 static struct Visual_class_name {
126 int visual_class;
127 const char *visual_name;
128 } visual_class_names[MAX_VISUAL_CLASS] = {
129 { StaticGray, "StaticGray" },
130 { GrayScale, "GrayScale" },
131 { StaticColor, "StaticColor" },
132 { PseudoColor, "PseudoColor" },
133 { TrueColor, "TrueColor" },
134 { DirectColor, "DirectColor" }
135 };
136
137 /*
138 * Structure to hold pixel information
139 * for a color cube for PseudoColor visuals.
140 */
141 struct Color_cube {
142 int reds;
143 int greens;
144 int blues;
145 int mustfree;
146 unsigned long pixels[256];
147 };
148 static struct Color_cube *color_cube;
149
150 /*
151 * Structure to hold pixel information
152 * for a true color visual.
153 */
154 struct True_color {
155 unsigned long red_bits[256];
156 unsigned long green_bits[256];
157 unsigned long blue_bits[256];
158 };
159 static struct True_color *true_color;
160
161 static void Colors_init_radar_hack(void);
162 static int Colors_init_color_cube(void);
163 static int Colors_init_true_color(void);
164
165 /*
166 * Create a private colormap.
167 */
Get_colormap(void)168 static void Get_colormap(void)
169 {
170 printf("Creating a private colormap\n");
171 colormap = XCreateColormap(dpy, DefaultRootWindow(dpy),
172 visual, AllocNone);
173 }
174
175
176 /*
177 * Convert a visual class to its name.
178 */
Visual_class_name(int visual_class)179 static const char *Visual_class_name(int visual_class)
180 {
181 int i;
182
183 for (i = 0; i < MAX_VISUAL_CLASS; i++) {
184 if (visual_class_names[i].visual_class == visual_class) {
185 return visual_class_names[i].visual_name;
186 }
187 }
188 return "UnknownVisual";
189 }
190
191
192 /*
193 * List the available visuals for the default screen.
194 */
List_visuals(void)195 void List_visuals(void)
196 {
197 int i,
198 num;
199 XVisualInfo *vinfo_ptr,
200 my_vinfo;
201 long mask;
202
203 num = 0;
204 mask = 0;
205 my_vinfo.screen = DefaultScreen(dpy);
206 mask |= VisualScreenMask;
207 vinfo_ptr = XGetVisualInfo(dpy, mask, &my_vinfo, &num);
208 printf("Listing all visuals:\n");
209 for (i = 0; i < num; i++) {
210 printf("Visual class %12s\n",
211 Visual_class_name(vinfo_ptr[i].class));
212 printf(" id 0x%02x\n", (unsigned)vinfo_ptr[i].visualid);
213 printf(" screen %8d\n", vinfo_ptr[i].screen);
214 printf(" depth %8d\n", vinfo_ptr[i].depth);
215 printf(" red_mask 0x%06x\n", (unsigned)vinfo_ptr[i].red_mask);
216 printf(" green_mask 0x%06x\n", (unsigned)vinfo_ptr[i].green_mask);
217 printf(" blue_mask 0x%06x\n", (unsigned)vinfo_ptr[i].blue_mask);
218 printf(" colormap_size %8d\n", vinfo_ptr[i].colormap_size);
219 printf(" bits_per_rgb %8d\n", vinfo_ptr[i].bits_per_rgb);
220 }
221 XFree((void *) vinfo_ptr);
222
223 #ifdef DEVELOPMENT
224 dbuff_list(dpy);
225 #endif
226 }
227
228
229 /*
230 * Support all available visuals.
231 */
Choose_visual(void)232 static void Choose_visual(void)
233 {
234 int i,
235 num,
236 best_size,
237 cmap_size,
238 using_default,
239 visual_id,
240 visual_class;
241 XVisualInfo *vinfo_ptr,
242 my_vinfo,
243 *best_vinfo;
244 long mask;
245
246 visual_id = -1;
247 visual_class = -1;
248 if (visualName[0] != '\0') {
249 if (strncmp(visualName, "0x", 2) == 0) {
250 if (sscanf(visualName, "%x", &visual_id) < 1) {
251 errno = 0;
252 error("Bad visual id \"%s\", using default\n", visualName);
253 visual_id = -1;
254 }
255 } else {
256 for (i = 0; i < MAX_VISUAL_CLASS; i++) {
257 if (strncasecmp(visualName, visual_class_names[i].visual_name,
258 strlen(visual_class_names[i].visual_name))
259 == 0) {
260 visual_class = visual_class_names[i].visual_class;
261 break;
262 }
263 }
264 if (visual_class == -1) {
265 errno = 0;
266 error("Unknown visual class named \"%s\", using default\n",
267 visualName);
268 }
269 }
270 }
271 if (visual_class < 0 && visual_id < 0) {
272 visual = DefaultVisual(dpy, DefaultScreen(dpy));
273 if (visual->class == TrueColor || visual->class == DirectColor) {
274 visual_class = PseudoColor;
275 strcpy(visualName, "PseudoColor");
276 }
277 using_default = true;
278 } else {
279 using_default = false;
280 }
281 if (visual_class >= 0 || visual_id >= 0) {
282 mask = 0;
283 my_vinfo.screen = DefaultScreen(dpy);
284 mask |= VisualScreenMask;
285 if (visual_class >= 0) {
286 my_vinfo.class = visual_class;
287 mask |= VisualClassMask;
288 }
289 if (visual_id >= 0) {
290 my_vinfo.visualid = visual_id;
291 mask |= VisualIDMask;
292 }
293 num = 0;
294 if ((vinfo_ptr = XGetVisualInfo(dpy, mask, &my_vinfo, &num)) == NULL
295 || num <= 0) {
296 if (using_default == false) {
297 errno = 0;
298 error("No visuals available with class name \"%s\", using default",
299 visualName);
300 }
301 visual_class = -1;
302 }
303 else {
304 best_vinfo = vinfo_ptr;
305 for (i = 1; i < num; i++) {
306 best_size = best_vinfo->colormap_size;
307 cmap_size = vinfo_ptr[i].colormap_size;
308 if (cmap_size > best_size) {
309 if (best_size < 256) {
310 best_vinfo = &vinfo_ptr[i];
311 }
312 }
313 else if (cmap_size >= 256) {
314 best_vinfo = &vinfo_ptr[i];
315 }
316 }
317 visual = best_vinfo->visual;
318 visual_class = best_vinfo->class;
319 dispDepth = best_vinfo->depth;
320 XFree((void *) vinfo_ptr);
321 printf("Using visual %s with depth %d and %d colors\n",
322 Visual_class_name(visual->class), dispDepth,
323 visual->map_entries);
324 Get_colormap();
325 }
326 }
327 if (visual_class < 0) {
328 visual = DefaultVisual(dpy, DefaultScreen(dpy));
329 dispDepth = DefaultDepth(dpy, DefaultScreen(dpy));
330 colormap = 0;
331 }
332 }
333
334
335 /*
336 * Parse the user configurable color definitions.
337 */
Parse_colors(Colormap cmap)338 static int Parse_colors(Colormap cmap)
339 {
340 int i;
341 const char **def;
342
343 /*
344 * Get the color definitions.
345 */
346 if (mono == true) {
347 colors[0].red = colors[0].green = colors[0].blue = 0;
348 colors[0].flags = DoRed | DoGreen | DoBlue;
349 colors[1].red = colors[1].green = colors[1].blue = 0xFFFF;
350 colors[1].flags = DoRed | DoGreen | DoBlue;
351 colors[2] = colors[1];
352 colors[3] = colors[1];
353 return 0;
354 }
355
356 if (visual->class == StaticGray || visual->class == GrayScale) {
357 def = &gray_defaults[0];
358 } else {
359 def = &color_defaults[0];
360 }
361 for (i = 0; i < maxColors; i++) {
362 if (color_names[i][0] != '\0') {
363 if (XParseColor(dpy, cmap, color_names[i], &colors[i])) {
364 continue;
365 }
366 printf("Can't parse color %d \"%s\"\n", i, color_names[i]);
367 }
368 if (def[i] != NULL && def[i][0] != '\0') {
369 if (XParseColor(dpy, cmap, def[i], &colors[i])) {
370 continue;
371 }
372 printf("Can't parse default color %d \"%s\"\n", i, def[i]);
373 }
374 if (i < NUM_COLORS) {
375 return -1;
376 } else {
377 colors[i] = colors[i % NUM_COLORS];
378 }
379 }
380 return 0;
381 }
382
383
384 /*
385 * If we have a private colormap and color switching is on then
386 * copy the first few colors from the default colormap into it
387 * to prevent ugly color effects on the rest of the screen.
388 */
Fill_colormap(void)389 static void Fill_colormap(void)
390 {
391 int i,
392 cells_needed,
393 max_fill;
394 unsigned long pixels[256];
395 XColor mycolors[256];
396
397 if (colormap == 0 || colorSwitch != true) {
398 return;
399 }
400 cells_needed = (maxColors == 16) ? 256
401 : (maxColors == 8) ? 64
402 : 16;
403 max_fill = MAX(256, visual->map_entries) - cells_needed;
404 if (max_fill <= 0) {
405 return;
406 }
407
408 if (XAllocColorCells(dpy, colormap,
409 False, NULL,
410 0, pixels, max_fill) == False) {
411 errno = 0;
412 error("Can't pre-alloc color cells");
413 return;
414 }
415
416 /* Check for misunderstanding of X colormap stuff. */
417 for (i = 0; i < max_fill; i++) {
418 if (i != (int) pixels[i]) {
419 #ifdef DEVELOPMENT
420 errno = 0;
421 error("Can't pre-fill color map, got %d'th pixel %lu",
422 i, pixels[i]);
423 #endif
424 XFreeColors(dpy, colormap, pixels, max_fill, 0);
425 return;
426 }
427 }
428 for (i = 0; i < max_fill; i++) {
429 mycolors[i].pixel = pixels[i];
430 }
431 XQueryColors(dpy, DefaultColormap(dpy, DefaultScreen(dpy)),
432 mycolors, max_fill);
433 XStoreColors(dpy, colormap, mycolors, max_fill);
434 }
435
436
437 /*
438 * Setup color and double buffering resources.
439 * It returns 0 if the initialization was successful,
440 * or -1 if it couldn't initialize the double buffering routine.
441 */
Colors_init(void)442 int Colors_init(void)
443 {
444 int i, num_planes;
445
446 colormap = 0;
447
448 Choose_visual();
449
450 /*
451 * Get misc. display info.
452 */
453 if (visual->class == StaticGray ||
454 visual->class == StaticColor ||
455 visual->class == TrueColor) {
456 colorSwitch = false;
457 }
458 if (visual->map_entries < 16) {
459 colorSwitch = false;
460 if (visual->map_entries < 4) {
461 mono = true;
462 }
463 }
464 if (mono == true) {
465 colorSwitch = false;
466 maxColors = 4;
467 }
468 else if (colorSwitch == true) {
469 maxColors = (maxColors >= 16 && visual->map_entries >= 256) ? 16
470 : (maxColors >= 8 && visual->map_entries >= 64) ? 8
471 : 4;
472 }
473 else {
474 maxColors = (maxColors >= 16 && visual->map_entries >= 16) ? 16
475 : (maxColors >= 8 && visual->map_entries >= 8) ? 8
476 : 4;
477 }
478 num_planes = (mono == true) ? 1
479 : (maxColors == 16) ? 4
480 : (maxColors == 8) ? 3
481 : 2;
482
483 if (Parse_colors(DefaultColormap(dpy, DefaultScreen(dpy))) == -1) {
484 printf("Color parsing failed\n");
485 return -1;
486 }
487
488 if (colormap != 0) {
489 Fill_colormap();
490 }
491
492 /*
493 * Initialize the double buffering routine.
494 */
495 dbuf_state = NULL;
496
497 if (multibuffer) {
498 dbuf_state = start_dbuff(dpy,
499 (colormap != 0)
500 ? colormap
501 : DefaultColormap(dpy,
502 DefaultScreen(dpy)),
503 MULTIBUFFER,
504 num_planes,
505 colors);
506 }
507 if (dbuf_state == NULL) {
508 dbuf_state = start_dbuff(dpy,
509 (colormap != 0)
510 ? colormap
511 : DefaultColormap(dpy,
512 DefaultScreen(dpy)),
513 ((colorSwitch) ? COLOR_SWITCH : PIXMAP_COPY),
514 num_planes,
515 colors);
516 }
517 if (dbuf_state == NULL && colormap == 0) {
518
519 /*
520 * Create a private colormap if we can't allocate enough colors.
521 */
522 Get_colormap();
523 Fill_colormap();
524
525 /*
526 * Try to initialize the double buffering again.
527 */
528
529 if (multibuffer) {
530 dbuf_state = start_dbuff(dpy, colormap,
531 MULTIBUFFER,
532 num_planes,
533 colors);
534 }
535
536 if (dbuf_state == NULL) {
537 dbuf_state = start_dbuff(dpy, colormap,
538 ((colorSwitch) ? COLOR_SWITCH : PIXMAP_COPY),
539 num_planes,
540 colors);
541 }
542 }
543
544 if (dbuf_state == NULL) {
545 /* Can't setup double buffering */
546 errno = 0;
547 error("Can't setup colors with visual %s and %d colormap entries",
548 Visual_class_name(visual->class), visual->map_entries);
549 return -1;
550 }
551
552 switch (dbuf_state->type) {
553 case COLOR_SWITCH:
554 printf("Using color switching\n");
555 break;
556
557 case PIXMAP_COPY:
558 printf("Using pixmap copying\n");
559 break;
560
561 case MULTIBUFFER:
562 #ifdef DBE
563 printf("Using double-buffering\n");
564 break;
565 #else
566 #ifdef MBX
567 printf("Using multi-buffering\n");
568 break;
569 #endif
570 #endif
571
572 default:
573 printf("Unknown dbuf state %d\n", dbuf_state->type);
574 exit(1);
575 }
576
577 for (i = maxColors; i < MAX_COLORS; i++) {
578 colors[i] = colors[i % maxColors];
579 }
580
581 Colors_init_radar_hack();
582
583 Colors_init_block_bitmaps();
584
585 return 0;
586 }
587
588
589 /*
590 * A little hack that enables us to draw on both sets of double buffering
591 * planes at once.
592 */
Colors_init_radar_hack(void)593 static void Colors_init_radar_hack(void)
594 {
595 int i, p;
596
597 for (p = 0; p < 2; p++) {
598 int num = 0;
599
600 dpl_1[p] = dpl_2[p] = 0;
601
602 for (i = 0; i < 32; i++) {
603 if (!((1 << i) & dbuf_state->drawing_plane_masks[p])) {
604 num++;
605 if (num == 1 || num == 3) {
606 dpl_1[p] |= 1<<i; /* planes with moving radar objects */
607 }
608 else {
609 dpl_2[p] |= 1<<i; /* constant map part of radar */
610 }
611 }
612 }
613 }
614 }
615
616
617 /*
618 * Setup color structures for use with drawing bitmaps.
619 *
620 * on error return -1,
621 * on success return 0.
622 */
Colors_init_block_bitmap_colors(void)623 static int Colors_init_block_bitmap_colors(void)
624 {
625 int r = -1;
626
627 switch (visual->class) {
628 case PseudoColor:
629 r = Colors_init_color_cube();
630 break;
631
632 case DirectColor:
633 /*
634 * I don't really understand the difference between
635 * DirectColor and TrueColor. Let's test if we can
636 * consider DirectColor to be similar to TrueColor.
637 */
638 /*FALLTHROUGH*/
639
640 case StaticColor:
641 case TrueColor:
642 r = Colors_init_true_color();
643 break;
644
645 case GrayScale:
646 case StaticGray:
647 /*
648 * Haven't implemented implemented bitmaps for gray colors yet.
649 */
650 /*FALLTHROUGH*/
651
652 default:
653 printf("blockBitmaps not implemented for visual \"%s\"\n",
654 Visual_class_name(visual->class));
655 blockBitmaps = false;
656 break;
657 }
658
659 return r;
660 }
661
662
663 /*
664 * See if we can use block bitmaps.
665 * If we can then setup the colors
666 * and allocate the bitmaps.
667 *
668 * on error return -1,
669 * on success return 0.
670 */
Colors_init_block_bitmaps(void)671 int Colors_init_block_bitmaps(void)
672 {
673 if (dbuf_state->type == COLOR_SWITCH) {
674 if (blockBitmaps) {
675 printf("Can't do blockBitmaps if colorSwitch\n");
676 blockBitmaps = false;
677 }
678 }
679 if (blockBitmaps) {
680 if (Colors_init_block_bitmap_colors() == -1) {
681 blockBitmaps = false;
682 }
683 }
684 if (blockBitmaps) {
685 if (Block_bitmaps_create() == -1) {
686 /*
687 ** not sure if this is possible after
688 ** blockbitmap colors have been created.
689 */
690 blockBitmaps = false;
691 }
692 }
693
694 return (blockBitmaps == true) ? 0 : -1;
695 }
696
697
698 /*
699 * Calculate a pixel from a RGB triplet for a PseudoColor visual.
700 */
RGB_PC(u_byte r,u_byte g,u_byte b)701 static unsigned long RGB_PC(u_byte r, u_byte g, u_byte b)
702 {
703 int i;
704
705 r = (r * color_cube->reds) >> 8;
706 g = (g * color_cube->greens) >> 8;
707 b = (b * color_cube->blues) >> 8;
708 i = (((r * color_cube->greens) + g) * color_cube->blues) + b;
709
710 return color_cube->pixels[i];
711 }
712
713
714 /*
715 * Calculate a pixel from a RGB triplet for a TrueColor visual.
716 */
RGB_TC(u_byte r,u_byte g,u_byte b)717 static unsigned long RGB_TC(u_byte r, u_byte g, u_byte b)
718 {
719 unsigned long pixel = 0;
720
721 pixel |= true_color->red_bits[r];
722 pixel |= true_color->green_bits[g];
723 pixel |= true_color->blue_bits[b];
724
725 return pixel;
726 }
727
728
729 /*
730 * Fill a color cube.
731 *
732 * Simple implementation for now.
733 * Make it more ambitious wrt. read-only cells later.
734 *
735 * Two ways to allocate colors for a RGB cube.
736 * One is to use the outer edges and sides for colors.
737 * Another is to divide the cube in r*g*b sub-cubes and
738 * choose the color in the centre of each sub-cube.
739 * The latter option looks better because it will most
740 * likely result in better color matches with on average
741 * less color distance.
742 */
Fill_color_cube(int reds,int greens,int blues,XColor colors[256])743 static void Fill_color_cube(int reds, int greens, int blues,
744 XColor colors[256])
745 {
746 int i, r, g, b;
747
748 i = 0;
749 for (r = 0; r < reds; r++) {
750 for (g = 0; g < greens; g++) {
751 for (b = 0; b < blues; b++, i++) {
752 colors[i].pixel = color_cube->pixels[i];
753 colors[i].flags = DoRed | DoGreen | DoBlue;
754 colors[i].red = (((r * 256) + 128) / reds) * 0x101;
755 colors[i].green = (((g * 256) + 128) / greens) * 0x101;
756 colors[i].blue = (((b * 256) + 128) / blues) * 0x101;
757 }
758 }
759 }
760
761 color_cube->reds = reds;
762 color_cube->greens = greens;
763 color_cube->blues = blues;
764 }
765
766
767 /*
768 * Allocate a color cube.
769 *
770 * Simple implementation for now.
771 * Make it more ambitious wrt. read-only cells later.
772 */
Colors_init_color_cube(void)773 static int Colors_init_color_cube(void)
774 {
775 int i, n, r, g, b;
776 XColor colors[256];
777
778 if (color_cube != NULL) {
779 error("Already a cube!\n");
780 exit(1);
781 }
782
783 color_cube = (struct Color_cube *) calloc(1, sizeof(struct Color_cube));
784 if (!color_cube) {
785 error("Could not allocate memory for a color cube");
786 return -1;
787 }
788 for (i = 0; i < NELEM(rgb_cube_sizes); i++) {
789
790 r = rgb_cube_sizes[i].r;
791 g = rgb_cube_sizes[i].g;
792 b = rgb_cube_sizes[i].b;
793 n = r * g * b;
794
795 if (XAllocColorCells(dpy,
796 (colormap != 0)
797 ? colormap
798 : DefaultColormap(dpy,
799 DefaultScreen(dpy)),
800 False, NULL, 0,
801 &color_cube->pixels[0],
802 n) == False) {
803 /*printf("Could not alloc %d colors for RGB cube\n", n);*/
804 continue;
805 }
806
807 printf("Got %d colors for a %d*%d*%d RGB cube\n",
808 n, r, g, b);
809
810 color_cube->mustfree = 1;
811
812 Fill_color_cube(r, g, b, &colors[0]);
813
814 XStoreColors(dpy,
815 (colormap != 0)
816 ? colormap
817 : DefaultColormap(dpy,
818 DefaultScreen(dpy)),
819 colors,
820 n);
821
822 RGB = RGB_PC;
823
824 return 0;
825 }
826
827 printf("Could not alloc colors for RGB cube\n");
828
829 return -1;
830 }
831
832
833 /*
834 * Free our color cube.
835 */
Colors_free_color_cube(void)836 static void Colors_free_color_cube(void)
837 {
838 if (color_cube) {
839 if (color_cube->mustfree) {
840 XFreeColors(dpy,
841 (colormap != 0)
842 ? colormap
843 : DefaultColormap(dpy,
844 DefaultScreen(dpy)),
845 &color_cube->pixels[0],
846 color_cube->reds * color_cube->greens * color_cube->blues,
847 0);
848 color_cube->mustfree = 0;
849 }
850 free(color_cube);
851 color_cube = NULL;
852 RGB = NULL;
853 }
854 }
855
856
857 /*
858 * Allocate and initialize a true color structure.
859 */
Colors_init_true_color(void)860 static int Colors_init_true_color(void)
861 {
862 int i, j, r, g, b;
863
864 if ((visual->red_mask == 0) ||
865 (visual->green_mask == 0) ||
866 (visual->blue_mask == 0) ||
867 ((visual->red_mask &
868 visual->green_mask &
869 visual->blue_mask) != 0)) {
870
871 printf("Your visual \"%s\" has weird characteristics:\n",
872 Visual_class_name(visual->class));
873 printf("\tred mask 0x%06lx, green mask 0x%06lx, blue mask 0x%06lx,\n",
874 visual->red_mask, visual->green_mask, visual->blue_mask);
875 printf("\toverlap mask 0x%06lx\n",
876 visual->red_mask & visual->green_mask & visual->blue_mask);
877 return -1;
878 }
879
880 if (true_color) {
881 error("Already a True_color!");
882 exit(1);
883 }
884
885 true_color = (struct True_color *) calloc(1, sizeof(struct True_color));
886 if (!true_color) {
887 error("Could not allocate memory for a true color structure");
888 return -1;
889 }
890
891 r = 7;
892 g = 7;
893 b = 7;
894 for (i = 31; i >= 0; --i) {
895 if ((visual->red_mask & (1UL << i)) != 0) {
896 if (r >= 0) {
897 for (j = 0; j < 256; j++) {
898 if (j & (1 << r)) {
899 true_color->red_bits[j] |= (1UL << i);
900 }
901 }
902 r--;
903 }
904 }
905 if ((visual->green_mask & (1UL << i)) != 0) {
906 if (g >= 0) {
907 for (j = 0; j < 256; j++) {
908 if (j & (1 << g)) {
909 true_color->green_bits[j] |= (1UL << i);
910 }
911 }
912 g--;
913 }
914 }
915 if ((visual->blue_mask & (1UL << i)) != 0) {
916 if (b >= 0) {
917 for (j = 0; j < 256; j++) {
918 if (j & (1 << b)) {
919 true_color->blue_bits[j] |= (1UL << i);
920 }
921 }
922 b--;
923 }
924 }
925 }
926
927 RGB = RGB_TC;
928
929 return 0;
930 }
931
932
933 /*
934 * Free a true color structure.
935 */
Colors_free_true_color(void)936 static void Colors_free_true_color(void)
937 {
938 if (true_color) {
939 free(true_color);
940 true_color = NULL;
941 RGB = NULL;
942 }
943 }
944
945
946 /*
947 * Deallocate everything related to colors.
948 */
Colors_free_block_bitmaps(void)949 void Colors_free_block_bitmaps(void)
950 {
951 Colors_free_color_cube();
952 Colors_free_true_color();
953
954 if (blockBitmaps) {
955
956 blockBitmaps = false;
957 }
958 }
959
960
961 /*
962 * Deallocate everything related to colors.
963 */
Colors_cleanup(void)964 void Colors_cleanup(void)
965 {
966 Colors_free_block_bitmaps();
967
968 if (dbuf_state) {
969 end_dbuff(dbuf_state);
970 dbuf_state = NULL;
971 }
972 if (colormap) {
973 XFreeColormap(dpy, colormap);
974 colormap = 0;
975 }
976 }
977
978
979 #ifdef DEVELOPMENT
Colors_debug(void)980 void Colors_debug(void)
981 {
982 int i, n, r, g, b;
983 XColor colors[256];
984 FILE *fp = fopen("rgb", "w");
985
986 if (!color_cube) {
987 static struct Color_cube cc;
988 color_cube = &cc;
989 for (i = 0; i < 256; i++) {
990 cc.pixels[i] = i;
991 }
992 }
993
994 for (i = 0; i < NELEM(rgb_cube_sizes); i++) {
995
996 r = rgb_cube_sizes[i].r;
997 g = rgb_cube_sizes[i].g;
998 b = rgb_cube_sizes[i].b;
999 n = r * g * b;
1000
1001 Fill_color_cube(r, g, b, colors);
1002
1003 fprintf(fp, "\n\n RGB %d %d %d\n\n", r, g, b);
1004 i = 0;
1005 for (r = 0; r < color_cube->reds; r++) {
1006 for (g = 0; g < color_cube->greens; g++) {
1007 for (b = 0; b < color_cube->blues; b++, i++) {
1008 fprintf(fp, "color %4d %04X %04X %04X\n",
1009 i, colors[i].red, colors[i].green, colors[i].blue);
1010 }
1011 }
1012 }
1013 fprintf(fp, "\nblack %3lu\nwhite %3lu\nred %3lu\ngreen %3lu\nblue %3lu\n",
1014 RGB_PC(0, 0, 0),
1015 RGB_PC(255, 255, 255),
1016 RGB_PC(255, 0, 0),
1017 RGB_PC(0, 255, 0),
1018 RGB_PC(0, 0, 255));
1019 }
1020
1021 fclose(fp);
1022
1023 exit(1);
1024 }
1025 #endif /* DEVELOPMENT */
1026
1027
1028 #endif /* _WINDOWS */
1029