-
- #if 0
- for (i=max_cmap_entries-1; i>=free_cmap_entries; i--)
-
- #else
- for (i=max_cmap_entries-1; i>=0; i--)
- {
- /*
- if (!pixel_used[i])
- continue;
- */
- #endif
-
- xcolor2.pixel = *(our_default_index + i);
-
- #if 0
- XQueryColor(disp, ximageinfo->cmap, &xcolor2);
- #else
- xcolor2 = xcolor_used[xcolor2.pixel];
- #endif
-
- if ((xcolor.red >> 8) == (xcolor2.red >> 8) &&
- (xcolor.green >> 8) == (xcolor2.green >> 8) &&
- (xcolor.blue >> 8) == (xcolor2.blue >> 8))
- break;
- }
-
- use_cmap_entry = i;
-
- if (0 && use_cmap_entry < free_cmap_entries) /* not found in colormap */
- {
- free_cmap_entries--;
- }
- else if (0 && use_cmap_entry < free_cmap_entries) /* not found in colormap */
- {
- }
- else if (use_cmap_entry < 0) /* not found in colormap */
- {
- /* look for an existing 'unused' color near the one we want */
-
- for (i=free_cmap_entries-1; i>=0; i--)
- {
- int closeness = 14;
-
- if (pixel_used[i])
- continue;
-
- xcolor2.pixel = *(our_default_index + i);
-
- #if 0
- XQueryColor(disp, ximageinfo->cmap, &xcolor2);
- #else
- xcolor2 = xcolor_used[xcolor2.pixel];
- #endif
-
-
- if ((xcolor.red >> closeness) == (xcolor2.red >> closeness) &&
- (xcolor.green >> closeness) == (xcolor2.green >> closeness) &&
- (xcolor.blue >> closeness) == (xcolor2.blue >> closeness))
- break;
- }
-
- use_cmap_entry = i;
-
- if (use_cmap_entry < 0) /* no 'near' color found */
- {
- /* look for the next free color */
-
- while (pixel_used[--free_cmap_entries])
- ;
- use_cmap_entry = free_cmap_entries;
- }
- }
-
- if (free_cmap_entries < 0)
- {
- printf("imageToXImage: too many global colors!\n");
- exit(0);
- }
-
-
- /*
- printf("--> eating color %d\n", use_cmap_entry);
- */
-
-
-
- xcolor.pixel = use_cmap_entry;
-
- xcolor_used[xcolor.pixel] = xcolor;
-
- *(ximageinfo->index + a) = xcolor.pixel;
-
- XStoreColor(disp, ximageinfo->cmap, &xcolor);
-
- pixel_used[use_cmap_entry] = 1;
+ if (!XAllocColor(disp, ximageinfo->cmap, &xcolor))
+ {
+ if (!private_cmap)
+ {
+ /*
+ printf("switching to private colormap...\n");
+ */
+
+ /* we just filled up the default colormap -- get a private one
+ which contains all already allocated colors */
+
+ global_cmap = XCopyColormapAndFree(disp, global_cmap);
+ ximageinfo->cmap = global_cmap;
+ private_cmap = TRUE;
+
+ /* allocate the rest of the color cells read/write */
+ global_cmap_index =
+ (Pixel *)lmalloc(sizeof(Pixel) * NOFLASH_COLORS);
+ for (i=0; i<NOFLASH_COLORS; i++)
+ if (!XAllocColorCells(disp, global_cmap, FALSE, NULL, 0,
+ global_cmap_index + i, 1))
+ break;
+ num_cmap_entries = free_cmap_entries = i;
+
+ /*
+ printf("We've got %d free colormap entries.\n", free_cmap_entries);
+ */
+
+ /* to minimize colormap flashing, copy default colors and try
+ to keep them as near as possible to the old values */
+
+ for(i=0; i<num_cmap_entries; i++)
+ {
+ xcolor2.pixel = *(global_cmap_index + i);
+ XQueryColor(disp, DefaultColormap(disp, scrn), &xcolor2);
+ XStoreColor(disp, global_cmap, &xcolor2);
+ xcolor_private[xcolor2.pixel] = xcolor2;
+ colorcell_used[xcolor2.pixel] = FALSE;
+ }
+
+ /* now we have the default colormap private: all colors we
+ successfully allocated so far are read-only, which is okay,
+ because we don't want to change them anymore -- if we need
+ an existing color again, we get it by XAllocColor; all other
+ colors are read/write and we can set them by XStoreColor,
+ but we will try to overwrite those color cells with our new
+ color which are as close as possible to our new color */
+ }
+
+ /* look for an existing default color close the one we want */
+
+ mask = 0xf000;
+ color_found = FALSE;
+
+ while (!color_found)
+ {
+ for (i=num_cmap_entries-1; i>=0; i--)
+ {
+ xcolor2.pixel = *(global_cmap_index + i);
+ xcolor2 = xcolor_private[xcolor2.pixel];
+
+ if (colorcell_used[xcolor2.pixel])
+ continue;
+
+ if ((xcolor.red & mask) == (xcolor2.red & mask) &&
+ (xcolor.green & mask) == (xcolor2.green & mask) &&
+ (xcolor.blue & mask) == (xcolor2.blue & mask))
+ {
+ /*
+ printf("replacing color cell %ld with a close color\n",
+ xcolor2.pixel);
+ */
+ color_found = TRUE;
+ break;
+ }
+ }
+
+ if (mask == 0x0000)
+ break;
+
+ mask = (mask << 1) & 0xffff;
+ }
+
+ if (!color_found) /* no more free color cells */
+ {
+ printf("Sorry, cannot allocate enough colors!\n");
+ exit(0);
+ }
+
+ xcolor.pixel = xcolor2.pixel;
+ xcolor_private[xcolor.pixel] = xcolor;
+ colorcell_used[xcolor.pixel] = TRUE;
+ XStoreColor(disp, ximageinfo->cmap, &xcolor);
+ free_cmap_entries--;
+ }
+
+ *(ximageinfo->index + a) = xcolor.pixel;