98N/A/*
98N/A* Copyright (c) 1990, 2011, Oracle and/or its affiliates. All rights reserved.
98N/A*
98N/A* Permission is hereby granted, free of charge, to any person obtaining a
1381N/A* copy of this software and associated documentation files (the "Software"),
98N/A* to deal in the Software without restriction, including without limitation
98N/A* the rights to use, copy, modify, merge, publish, distribute, sublicense,
919N/A* and/or sell copies of the Software, and to permit persons to whom the
919N/A* Software is furnished to do so, subject to the following conditions:
919N/A*
919N/A* The above copyright notice and this permission notice (including the next
919N/A* paragraph) shall be included in all copies or substantial portions of the
919N/A* Software.
919N/A*
919N/A* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
919N/A* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
919N/A* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
919N/A* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
919N/A* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
919N/A* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
919N/A* DEALINGS IN THE SOFTWARE.
919N/A*
919N/A*/
919N/A
98N/A
98N/A#include <stdio.h>
98N/A#ifndef SYSV
98N/A#include <alloca.h>
493N/A#endif
98N/A#include <X11/Xlib.h>
98N/A#include <X11/Xlibint.h>
1381N/A#include "cmc.h"
98N/A#include "cmcutil.h"
911N/A
1381N/A#define CELL_IGNORE 0
1381N/A#define CELL_READONLY 1
1381N/A
911N/A
98N/A/*
1381N/A** Handle I/O errors when opening display
523N/A*/
98N/A
98N/Astatic int badaccess_error;
98N/A
98N/A/*
98N/A** Handle X request errors.
493N/A** Just set a flag to let the routine making an X
969N/A** call know that the call resulted in a BadAccess error.
98N/A** Any other errors are processed normally.
970N/A*/
970N/A
970N/Astatic int
970N/Abad_handler (
98N/A Display *dpy,
493N/A XErrorEvent *err)
705N/A{
523N/A if (err->error_code == BadAccess)
98N/A badaccess_error = 1;
98N/A else
98N/A return _XDefaultError(dpy,err);
98N/A return 0;
98N/A}
493N/A
98N/A
536N/A/*
536N/A** Examines the given colormap to determine the number of
536N/A** read-only cells, their locations, and their color values.
729N/A**
965N/A** All non-read-only cells (privately allocated, unallocated
729N/A** or reserved) are ignored.
98N/A*/
98N/A
static void
cmc_record (screen, ncolors, colors)
Screen *screen;
int *ncolors;
XColor **colors;
{
register Colormap cmap = DefaultColormapOfScreen(screen);
register int i, nalloc;
register int *p;
register XColor *c;
int totalpix;
unsigned long masks; /* NOTUSED */
Pixel *pixels;
int *pixtype;
XColor color;
/* start out assuming all are read-only */
totalpix = 1<<PlanesOfScreen(screen);
/* allocate local scratch memory */
#ifdef SYSV
if (!(pixels = (Pixel *) malloc(totalpix * sizeof(Pixel))))
fatal_error("cannot allocate memory ");
if (!(pixtype = (int *) malloc(totalpix * sizeof(Pixel))))
fatal_error("cannot allocate memory ");
#else
if (!(pixels = (Pixel *) alloca(totalpix * sizeof(Pixel))))
fatal_error("cannot allocate memory on stack");
if (!(pixtype = (int *) alloca(totalpix * sizeof(Pixel))))
fatal_error("cannot allocate memory on stack");
#endif
for (i=0, p=pixtype; i<totalpix; i++, p++)
*p = CELL_READONLY;
*ncolors = totalpix;
/*
** First, find the free cells by allocating them all private.
** We allocate by decreasing powers of 2 so the allocation
** time will be proportional to the number of display planes
** instead of the number of display cells.
**
** Mark the free cells we find. These allocations will
** be freed when the connection is closed.
*/
for (nalloc=totalpix; nalloc > 0; nalloc >>= 1) {
if(!XAllocColorCells(DisplayOfScreen(screen), cmap, 0, &masks, 0,
pixels, nalloc))
continue;
for (i=0; i<nalloc; i++) {
pixtype[pixels[i]] = CELL_IGNORE;
}
*ncolors -= nalloc;
}
/*
** Find the read-only cells (excluding white/black).
**
** Get the Hardware color for the color of each allocated cell.
** This can only work if the returned color is a previously
** allocated r/o cell (we have all cells allocated).
*/
XSetErrorHandler(bad_handler);
for(i=0, p=pixtype; i<totalpix; i++, p++) {
if(*p != CELL_IGNORE) {
color.pixel = i;
/* Eliminate reserved cells */
badaccess_error = 0;
XQueryColor(DisplayOfScreen(screen), cmap, &color);
XSync(DisplayOfScreen(screen), 0); /* make sure any error is reported */
if (badaccess_error) {
pixtype[color.pixel] = CELL_IGNORE;
(*ncolors)--;
} else {
badaccess_error = 0;
XStoreColor(DisplayOfScreen(screen), cmap, &color);
if (!badaccess_error) {
/* Eliminate read/write cells */
pixtype[color.pixel] = CELL_IGNORE;
(*ncolors)--;
} else if (WHITE(&color) || BLACK(&color)) {
/* Eliminate white/black cells */
pixtype[color.pixel] = CELL_IGNORE;
(*ncolors)--;
}
/* else if alloc succeeded, it must be read-only */
}
}
}
XSync(DisplayOfScreen(screen), 0);
XSetErrorHandler(NULL);
/* allocate the memory for the read-only cells */
if (!(*colors = (XColor *) calloc(*ncolors, sizeof(XColor))))
fatal_error("not enough memory");
/*
** Get the color values for the read-only cells, ignoring private
** cells, reserved cells, and white/black.
*/
for (i=0, c=*colors; i<totalpix; i++) {
if (pixtype[i] != CELL_IGNORE) {
(c++)->pixel = i;
}
}
XQueryColors(DisplayOfScreen(screen), cmap, *colors, *ncolors);
#ifdef SYSV
free(pixels);
free(pixtype);
#endif
}
/*
** Examines the default colormap with the server grabbed
** to prevent changes during the examination process.
*/
static void
cmc_record_protected (screen, ncolors, colors)
Screen *screen;
int *ncolors;
XColor **colors;
{
XGrabServer(DisplayOfScreen(screen));
cmc_record(screen, ncolors, colors);
XUngrabServer(DisplayOfScreen(screen));
}
/*
** For each screen for which the default colormap is dynamic indexed
** record all read-only color cells in the default colormap.
*/
void
cmc_save ()
{
register int scr_num;
Display *dpy;
FILE *f;
const char *filename;
/* Open display */
if (!(dpy = open_display(display_name)))
fatal_error("cannot open display '%s'", display_name);
/* For some strange reason, colorscells_get_protected fails if not
run synchronously */
XSynchronize(dpy, 1);
/* Open file to save in */
filename = comp_colors_filename(basename_arg);
if ((f = fopen(filename, "w")) == NULL)
fatal_error("cannot open file '%s' for writing", filename);
/* Save magic number and version */
cmc_header_write(f);
/* For each screen of display ... */
for (scr_num = 0; scr_num < ScreenCount(dpy); scr_num++) {
Screen *screen = ScreenOfDisplay(dpy, scr_num);
int ncolors;
XColor *colors;
/* Do nothing if default visual is not dynamic */
if (!dynamic_indexed_default_visual(screen)) {
if (warn_flag) {
warning("default visual for screen %d is not dynamic indexed",
scr_num);
warning("no colors saved for screen %d", scr_num );
}
continue;
}
/*
** Discover what read-only cells are in the default colormap.
**
** These will be considered the "workspace colors."
*/
cmc_record_protected(screen, &ncolors, &colors);
/* Save read-only cells for screen in workspace color file */
if (!cmc_write(f, scr_num, ncolors, colors))
fatal_error("cannot write to file %s", filename);
free((char *)colors);
}
XCloseDisplay(dpy);
}