open-src/app/cmap_compact/sun-src/cmcinit.c
author X gate hg captive account <xhg@xserver.us.oracle.com>
Wed, 19 Aug 2015 13:48:41 -0700
changeset 1484 bc8922b8e1d2
parent 1233 1134c9fd2fe6
permissions -rw-r--r--
Added tag s11u3_30 for changeset 221e9d9cc9cb

/*
* Copyright (c) 1990, 2011, Oracle and/or its affiliates. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*/


#include <stdio.h>
#ifndef SYSV
#include <alloca.h>
#endif
#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include "cmc.h"
#include "cmcutil.h"

#define MIN(a,b)	((a)<(b)?(a):(b))


static void
cmc_alloc (
    Screen	*screen,
    int		ncolors,
    XColor	*colors)

{
	register Colormap cmap = DefaultColormapOfScreen(screen);
	register Pixel  *p;
	register XColor	*c;
	register int	nalloc;
	register int	total_alloc = 0;
	register int	ntotal;
	unsigned long	mask;
	Pixel		*pixels;
	int		nc;

	ntotal = 1<<PlanesOfScreen(screen);
#ifdef SYSV
	pixels = (Pixel *) malloc(ntotal * sizeof(Pixel));
#else
	pixels = (Pixel *) alloca(ntotal * sizeof(Pixel));
#endif

	/* Grab as many private cells as we can */
	for (nalloc=ntotal, p=pixels;  nalloc > 0; nalloc>>=1) {
		if (!XAllocColorCells(DisplayOfScreen(screen), cmap, 0, &mask, 0, 
				p, nalloc))
		        continue;
		p += nalloc;
		total_alloc += nalloc;
	}

	/* 
	** May not be able to get as many colors as requested.
	*/	
	nc = MIN(ncolors, total_alloc);
	if (nc != ncolors) {
	    (void) fprintf(stderr, "Warning: can only allocate %d of the requested %d colors.\n", nc, ncolors);
	    (void) fprintf(stderr, "Continuing anyway.\n");
        }
	ncolors = nc;

	/* Free enough space for workspace colors */
	nalloc = total_alloc - ncolors;
	XFreeColors(DisplayOfScreen(screen), cmap, pixels+nalloc, ncolors, 0);

	/* Allocate the workspace colors */
	for (c=colors+ncolors-1; c>=colors; c--)
		if (!XAllocColor(DisplayOfScreen(screen), cmap, c)) 
			fatal_error("attempt to allocate color failed");

	/* Free placeholder pixels */
	XFreeColors(DisplayOfScreen(screen), cmap, pixels, nalloc, 0);

	/* 
	** Tell everybody how many workspace colors there are.
	** Be sure to include white/black if they're at the
	** high end.
	*/
	{ Visual *vis = DefaultVisualOfScreen(screen);
	  int    cmap_size = vis->map_entries;
	  if (WhitePixelOfScreen(screen) == cmap_size-1 ||
	      WhitePixelOfScreen(screen) == cmap_size-2)
		ncolors++;
	  if (BlackPixelOfScreen(screen) == cmap_size-1 ||
	      BlackPixelOfScreen(screen) == cmap_size-2)
		ncolors++;
	  prop_update(DisplayOfScreen(screen), RootWindowOfScreen(screen), 
			COUNT_PROP_NAME, XA_INTEGER, 32, ncolors, 1);
	}
#ifdef SYSV
	free(pixels);
#endif
}


static void
cmc_alloc_protected (screen, ncolors, colors)
Screen	*screen;
int	ncolors;
XColor	*colors;

{
	XGrabServer(DisplayOfScreen(screen));
	cmc_alloc(screen, ncolors, colors);
	XUngrabServer(DisplayOfScreen(screen));
}


/*
** For each screen for which there is saved workspace colors,
** allocates these colors as high as possible in the default
** colormap of the screen.
*/

void
cmc_init (void)

{
	Display		*dpy;
	FILE		*f;
	const char	*filename;

	/* Open display */
	if (!(dpy = open_display(display_name))) 
		fatal_error("cannot open display '%s'\n", display_name);

	/* For some strange reason, cmc_alloc_protected fails if not
	   run synchronously */
	XSynchronize(dpy, 1);

	/* Open file where workspace colors are stored */
	filename = comp_colors_filename(basename_arg);	
	if ((f = fopen(filename, "r")) == NULL) 
		/* Do nothing if not found */
		return;
		
	/* Check magic number and version */
	cmc_header_test(f);

	/* Abandon any previously allocated workspace colors (all screens) */
	resource_discard(dpy);

	/* For each screen of display ... */
	for (;;) {
		Screen  *screen;
		int	scr_num;
		int	ncolors;
		XColor	*colors;

		if (!cmc_read(f, &scr_num, &ncolors, &colors))
			break;

		/* See if screen is still present */
		if (scr_num >= ScreenCount(dpy)) {
			warning("Warning: cannot allocated saved colors for screen %d because\nthe display no longer has this many screens\n", scr_num);
			continue;
		}
		screen = ScreenOfDisplay(dpy, scr_num);

		/* 
		** Existence of workspace colors for the screen implies
		** that its default visual was dynamic indexed.   Make sure
		** it still is.
		*/
		if (!dynamic_indexed_default_visual(screen)) {
			warning("default visual for screen %d is no longer dynamic indexed\nsaved colors not allocated for screen %d", scr_num, scr_num);
			continue;
		}

		/* Allocate workspace colors at high end of colormap */
		cmc_alloc_protected(screen, ncolors, colors);
		free((char *)colors);
	}

	/* Preserve newly allocated client resources */
	resource_preserve(dpy);

	XCloseDisplay(dpy);
}