550N/A/*
1515N/A* Copyright (c) 1990, 2015, Oracle and/or its affiliates. All rights reserved.
550N/A*
550N/A* Permission is hereby granted, free of charge, to any person obtaining a
919N/A* copy of this software and associated documentation files (the "Software"),
919N/A* to deal in the Software without restriction, including without limitation
919N/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:
550N/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.
550N/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.
550N/A*
550N/A*/
550N/A
550N/A
550N/A#include <stdio.h>
550N/A#ifndef SYSV
550N/A#include <alloca.h>
550N/A#endif
550N/A#include <X11/Xlib.h>
1233N/A#include <X11/Xlibint.h>
550N/A#include "cmc.h"
550N/A#include "cmcutil.h"
550N/A
550N/A#define CELL_IGNORE 0
550N/A#define CELL_READONLY 1
550N/A
550N/A
550N/A/*
550N/A** Handle I/O errors when opening display
550N/A*/
550N/A
550N/Astatic int badaccess_error;
550N/A
550N/A/*
550N/A** Handle X request errors.
550N/A** Just set a flag to let the routine making an X
550N/A** call know that the call resulted in a BadAccess error.
550N/A** Any other errors are processed normally.
550N/A*/
550N/A
1233N/Astatic int
1233N/Abad_handler (
1233N/A Display *dpy,
1233N/A XErrorEvent *err)
550N/A{
550N/A if (err->error_code == BadAccess)
550N/A badaccess_error = 1;
550N/A else
1233N/A return _XDefaultError(dpy,err);
1233N/A return 0;
550N/A}
550N/A
550N/A
550N/A/*
550N/A** Examines the given colormap to determine the number of
550N/A** read-only cells, their locations, and their color values.
550N/A**
550N/A** All non-read-only cells (privately allocated, unallocated
550N/A** or reserved) are ignored.
550N/A*/
550N/A
550N/Astatic void
1515N/Acmc_record (
1515N/A Screen *screen,
1515N/A int *ncolors,
1515N/A XColor **colors)
550N/A{
550N/A register Colormap cmap = DefaultColormapOfScreen(screen);
550N/A register int i, nalloc;
550N/A register int *p;
550N/A register XColor *c;
550N/A int totalpix;
1233N/A unsigned long masks; /* NOTUSED */
550N/A Pixel *pixels;
550N/A int *pixtype;
550N/A XColor color;
550N/A
550N/A /* start out assuming all are read-only */
550N/A totalpix = 1<<PlanesOfScreen(screen);
550N/A
550N/A /* allocate local scratch memory */
550N/A#ifdef SYSV
550N/A if (!(pixels = (Pixel *) malloc(totalpix * sizeof(Pixel))))
550N/A fatal_error("cannot allocate memory ");
550N/A if (!(pixtype = (int *) malloc(totalpix * sizeof(Pixel))))
550N/A fatal_error("cannot allocate memory ");
550N/A#else
550N/A if (!(pixels = (Pixel *) alloca(totalpix * sizeof(Pixel))))
550N/A fatal_error("cannot allocate memory on stack");
550N/A if (!(pixtype = (int *) alloca(totalpix * sizeof(Pixel))))
550N/A fatal_error("cannot allocate memory on stack");
550N/A#endif
550N/A for (i=0, p=pixtype; i<totalpix; i++, p++)
550N/A *p = CELL_READONLY;
550N/A *ncolors = totalpix;
550N/A
550N/A /*
550N/A ** First, find the free cells by allocating them all private.
550N/A ** We allocate by decreasing powers of 2 so the allocation
550N/A ** time will be proportional to the number of display planes
550N/A ** instead of the number of display cells.
550N/A **
550N/A ** Mark the free cells we find. These allocations will
550N/A ** be freed when the connection is closed.
550N/A */
550N/A for (nalloc=totalpix; nalloc > 0; nalloc >>= 1) {
550N/A if(!XAllocColorCells(DisplayOfScreen(screen), cmap, 0, &masks, 0,
550N/A pixels, nalloc))
550N/A continue;
550N/A for (i=0; i<nalloc; i++) {
550N/A pixtype[pixels[i]] = CELL_IGNORE;
550N/A }
550N/A *ncolors -= nalloc;
550N/A }
550N/A
550N/A /*
550N/A ** Find the read-only cells (excluding white/black).
550N/A **
550N/A ** Get the Hardware color for the color of each allocated cell.
550N/A ** This can only work if the returned color is a previously
550N/A ** allocated r/o cell (we have all cells allocated).
550N/A */
550N/A XSetErrorHandler(bad_handler);
550N/A for(i=0, p=pixtype; i<totalpix; i++, p++) {
550N/A if(*p != CELL_IGNORE) {
550N/A color.pixel = i;
550N/A
550N/A /* Eliminate reserved cells */
550N/A badaccess_error = 0;
550N/A XQueryColor(DisplayOfScreen(screen), cmap, &color);
550N/A XSync(DisplayOfScreen(screen), 0); /* make sure any error is reported */
550N/A if (badaccess_error) {
550N/A pixtype[color.pixel] = CELL_IGNORE;
550N/A (*ncolors)--;
550N/A } else {
550N/A badaccess_error = 0;
550N/A XStoreColor(DisplayOfScreen(screen), cmap, &color);
550N/A if (!badaccess_error) {
550N/A /* Eliminate read/write cells */
550N/A pixtype[color.pixel] = CELL_IGNORE;
550N/A (*ncolors)--;
550N/A } else if (WHITE(&color) || BLACK(&color)) {
550N/A /* Eliminate white/black cells */
550N/A pixtype[color.pixel] = CELL_IGNORE;
550N/A (*ncolors)--;
550N/A }
550N/A /* else if alloc succeeded, it must be read-only */
550N/A }
550N/A }
550N/A }
550N/A XSync(DisplayOfScreen(screen), 0);
550N/A XSetErrorHandler(NULL);
550N/A
550N/A /* allocate the memory for the read-only cells */
550N/A if (!(*colors = (XColor *) calloc(*ncolors, sizeof(XColor))))
550N/A fatal_error("not enough memory");
550N/A
550N/A /*
550N/A ** Get the color values for the read-only cells, ignoring private
550N/A ** cells, reserved cells, and white/black.
550N/A */
550N/A for (i=0, c=*colors; i<totalpix; i++) {
550N/A if (pixtype[i] != CELL_IGNORE) {
550N/A (c++)->pixel = i;
550N/A }
550N/A }
550N/A XQueryColors(DisplayOfScreen(screen), cmap, *colors, *ncolors);
550N/A#ifdef SYSV
550N/A free(pixels);
550N/A free(pixtype);
550N/A#endif
550N/A}
550N/A
550N/A
550N/A/*
550N/A** Examines the default colormap with the server grabbed
550N/A** to prevent changes during the examination process.
550N/A*/
550N/A
550N/Astatic void
1515N/Acmc_record_protected (
1515N/A Screen *screen,
1515N/A int *ncolors,
1515N/A XColor **colors)
550N/A{
550N/A XGrabServer(DisplayOfScreen(screen));
550N/A cmc_record(screen, ncolors, colors);
550N/A XUngrabServer(DisplayOfScreen(screen));
550N/A}
550N/A
550N/A
550N/A/*
550N/A** For each screen for which the default colormap is dynamic indexed
550N/A** record all read-only color cells in the default colormap.
550N/A*/
550N/A
550N/Avoid
1515N/Acmc_save (void)
550N/A{
550N/A register int scr_num;
550N/A Display *dpy;
550N/A FILE *f;
1233N/A const char *filename;
550N/A
550N/A /* Open display */
550N/A if (!(dpy = open_display(display_name)))
550N/A fatal_error("cannot open display '%s'", display_name);
550N/A
550N/A /* For some strange reason, colorscells_get_protected fails if not
550N/A run synchronously */
550N/A XSynchronize(dpy, 1);
550N/A
550N/A /* Open file to save in */
1233N/A filename = comp_colors_filename(basename_arg);
550N/A if ((f = fopen(filename, "w")) == NULL)
550N/A fatal_error("cannot open file '%s' for writing", filename);
550N/A
550N/A /* Save magic number and version */
550N/A cmc_header_write(f);
550N/A
550N/A /* For each screen of display ... */
550N/A for (scr_num = 0; scr_num < ScreenCount(dpy); scr_num++) {
550N/A Screen *screen = ScreenOfDisplay(dpy, scr_num);
550N/A int ncolors;
550N/A XColor *colors;
550N/A
550N/A /* Do nothing if default visual is not dynamic */
550N/A if (!dynamic_indexed_default_visual(screen)) {
1233N/A if (warn_flag) {
550N/A warning("default visual for screen %d is not dynamic indexed",
550N/A scr_num);
550N/A warning("no colors saved for screen %d", scr_num );
550N/A }
550N/A continue;
550N/A }
550N/A
550N/A /*
550N/A ** Discover what read-only cells are in the default colormap.
550N/A **
550N/A ** These will be considered the "workspace colors."
550N/A */
550N/A cmc_record_protected(screen, &ncolors, &colors);
550N/A
550N/A /* Save read-only cells for screen in workspace color file */
550N/A if (!cmc_write(f, scr_num, ncolors, colors))
550N/A fatal_error("cannot write to file %s", filename);
550N/A
550N/A free((char *)colors);
550N/A }
550N/A
550N/A XCloseDisplay(dpy);
550N/A}
550N/A
550N/A
550N/A